8.3 string 流
sstream 头文件定义了三个类型来支持内存 IO,这些类型可以向 string 写入数据,也可以从 string 读取数据,就像 string 是一个 IO 流一样。
istringstream 从 string 读数据;ostringstream 向 string 写入数据;而头文件 stringstream 既可以从 string 读数据,也可以向 string 写数据。
8.3.1 使用 istringstream
假定现在有如下的输入文件:
morgan 2015552368 8625550123
drew 9735550130
...
文件中的每条记录以人名开始,后面的数字表示电话号码,定义一个简单的结构体来描述输入数据:
struct PersonInfo {
string name;
vector<string> phones;
};
程序需要读取数据文件,并创建一个 PersonInfo 的 vector:
string line, word;
vector<PersonInfo> people;
while(getline(cin, line)) {
PersonInfo info; // 创建一个保存当前行数据的对象
istringstream record(line); // 将记录绑定到刚读入的行
record >> info.name; // 读取名字
while(record >> word) { // 读取电话号码
info.phones.push_back(word); // 保存到 vector
}
people.push_back(info);
}
8.2.2 使用 ostringstream
当我们逐步构造输出,虚妄最后一起打印时,ostringstream 非常有用。对于刚才的例子:
for(const auto &entry : people) { // 遍历 people 当中的每一项
// 注意 people 是保存着 PersonInfo 的 vector 对象, 因此 entry 是 PersonInfo 对象
ostringstream formatted, badNums; // 每个循环创建对象自动析构
for(const auto &nums : entry.phones) { // 对每一个数
if(!valid(nums)) { // 如果不是 valid 的数
badNums << " " << nums; // 将数的字符串形式存入 badNums
} else {
// 将格式化的字符串写入 formatted
formatted << " " << format(nums);
}
}
if(badNums.str().empty()) { // 如果没有错误的数
os << entry.name << " " << formatted.str() << endl;
} else {
cerr << "input error: " << entry.name << "invalid number(s)" << badNums.str() << endl;
}
}