C++的IO流

您所在的位置:网站首页 文件输入流的使用情况 C++的IO流

C++的IO流

2023-07-12 14:41| 来源: 网络整理| 查看: 265

// 单个元素循环输入 while(cin>>str) {    // ... }

OJ是如何判断当前是输出结束的呢?

底层调用了 operator bool .

        C++中的输入流操作符 >> 会返回左操作数(cin对象--istream)的引用。此时 while 条件判断需要一个bool类型,则会自动调用operator bool函数,该函数会将一个对象隐式地转换为 bool 类型。

当输入流(cin)达到文件末尾(EOF)或者输入格式错误时,operator bool会返回false,循环终止;反之会返回true,继续读取。

通过这种方式,while(cin>>str)循环会自动判断输入结束的条件,无需用户手动输入特定的结束标志。编译器会根据输入流的状态自动决定循环何时结束。

tips:

(库中的explicit是防止隐式类型转化的,如果使用了explict就禁掉了隐式类型转化,只能使用显示类型转换,用于提高代码可读性)

在C++中还有很多这种对象转换为内置类型的函数,比如我们可以编写一个operator int 、operator string ,当需要int、string类型的时候,会自动调用operator int/operator string,返回int类型的值。

3.3 C++文件IO流

C++根据文件内容的数据格式分为二进制文件和文本文件。采用文件流对象操作文件的一般步骤:

1. 定义一个文件流对象

ifstream ifile(只输入用)ofstream ofile(只输出用)fstream iofile(既输入又输出用)

2.使用文件流对象的成员函数打开一个函数文件,使得文件流对象和磁盘文件之间建立联系。

3.使用提取和插入运算符对文件进行读写操作,或使用成员函数进行读写。

4.关闭文件。

读取文件的使用举例:

我们除了可以读取同一种类型,我们还可以使用流提取不同类型的数据。

并将其取出。

//data类: class Date { friend ostream& operator d._day; return in; } public: Date(int year = 1, int month = 1, int day = 1) :_year(year), _month(month), _day(day) {} private: int _year,_month,_day; };

C++中的IO流对自定义类型进行了更好的支持,使用的方式进行了同一的管理,对控制台、文件的读写十分便捷。

注意:

        不要使用string这种涉及深浅拷贝的类进行文件读写。

 

        当我们运行写程序时,程序将Serverinfo中的数据整个写入到文件中,string中写入的是_ptr指针,而_ptr指向着实际的字符串,该字符串存储在堆上;当该进程退出,程序地址空间回收,则_ptr成为野指针,此时文件便存储着一系列无效信息。         当我们再运行读进程时,程序将文件中的数据再写入到info中,此时文件中存储着上个进程中的数据,此进程因为拷贝来的_ptr是野指针,便无法获取到字符串;则内部都存放着非法地址(野指针),程序崩溃。

        即使现在我们对程序进行改写,让其读、写文件在同一个进程中:

 

 但是程序仍然出现了奔溃,因为我们我们ServerInfo中的string指向了同一空间,我们如果直接使用ReadBin将文件中的内容直接拷贝(浅拷贝)到rinfo中,此时rinfo中的string是浅拷贝,当出作用域时,winfo、rinfo中的string都会调用析构函数,则会产生内存泄漏,便程序崩溃。

这里给出几种解决方法:

        1. 自己写一个string,不编写析构函数,当文件关闭时,自己释放string指向的空间,

        2. 自己写一个string,使用智能指针来控制析构函数。

        3. 直接使用C语言的字符数组,简单省事。

3.4 二进制读写

二进制读写和文本读写

配合(或 | )操作符来设置打开方式

 接下来我们使用二进制来进行读和写:

//存储的文件 struct ServerInfo { char _address[32]; int _port; }; //进行存储的对象 struct ConfigManager_Bin { public: ConfigManager_Bin(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)); } private: string _filename; // 配置文件 };

 写入后,查看文件:

发现其中字符串部分正常显示,而数字部分为乱码。

这是因为:

        数字其以补码的形式进行存放,在程序中,数字以特定的方式进行存储的,当以二进制的方式写入到文件中,其会按存储方式的二进制写入文件,当打开文件时,该二进制会根据编码进行显示,则会出现乱码。 如果想让该数字正常显示,要将其转为字符串,再进行文件的写入

但是其确是是将内容以二进制的形式进行了写入。

然后我们使用二进制读取的方式将bin.txt中的内容读取出来:

3.5 文本读写

此时我们只用修改打开方式,并将其数据部分改为字符串类型进行写入,修改后的ConfigManager对象如下:

struct ConfigManager_Text { public: ConfigManager_Text(const char* filename) :_filename(filename) {} //文本的形式写 void WriteText(const ServerInfo& info) { ofstream ofs(_filename, ios_base::out ); ofs.write(info._address, strlen(info._address)); char str[20]=""; sprintf(str, "\n%d\n", info._port); //将整形写入到str中 ofs.write(str, strlen(str)); } //文本的形式读 void ReadText(ServerInfo& info) { ifstream ifs(_filename, ios_base::in ); //行读取 ifs.getline(info._address, 128); char port[32]; ifs.getline(port, 32); info._port = atoi(port); } private: string _filename; // 配置文件 };

读/写的函数如下:

void test_file03() { ServerInfo winfo = { "192.0.0.1", 80 }; ConfigManager_Text cf_bin("bin2.txt"); cf_bin.WriteText(winfo); } void test_file04() { ServerInfo rinfo; ConfigManager_Text cm("bin2.txt"); cm.ReadText(rinfo); cout


【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3