28.C++的IO流

一.C语言的输入与输出

二.流是什么


三.C++IO流









1.C++标准IO流






2.代码解析:
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
using namespace std;int main()
{cout << "11111" << endl;cerr << "11111" << endl;clog << "11111" << endl;string str;// istream& operator>> (istream& is, string& str);//while (cin >> str)while (operator>>(cin, str).operator bool()){cout << str << endl; }return 0;
}
a.cout,cerr,clog的区别




b.istream







如果 failbit 或者 badbit 标志位被设置了,那么就会返回 false ,如果没被设置了,返回 true
3.io流的标志位


a.ctrl + z和ctrl + c原理



b.代码测试
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
using namespace std;int main()
{string str;cout << cin.good() << endl;cout << cin.eof() << endl;cout << cin.bad() << endl;cout << cin.fail() << endl << endl;return 0;
}

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
using namespace std;int main()
{// istream& operator>> (istream& is, string& str);//while (cin >> str)while (operator>>(cin, str).operator bool()){cout << cin.good() << endl;cout << cin.eof() << endl;cout << cin.bad() << endl;cout << cin.fail() << endl << endl;cout << str << endl; }return 0;
}


ctrl + z之后,我们的cin就不能继续使用了(cin要能使用,good被设置成为1,其他标志位设置成为0)

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
using namespace std;int main()
{while (operator>>(cin, str).operator bool()){cout << cin.good() << endl;cout << cin.eof() << endl;cout << cin.bad() << endl;cout << cin.fail() << endl << endl;cout << str << endl; }cout << cin.good() << endl;cout << cin.eof() << endl;cout << cin.bad() << endl;cout << cin.fail() << endl << endl;// 恢复标志状态cin.clear();while (cin >> str){cout << cin.good() << endl;cout << cin.eof() << endl;cout << cin.bad() << endl;cout << cin.fail() << endl << endl;cout << str << endl;}return 0;
}

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
using namespace std;int main()
{int i = 0;cout << cin.good() << endl;cout << cin.eof() << endl;cout << cin.bad() << endl;cout << cin.fail() << endl << endl;cin >> i;cout << i << endl;// 11ssscout << cin.good() << endl;cout << cin.eof() << endl;cout << cin.bad() << endl;cout << cin.fail() << endl << endl;cin >> i;cout << i << endl;if (cin.fail()){cin.clear();char ch;while (cin.get(ch)){cout << ch;}}cin >> i;cout << i << endl;cout << cin.good() << endl;cout << cin.eof() << endl;cout << cin.bad() << endl;cout << cin.fail() << endl << endl;return 0;
}


我们要将字符想办法拿掉
if (cin.fail()){cin.clear();char ch;while (cin.get(ch)){cout << ch;}}
这样我们就能将一次输入里面的字符全部都拿走,(只要进入这里面就不会再出去了)

4.竞赛IO效率问题
int main()
{// 在io需求比较高的地方,如部分大量输入的竞赛题中,加上以下3行代码// 可以提高C++IO效率ios_base::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);//cout << "31312312";//cin >> i;return 0;
}



顺序就打乱了,那也就是说,C++每次入数据的时候,我们要将两个缓存区的数据全部刷出去
这种同步,要付出代价的,所以效率会有牺牲
我们上面的代码就是将我们的流同步进行关闭了,但是还是没有scanf和printf效率高

5.补充知识



6.C++文件IO流

ofstream - C++ Reference

文件读写方式:

a.文件的写入

#include<fstream>int main()
{ofstream ofs("test.txt");//ofs.open("test.txt");ofs.put('x');ofs.write("hello\n", 6);ofs << "22222222" << endl;int x = 111;double y = 1.11;ofs << x << endl;ofs << y << endl;//ofs.close();return 0;
}




为了代码规范,我们还是建议自己主动进行关闭
b.文件的读取
int main()
{//ifstream ofs("test.cpp");ifstream ofs("D:\\8-10.png", ios_base::in | ios_base::binary);int n = 0;while (!ofs.eof()){char ch = ofs.get();//cout << ch;++n;}cout << n << endl;return 0;
}
像test.cpp的这些就是文本文件,像图片视频都是二进制文件
文本文件就正常读取就可以了,二进制文件要加上我们的读取方式(ios_base::binary)
c.向文件中分方式写
class Date
{friend ostream& operator << (ostream& out, const Date& d);friend istream& operator >> (istream& in, Date& d);
public:Date(int year = 1, int month = 1, int day = 1):_year(year), _month(month), _day(day){}operator bool(){// 这里是随意写的,假设输入_year为0,则结束if (_year == 0)return false;elsereturn true;}
private:int _year;int _month;int _day;
};istream& operator >> (istream& in, Date& d)
{in >> d._year >> d._month >> d._day;return in;
}ostream& operator << (ostream& out, const Date& d)
{out << d._year << " " << d._month << " " << d._day;return out;
}struct ServerInfo
{//char _address[32];string _address;int _port;Date _date;
};struct ConfigManager
{
public:ConfigManager(const char* filename):_filename(filename){}// 二进制// 内存中怎么存,囫囵吞枣,怎么写出去void WriteBin(const ServerInfo& info){ofstream ofs(_filename, ios_base::out | ios_base::binary);ofs.write((const char*)&info, sizeof(info));}void ReadBin(ServerInfo& info){ifstream ifs(_filename, ios_base::in | ios_base::binary);ifs.read((char*)&info, sizeof(info));}void WriteText(const ServerInfo& info){ofstream ofs(_filename);ofs << info._address << " " << info._port << " " << info._date;}void ReadText(ServerInfo& info){ifstream ifs(_filename);ifs >> info._address >> info._port >> info._date;}private:string _filename; // 配置文件
};
int main()
{ServerInfo winfo = { "192.0.0.1111111111111111111111", 80, { 2022, 4, 10 } };// 二进制读写ConfigManager cf_bin("test.bin");cf_bin.WriteBin(winfo);return 0;
}


int main()
{// 二进制读写ConfigManager cf_bin("test.bin");ServerInfo rbinfo;cf_bin.ReadBin(rbinfo);cout << rbinfo._address << " " << rbinfo._port << " " << rbinfo._date << endl;return 0;
}


我们要是写入是用char*就可以,但是用string就会奔溃,为啥呢?

程序结束,就将内存进行销毁了,但是我们的读程序启动是,就将这个重新读取进来了,这里就野指针了
总结: 有深浅拷贝的类,在进行读写拷贝的时候,就会出现该问题
文本读写

类转strIng 如下:


这时就有一个切割和切片的问题:

int main()
{ServerInfo winfo = { "192.0.0.1", 80, { 2022, 4, 10 } };// 文本读写ConfigManager cf_text("test.text");cf_text.WriteText(winfo);return 0;
}

int main()
{ConfigManager cf_text("test.text");ServerInfo rtinfo;cf_text.ReadText(rtinfo);cout << rtinfo._address << " " << rtinfo._port << " " << rtinfo._date << endl;return 0;
}

四.stringstream的简单介绍



![]()
1. 将数值类型数据格式化为字符串
#include<sstream>int main()
{int i = 123;Date d = { 2022, 4, 10 };ostringstream oss;oss << i << endl;oss << d << endl;string s = oss.str();cout << s << endl;//istringstream iss(s);//istringstream iss;//iss.str("100 2024 9 9");istringstream iss("100 2024 9 9");int j;Date x;iss >> j >> x;return 0;
}




2. 字符串拼接

3. 序列化和反序列化结构数据
// json库struct ChatInfo
{string _name; // 名字int _id; // idDate _date; // 时间string _msg; // 聊天信息
};int main()
{// 结构信息序列化为字符串ChatInfo winfo = { "张三", 135246, { 2022, 4, 10 }, "晚上一起看电影吧" };ostringstream oss;oss << winfo._name << " " << winfo._id << " " << winfo._date << " " << winfo._msg;string str = oss.str();cout << str << endl << endl;// send(str);// str = recv()ChatInfo rInfo;istringstream iss(str);iss >> rInfo._name >> rInfo._id >> rInfo._date >> rInfo._msg;cout << "-------------------------------------------------------" << endl;cout << "姓名:" << rInfo._name << "(" << rInfo._id << ") ";cout << rInfo._date << endl;cout << rInfo._name << ":>" << rInfo._msg << endl;cout << "-------------------------------------------------------" << endl;return 0;
}
后续网络部分,使用的比较多(json类似于是map,可以直接进行提取)


