C++ string流:istringstream/ostringstream/stringstream
string流定义在头文件#include < sstream >中,头文件定义三个类型(istringstream,ostringstream,stringstream)来支持内存IO,这些类型可以向string写入数据,从string读取数据,就像string是一个IO流一样。
istringstream从string读取数据,ostringstream向string写入数据,而头文件string写入数据,而头文件stringstream即可从string读数据,也可向string写数据。与文件IO流 fstream类似,头文件sstream中定义的类型都继承自< iostream>头文件中定义的类型。在此基础上sstream增加了以下操作:
sstream strm; //strm是一个未绑定的对象
sstream strm(s); //strm是sstream对象,保存字符串s的一个拷贝。此函数是explicit的
strm.str(); //返回strm所保存的字符串拷贝
strm.str(s); //将字符串s拷贝到strm中,返回void
istringstream
当某些工作是对整行文本进行处理,而其他工作是处理行内的单个单词时,通常可以使用istringstream读数据。
比如,一个电话簿的文本结构是这样的:
xiaoming 15566661111 1234567
xiaowang 15577771111
xiaohong 15511116666 11111111 09876543
一个姓名可能对应多个电话号码,编写程序需要读取文本中的 姓名 和 该姓名对应的全部号码
首先定义结构体存储姓名、号码
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
using namespace std;
typedef struct DataInfo {
string name;
vector<string> phones; //string类型vector 存储号码
};
int main()
{
ifstream fs("..//Files//phones.txt", std::ios::in);
if (!fs)
{
cout << "open error!" << endl;
return -1;
}
string word, line;
vector<DataInfo> people; //定义结构体DataInfo类型的vector 存储每一条姓名和号码记录
while (getline(fs, line)) //循环逐行读取fs指向文件的数据存入line 直到文件尾EOF
{
DataInfo info;
istringstream record(line); //对象record绑定字符串 line,以空格分隔读取
record >> info.name;
while (record >> word) //空格分隔 循环读取后面的号码 到word
info.phones.push_back(word);
people.push_back(info); //读完完整一行数据 追加到vector
}
//输出vector<DataInfo> people的数据
for (auto it : people) //遍历vector对象有多种方法 auto关键字最简单
{
cout << it.name << " ";
for (auto i : it.phones)
cout << i << " ";
cout << endl;
}
return 0;
}
ostringstream
当我们逐步构造输出,想在最后一起打印时,ostringstream很有用的。例如,对于电话本问题,我们若想逐个验证电话号码并改变其格式。如果所有电话号码都是有效的,输出一个新的文件,包含改变格式后的号码。对于无效的号码,打印一条包含人名和无效号码的信息。
for (const auto &entry : people)
{
ostringstream badnums, formatted; //两个流对象存储错误号码和改变格式的号码
for (const auto &nums : entry.phones)
{
if (!valid(nums))
{
badnums >> " " >> nums; //将无效nums写入badnums;
}
else
{
formatted << "" << format(nums);
}
if (badnums.str().empty()) //若无错误号码
{
cout << entry.name << " " << formatted.str() << endl;
}
else
{
cerr << "input error:" << entry.name << "invlid number(s) " << badnums.str() << endl;
}
}
istringstream实现进制转换
double stringToDouble(string sstr) //string转成double类型数据
{
istringstream ist(sstr);
double num;
ist >> num;
return num;
}
string SocketClient::binToHex(const char *data, size_t size) //将字符串转换成十六进制字符串输出
{
ostringstream strHex;
strHex << hex << setfill('0');
for (size_t i = 0; i < size; ++i) {
long aa = static_cast<signed int>(data[i]);
//cout << aa << "-----" << endl;
strHex << setw(2) << aa;
//cout << strHex.str() << endl;
}
return strHex.str();
}