1. 流的概述
- C++流是读写(输入和输出)逻辑的通用实现,让您能够用统一的模式读写数据
- 不管是磁盘或键盘读取数据,还是将输入写入显示器或磁盘,这些模式都相同
- 您只需使用合适的流类,类的实现将负责处理与设备和操作系统相关的细节
- std:cout 是 ostream 类的一个对象,用于输出到控制台,std::cin 让您能够从流中读取数据
- 如果要将 Hello World 写入文本文件,可将同样的语法用于文件流对象 fsHello
fsHello << "Hello World!" << endl;
2. 重要的 C++ 流类和流对象
- std命名空间中常用的C++流类
类/对象 | 用途 |
---|---|
cout | 标准输出流,通常被重定向到控制台 |
cin | 标准输入流,通常用于将数据读入变量 |
cerr | 用于显示错误信息的标准输出流 |
fstream | 用于操作文件的输入和输出流,继承了ofstream 和ifstream |
ofstream | 用于操作文件的输出流类,即用于创建文件 |
ifstream | 用于操作文件的输入流类,即用于读取文件 |
stringstream | 用于操作字符串的输入和输出流类,继承了istringstream 和ostringstream,通常用于在字符串和其他类型之间进行转换 |
- cout、cin 和 cerr 分别是流类 ostream、istream 和 ostream 的全局对象,由于是全局对象,它们在 main() 开始之前就已初始化
- std命名空间中常用于流的控制符
类/对象 | 用途 |
---|---|
输出控制符 | |
endl | 插入一个换行符 |
ends | 插入一个空字符 |
基数控制符 | |
dec | 让流以十进制方式解释输入或显示输出 |
hex | 让流以十六进制方式解释输入或显示输出 |
oct | 让流以八进制方式解释输入或显示输出 |
浮点数表示控制符 | |
fixed | 让流以定点表示法显示数据 |
scientific | 让流以科学表示法显示数据 |
<iomanip>控制符 | |
setprecision | 设置小数精度 |
setw | 设置字段宽度 |
setfill | 设置填充字符 |
setbase | 设置基数,与使用dec、hex 或oct 等效 |
setiosflag | 通过类型为std::ios_base::fmtflags 的掩码输入参数设置标志 |
resetiosflag | 将std::ios_base::fmtflags 参数指定的标志重置为默认值 |
3. 使用std::cout 将指定格式的数据写入控制台
3.1 使用std::cout 修改数字的显示格式
- 使用 cout 和 <iomanip> 控制符以十进制、十六进制和八进制格式显示整数
#include <iostream>
#include <iomanip>
using namespace std;
int main(){
cout << "Enter an integer: ";
int input = 0;
cin >> input;
cout << "Integer in octal: " << oct << input << endl;
cout << "Integer in hexadecimal: " << hex << input << endl;
cout << "Integer in hex using base notation: ";
cout<<setiosflags(ios_base::hex|ios_base::showbase|ios_base::uppercase);
cout << input << endl;
cout << "Integer after resetting I/O flags: ";
cout<<resetiosflags(ios_base::hex|ios_base::showbase|ios_base::uppercase);
cout << input << endl;
return 0;
}
- 使用 cout 以定点表示法和科学表示法显示Pi 和圆面积
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
const double Pi = (double)22.0 / 7;
cout << "Pi = " << Pi << endl;
cout << endl << "Setting precision to 7: " << endl;
cout << setprecision(7);
cout << "Pi = " << Pi << endl;
cout << fixed << "Fixed Pi = " << Pi << endl;
cout << scientific << "Scientific Pi = " << Pi << endl;
cout << endl << "Setting precision to 10: " << endl;
cout << setprecision(10);
cout << "Pi = " << Pi << endl;
cout << fixed << "Fixed Pi = " << Pi << endl;
cout << scientific << "Scientific Pi = " << Pi << endl;
cout << endl << "Enter a radius: ";
double radius = 0.0;
cin >> radius;
cout << "Area of circle: " << 2*Pi*radius*radius << endl;
return 0;
}
3.2 使用std::cout 对齐文本和设置字段宽度
- 可使用 setw() 控制符来设置字段宽度,插入到流中的内容将在指定宽度内右对齐
- 在这种情况下,还可使用 setfill() 指定使用什么字符来填充空白区域
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
cout << "Hey - default!" << endl;
cout << setw(35);
cout << "Hey - right aligned!" << endl;
cout << setw(35) << setfill('*');
cout << "Hey - right aligned!" << endl;
cout << "Hey - back to default!" << endl;
return 0;
}
4. 使用std::cin 进行输入
4.1 使用std::cin 将输入读取到基本类型变量中
- 使用 cin 将输入读取到 int 变量中,将使用科学表示法的浮点数读取到 double 变量中,将三个字符分别读取到 char 变量中
#include<iostream>
using namespace std;
int main() {
cout << "Enter an integer: ";
int inputNum = 0;
cin >> inputNum;
cout << "Enter the value of Pi: ";
double Pi = 0.0;
cin >> Pi;
cout << "Enter three characters separated by space: " << endl;
char char1 = '\0', char2 = '\0', char3 = '\0';
cin >> char1 >> char2 >> char3; // 使用一行代码将输入读取到三个字符变量中
cout << "The recorded variable values are: " << endl;
cout << "inputNum: " << inputNum << endl;
cout << "Pi: " << Pi << endl;
cout << "The three characters: " << char1 << char2 << char3 << endl;
return 0;
}
4.2 使用std::cin:get 将输入读取到char*缓冲区中
- 插入到 char 缓冲区中时不超越其边界
#include<iostream>
#include<string>
using namespace std;
int main() {
cout << "Enter a line: " << endl;
char charBuf[10] = {0};
cin.get(charBuf, 9);
cout << "charBuf: " << charBuf << endl;
return 0;
}
尽可能不要使用 char 数组;只要可能,就应使用 std::string 而不是 char*
4.3 使用std::cin 将输入读取到std::string 中
#include<iostream>
#include<string>
using namespace std;
int main() {
cout << "Enter your name: ";
string name;
cin >> name;
cout << "Hi " << name << endl;
return 0;
}
Enter your name: Siddhartha Rao
Hi Siddhartha
输出表明,只显示了我的名字,而不是整个输入字符串,这可能让您感到惊讶。为什么会这样呢?显然是由于 cin 遇到空白后停止插入
- 要读取整行输入(包括空白),需要使用 getline()
#include<iostream>
#include<string>
using namespace std;
int main() {
cout << "Enter your name: ";
string name;
getline(cin, name);
cout << "Hi " << name << endl;
return 0;
}
5. 使用std::fstream 处理文件
- C++ 提供了 std::fstream,旨在以独立于平台的方式访问文件。std::fstream 从 std::ofstream 那里继承了写入文件的功能,并从 std::ifstream 那里继承了读取文件的功能
5.1 使用 open() 和 close() 打开和关闭文件
- 要使用 fstream、ofstream 或 ifstream 类,需要使用方法 open() 打开文件
fstream myFile;
// open()接受两个参数:第一个是要打开的文件的路径和名称(如果没有提供路径,将假定为应用程序的当前目录设置)
// 第二个是文件的打开模式:在上述代码中,指定了模式ios_base::trunc(即便指定的文件存在,也重新创建它)、
// ios_base::in(可读取文件)和ios_base::out(可写入文件)
myFile.open("HelloFile.txt", ios_base::in|ios_base::out|ios_base::trunc);
if (myFile.is_open()) { // check if open() succeeded
// do reading or writing here
myFile.close();
}
- 保存到文件时,必须使用 close() 关闭文件流
- 无论是使用构造函数还是成员方法 open() 来打开文件流,都建议在使用文件流对象前,使用 open() 检查文件打开操作是否成功
- 可在下述各种模式下打开文件流
ios_base::app // 附加到现有文件末尾,而不是覆盖它
ios_base::ate // 切换到文件末尾,但可在文件的任何地方写入数据
ios_base::trunc // 导致现有文件被覆盖,这是默认设置
ios_base::binary // 创建二进制文件(默认为文本文件)
ios_base::in // 以只读方式打开文件
ios_base::out // 以只写方式打开文件
5.2 使用 open() 创建文本文件并使用运算符 << 写入文本
- 使用 ofstream 新建一个文本文件并向其中写入文本
#include<fstream>
#include<iostream>
using namespace std;
int main() {
ofstream myFile;
myFile.open("HelloFile.txt", ios_base::out);
if (myFile.is_open()) {
cout << "File open successful" << endl;
myFile << "My first text file!" << endl;
myFile << "Hello file!";
cout << "Finished writing to file, will close now" << endl;
myFile.close();
}
return 0;
}
File open successful
Finished writing to file, will close now
// 生成的 HelloFile.txt 文件的内容如下
My first text file!
Hello file!
5.3 使用 open() 和运算符 >> 读取文本文件
#include<fstream>
#include<iostream>
#include<string>
using namespace std;
int main() {
ifstream myFile;
myFile.open("HelloFile.txt", ios_base::in);
if (myFile.is_open()) {
cout << "File open successful. It contains: " << endl;
string fileContents;
while (myFile.good()) {
getline (myFile, fileContents);
cout << fileContents << endl;
}
cout << "Finished reading file, will close now" << endl;
myFile.close();
} else {
cout << "open() failed: check if file is in right folder" << endl;
}
return 0;
}
5.4 读写二进制文件
- 将一个结构写入二进制文件并使用该文件的内容创建一个结构
#include <fstream>
#include <iomanip>
#include <cstring>
#include <iostream>
using namespace std;
struct Human {
Human() {};
Human(const char* inName, int inAge, const char* inDOB) : age(inAge) {
strcpy(name, inName);
strcpy(DOB, inDOB);
}
char name[30];
int age;
char DOB[20];
};
int main() {
Human Input("Siddhartha Rao", 101, "May 1916");
ofstream fsOut ("MyBinary.bin", ios_base::out | ios_base::binary);
if (fsOut.is_open()) {
cout << "Writing one object of Human to a binary file" << endl;
// reinterpret_cast 让编译器将结构解释为char*
fsOut.write(reinterpret_cast<const char*>(&Input), sizeof(Input));
fsOut.close();
}
ifstream fsIn ("MyBinary.bin", ios_base::in | ios_base::binary);
if(fsIn.is_open()) {
Human somePerson;
fsIn.read((char*)&somePerson, sizeof(somePerson));
cout << "Reading information from binary file: " << endl;
cout << "Name = " << somePerson.name << endl;
cout << "Age = " << somePerson.age << endl;
cout << "Date of Birth = " << somePerson.DOB << endl;
}
return 0;
}
6. 使用std::stringstream 对字符串进行转换
- 假设您有一个字符串,它包含字符串值 45,如何将其转换为整型值 45 呢?如何将整型值 45 转换为字符串 45 呢?C++提供的 stringstream 类是最有用的工具之一
#include<fstream>
#include<sstream>
#include<iostream>
using namespace std;
int main() {
cout << "Enter an integer: ";
int input = 0;
cin >> input;
stringstream converterStream;
converterStream << input;
string inputAsStr;
converterStream >> inputAsStr;
cout << "Integer Input = " << input << endl;
cout << "String gained from integer = " << inputAsStr << endl;
stringstream anotherStream;
anotherStream << inputAsStr;
int Copy = 0;
anotherStream >> Copy;
cout << "Integer gained from string, Copy = " << Copy << endl;
return 0;
}
- 只想读取文件时,务必使用 ifstream
- 只想写入文件时,务必使用 ofstream
- 插入文件流或从文件流中提取之前,务必使用 is_open() 核实是否成功地打开了它。