- 程序的输入:从输入文件将数据传送给程序
- 程序的输出:从程序将数据传送给输出文件
C++的输入主要包括:对系统指定标准设备的输入输出(如从键盘输入,从显示器输出);以外存(磁盘、光盘等)为对象进行输入输出;对内存中指定空间进行输入输出。
(二)输入输出流输入和输出是数据传输的过程被称为流。流表示了信息从源到目的端的流动,有序连续,具有方向性。
实际上,在内存中为每个数据流开辟一个内存缓冲区,用来存放流中的数据,即缓冲区中的数据就是流。
C++中,输入输出流被定义为类;I/O库中的类称为流类;用流类定义的对象称为流对象。
(三)IO类不同种类的IO处理操作主要定义在三个独立的头文件中:iostream定义了用于读写流的基本类型,fstream定义了读写命名文件的类型,sstream定义了读写内存string对象的类型。
头文件 类型
iostream istream,wistream从流读取数据
ostream,wostream从流写入数据
iostream,wiostream读写流
fstream ifstream,wifstream从文件读取数据
ofstream,wofstream向文件写入数据
fstream,wfstream读写文件
sstream istringstream,wistringstream从string读取数据
ostringstream,wostringstream向string写入数据
stringstream,wstringstream读写string
为了支持使用宽字符的,标准库定义了一组类型和对象来操纵wchar_t类型的数据,宽字符版本的类型和函数的名字以一个w开始。
(1)C++标准IO流| 对象 | 含义 | 对应设备 | 有无缓冲区 |
| cin | 标准输入流 | 键盘 | 有缓冲区 |
| cout | 标准输出流 | 键盘 | 有缓冲区 |
| cerr | 标准错误流 | 屏幕 | 无缓冲区 |
| clog | 标准错误流 | 屏幕 | 有缓冲区 |
- cin为缓冲流,键盘输入的数据保存在缓冲区,当需要提取时,从缓冲区提取;遇到Enter键完成输入;
-
//敲回车键的有 int a; cin >> a; char c; c = getchar(); int b; scanf("%d", &b); //末尾会添加一个空字符,如果键入1234567890会中断 //只能键入123456789 char str[10]; gets(str, 10); - 输入数据类型和要提取数据类型一致
- cin和cout可以直接输入和输出内置类型数据
- 对于自定义的类型,如果要支持cin和cout的标准输入输出,需要对<<和>>进行重载
由于不能拷贝IO对象,因此我们不能将形参活返回类型设置为流类型,进行IO操作的函数通常以引用方式传递和返回流,读写一个IO对象会改变其状态,因此其引用不能是const的。
ofstream out1, out2; out1 = out2; //错误,不能对流对象赋值 ofstream print(ofstream); //错误,不能初始化ofstream参数 out2 = print(out2); //错误,不能拷贝流对象(3)条件状态
IO操作一个与生俱来的问题就是可能发生错误,一些错误是可恢复的,而一些错误是发生在系统深处,已经超出应用程序可以修正的范围,而IO类所定义的一些函数和标志,可以帮助我们访问和操纵流的条件状态。
下面是一个错误的例子:
int val; cin >> val;
如果我们在标准输入上键入Boo,该操作就会失败,因为代码中输入运算符期待读取一个int,但却得到了一个字符B。
一旦一个流发生了错误,其上后续的IO操作都会失败,只有当一个流处于无错误状态,我们才可以从它读取数据。确定一个流对象的状态最简单的方法就是将它当作一个流来使用:
while(cin >> word)
//ok:读操作成功......
(四)C++文件IO流
暂补充
(五)C++ stringstream- 将整型变量的数据转换为字符串格式:(1)使用itoa()函数(2)使用sprintf()函数,但是使用时都得需要先给出保存结果的空间,而且转换格式需要匹配
int n = 123456789; char s1[32]; _itoa(n, s1, 10); cout << s1 << endl; //123456789 char s2[32]; sprintf(s2, "%d", n); cout << s2 << endl; //123456789 char s3[32]; sprintf(s3, "%f", n); cout << s3 << endl; //0.000000 char s4[32]; float n1 = 3.2; sprintf(s4, "%f", n1); cout << s4 << endl; //3.200000
- 在C++中,可以使用stringstream类对象避开此问题,避免缓冲区溢出的危险,而且会对参数类型进行推演,不需要格式化控制,使用更安全。stringstream实际时在其底层维护了一个string类型的对象来保存结果
- 多次数据类型转换时,一定要用clear(),才能正确转换,但clear()不会将stringstream底层的string对象清空
int a = 123456; stringstream ss; //字符串读写流 string str; ss << a; //a->ss ss >> str; //ss->str cout << str << endl; //输出123456 ss.clear(); //清空ss float f = 1.2; ss << f; ss >> str; cout << str << endl; //输出1.2
- stringstream可以完成字符串拼接,可以使用s.str("")方法将底层string对象设置为""空字符串,可以使用s.str()让stringstream返回其底层的string对象
stringstream ss;
//把多个字符串放入stringstream
ss << "first" << " " << "string,";
ss << " second string";
cout << ss.str() << endl; //输出first string, second string
//clear() 操作,并不会清除底层string对象
ss.clear();
cout << ss.str() << endl; //输出first string, second string
//删除底层,使用s.str("");
ss.str("");
ss << "third string";
cout << ss.str() << endl; //输出third string
补充一下:
(六)string 与 char* 和char[]的相互转换
(1)string 转换为 char*和char[]
- 使用data()方法
string str = "fisrt str"; const char* p1 = str.data(); cout << p1 << endl; //输出fisrt str
- 使用c_str()方法
string str = "fisrt str"; const char* p1 = str.c_str(); cout << p1 << endl; //输出fisrt str
- 使用copy()方法
string str = "fisrt str"; int len = str.length(); char* p = new char[len + 1]; str.copy(p, len, 0); //第二个参数表示复制几个字符,第三个参数表示赋值的起始位置 *(p + len) = ' '; //一定要加上 cout << p << endl; //输出fisrt str(2)char[] 转换为string
多种方法,这里记录两种
- 向构造函数传入c字符串创建string对象
- 使用拷贝构造函数创建string对象
char c[] = "hello world"; //构造函数 string str(c); //拷贝构造函数 string str = c;(七)string 转换为整数
string k = "12345"; cout << atoi(k.data()) << endl; cout << atoi(k.c_str()) << endl;



