C++IO流
C++系统实现了一个庞大的类库,其中ios为基类,其他类都是直接或间接派生自ios类
注意:
1. cin为缓冲流。键盘输入的数据保存在缓冲区中,当要提取时,是从缓冲区中拿。如果一次输 入过多,会留在那儿慢慢用,如果输入错了,必须在回车之前修改,如果回车键按下就无法 挽回了。只有把输入缓冲区中的数据取完后,才要求输入新的数据。
2. 输入的数据类型必须与要提取的数据类型一致,否则出错。出错只是在流的状态字state中对 应位置位(置1),程序继续。
3. 空格和回车都可以作为数据之间的分格符,所以多个数据可以在一行输入,也可以分行输 入。但如果是字符型和字符串,则空格(ASCII码为32)无法用cin输入,字符串中也不能有 空格。回车符也无法读入。
4. cin和cout可以直接输入和输出内置类型数据,原因:标准库已经将所有内置类型的输入和 输出全部重载了:
5. 对于自定义类型,如果要支持cin和cout的标准输入输出,需要对>>和<<进行重载。
6. 在线OJ中的输入和输出:
对于IO类型的算法,一般都需要循环输入
输出:严格按照题目的要求进行,多一个少一个空格都不行。
连续输入时,vs系列编译器下在输入ctrl+Z时结束
istream类型对象转换为逻辑条件判断值
类似于:
class A
{
public:
A(int a)
:_a1(1)
,_a2(2)
{}
operator int()
{
return _a1 + _a2;
}
private:
int _a1;
int _a2;
};
C++文件IO流
C++根据文件内容的数据格式分为二进制文件和文本文件。采用文件流对象操作文件的一般步 骤:
1. 定义一个文件流对象
ifstream ifile(只输入用)
ofstream ofile(只输出用)
fstream iofile(既输入又输出用)
2. 使用文件流对象的成员函数打开一个磁盘文件,使得文件流对象和磁盘文件之间建立联系
3. 使用提取和插入运算符对文件进行读写操作,或使用成员函数进行读写
4. 关闭文件
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;
else
return 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)
{}
//二进制读写操作(不能读写string这种需要深拷贝的自定义类型)
void WriteBin(const ServerInfo& info)
{
//ofstream ofs(_filename, ofstream::out | ofstream::binary);
ofstream ofs(_filename, ios_base::out | ios_base::binary);
ofs.write((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 << endl;
ofs << info._port << endl;
ofs << info._date << endl;
}
void ReadText(ServerInfo& info)
{
ifstream ifs(_filename);
ifs >> info._address;
ifs >> info._port;
ifs >> info._date;
}
private:
string _filename; // 配置文件
};
int main()
{
ConfigManager cm("test.txt");
ServerInfo winfo = { "192.0.0.111111111111111111", 80, {2023,4,1} };
cm.WriteText(winfo);
ServerInfo rinfo;
cm.ReadText(rinfo);
cout << rinfo._address << endl;
cout << rinfo._port << endl;
cout << rinfo._date << endl;
return 0;
}
stringstream的简单介绍
在程序中如果想要使用stringstream,必须要包含头文件。在该头文件下,标准库三个类: istringstream、ostringstream 和 stringstream,分别用来进行流的输入、输出和输入输出操 作,本文主要介绍stringstream。
// 序列化和反序列化
struct ChatInfo
{
string _name; // 名字
int _id; // id
Date _date; // 时间
string _msg; // 聊天信息
};
int main()
{
ChatInfo winfo = { "张三", 135246, { 2023, 4, 1 }, "晚上一起看电影吧" };
stringstream oss;
oss << winfo._name << endl;
oss << winfo._id << endl;
oss << winfo._date << endl;
oss << winfo._msg << endl;
string s = oss.str();
cout << s;
ChatInfo rInfo;
stringstream iss(oss.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;
}