🎁个人主页:我们的五年
🔍系列专栏:C++课程学习
🎉欢迎大家点赞👍评论📝收藏⭐文章
C++学习笔记:
https://blog.csdn.net/djdjiejsn/category_12682189.html
前言:
在C语言中有各种IO流,控制台IO流,文件IO流。C++作为一门面向对象的语言,肯定是要自己封装IO流的。更加灵活,自定义类也可以重载输入输出流。
目录
1.C语言中的流
1.1控制台IO:
1.2输入,输出缓冲区:
1.3 流是什么:
2.C++的IO流
2.1说明:
2.2标准流(cin)的标志位:
2.3当出现类型不匹配出现输入流fail错误时,怎么处理?
3.C++的标准IO流:
3.1使用说明:
3.3注意事项:
3.4istream作为逻辑判断真假
4.C++文件IO流
5.stringstream流
1.C语言中的流
1.1控制台IO:
控制台(console)流有printf,scanf
scanf | 从标准输入设备读取数据,放到变量中 |
printf | 向标准输出设备中输出数据 |
1.2输入,输出缓冲区:
设计输入输出缓冲区的好处:
●提高效率,直接将一个小部分整体IO,避免多次IO。IO是和外设打交道,是很浪费时间的。
●有了缓存区,IO的底层实现可以交给操作系统,我们要IO的数据,直接拷贝到缓冲区就行,剩下的交给操作系统,其他类似的缓冲区也是这样的原理。这样可以上次开发不要管IO这部分了,屏蔽这部分的差异,开发效率更高。
●还有一点就是,计算机本来没有‘行’的概念,缓冲区的大小,就可以定义为行的大小,从而可以向缓冲区写满就刷新(按行刷新)。
1.3 流是什么:
1.有序, 2.连续, 3.有方向
2.C++的IO流
2.1说明:
除了标准IO流,还有文件IO流,stringIO流,后面都讲一下,C++的IO流是一个庞大的体系。继承关系可见下面的图。
推荐C++语法查询的网站:https://www.cplusplus.com/
不是官方的网站,但是感觉挺好用,有什么忘记了的一查便知。
ios继承ios_base,箭头就表示继承。
可见标准IO,文件IO,stringIO,都是由istream,ostream继承来的。
2.2标准流(cin)的标志位:
goodbit | 为1时,表示输入流正常。 |
eofbit | 为1时,表示读到文件末尾。 |
failbit | 为1时,表示逻辑错误,轻微错误,可以恢复。 |
badbit | 为1,表示读写错误,严重错误,不可回复。 |
上面的这四个标志位,iostat用的是位图的思想,某个比特位为1,就表示某种情况,所以他们要被一起设置的时候,用按位与|。
eofbit, failbit and badbit are member constants with implementation-defined values that can be combined (as if with the bitwise OR operator). goodbit is zero, indicating that none of the other bits is set.
当eofbit,failbit,badbit没有被设置的时候,goodbit被设置。
2.3当出现类型不匹配出现输入流fail错误时,怎么处理?
类型不匹配,failbit被设置,badbit时很严重的错误,进程直接没了。
一:先把三个错误都设置为0,goodbit就设置为1了,就能正常使用了。
通过clear,setstate函数进行设置。
stat函数:
void setstate (iostate state);
clear函数:
void clear (iostate state = goodbit);
我觉得这个clear更好,因为默认的参数就是goodbit。
二:把cin输入缓冲区里面的数据全部拿走。
避免再次输入错误。
整体代码:
if (cin.fail())
{
//清理标志位
cin.clear();
//清理缓冲区
getline(cin, s);
}
#include <iostream>
#include <string>
using namespace std;int main()
{int n;cin >> n;cout << n << endl;string s;if (cin.fail()){//清理标志位cin.clear();//清理缓冲区getline(cin, s);}cout << "11111111111111" << endl;cout << cin.good() << endl;cout << cin.fail() << endl;cout << cin.bad() << endl;cout << cin.eof() << endl;cout << "11111111111111" << endl;cin >> n;cout << n << endl;return 0;
}
3.C++的标准IO流:
3.1使用说明:
标准输入(cin),标准输出(cout),标准错误(cerr),标准日志(clog)都是继承ios。
前一个是由istream来的,后面三个是ostream来的。
cin是从输入缓冲区读取,放入变量中。
cout,cerr,clog都是向显示器输出,这三个差不多,应用场景不一样。用法如下。
他们都在命名空std中,要不展开命名空间,要不每次用的时候,指明命名空间。
#include <iostream>
using namespace std;int main()
{int a;cin >> a; //标准输入cout <<"cout:" << a << endl; //标准输出cerr <<"cerr:" << a << endl; //标准错误clog <<"clog:" << a << endl; //标准日志return 0;
}
// 单个元素循环输入
while(cin>>a)
{
// ...
}
// 多个元素循环输入
while(c>>a>>b>>c)
{
// ...
}
// 整行接收
while(cin>>str)
{
// ...
}
3.3注意事项:
1.我们在用cin的时候,如果我们输错了,一定要在回车之前修改,回车以后就写入输入缓冲区了,就不能修改了。前面也说了流是有方向的,连续的,有方向的,所以输入流,要把前面的读完,才能读后面的。
2.输入的类型和提取的类型必须一样,否则出错,根据不同错误设置不同的bit位。
3.空格和换行可以作为数据之间的区分标志。
4.内置类型库中已经重载了,如果自定义类型要想使用,要重载operator<<,operator>>。
5.连续输出时,Ctrl+z结束,错误标志failbit被设置。
3.4istream作为逻辑判断真假
我们在连续输入的时候,cin>>n放在while里面,但是operator >>函数返回的istream&,istream为什么能作为真假进行判断呢?
其本质是istream又去调用了operator bool()
当流失败的时候,有错误标志的时候,返回false,流没有问题的时候,就返回true,就能进行真假判断了。
//while(cin>>n)
while ((cin>>n).operator bool())
{//哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈
//相信美好的事情即将发生
}
4.C++文件IO流
包含的头文件:
#include <fstream>
文件的可区分为:二进制文件,文本文件。
●ifstream ifile(只输入用)
●ofstream ofile(只输出用)
●fstream iofile(既输入又输出用)
刚刚在写的时候,就打开同一个文件,用ifstream,ofstream同时打开同一个文件,就读不出来了,要对文件读写,得用fstream。BUG
还有就是打开文件设置的权限。
ios_base::binary|ios_base::in
int main()
{//const string filename = "file.txt";//ofstream out(filename);//int n = 1001;//out <<n;//out.close();//int m;//ifstream in(filename);//in >> m;//cout << m;const string filename = "file.txt";//用|将这个合并fstream out(filename,ios_base::binary|ios_base::in);int n = 1001;out <<n;int m;ifstream in(filename, ios_base::binary | ios_base::in);in >> m;cout << m;return 0;
}
1.使用文件流对象的成员函数打开一个磁盘文件,使得文件流对象和磁盘文件之间建立联系。
2.使用提取和插入运算符对文件进行读写操作,或使用成员函数进行读。
3.关闭文件。
5.stringstream流
这个流的主要用途是,把一系列的类型,转换为字符串。
C语言中的转字符串的函数有:
1.使用itoa()函数。
2.使用sprintf()函数。
这两个函数就是要先开空间,确定好空间的大小,不太好使用。
int main()
{stringstream s;int a = 12134;string str;s << a;str=s.str();cout << str;return 0;
}
stringstreams在转换结尾时(即最后一个转换后),会将其内部状态设置为badbit,因此下一次转换是必须调用clear()将状态重置为goodbit才可以转换,但是clear()不会将stringstreams底层字符串清空掉 。
1.stringstream底层是维护了一个string对象保存。
2.对同一个流多次转换时,一定要clear()清理,才能正确转换,但是clear不会把底层的string对象清空。
3.可以用.str("")对string对象进行清空。
4.用.str()拿到底层的string对象里的对象。