14.9.2 sstream类族
sstream类族包含一个从ostream类中派生而来的ostringstream类(是basic_ostringstream类的char型示例化,对应着wchar_t宽类型还有wostringstream,本节针对的都是char型实例化后的sstream类族),从istream类中派生来的istringstream类,还有从iostream类派生而来的stringstream类。相比strstream类族,sstream类族将C++风格字符串,即string类型变量当做输入输出设备。
注意
使用sstream类族必须包含头文件<sstream>。
1.ostringstream类流对象
ostringstream类流对象用于向string类变量中插入字符,ostringstream类流对象的构造函数有如下两种重载形式。
ostringstream(const string&str,openmode which=ios_base:out); ostringstream(openmode which=ios_base:out);
第1种重载形式用string对象str初始化缓冲区,从传递的参数str为const引用来看,流对象的输出操作并不会对原来的string对象str产生影响,输出的目的地是流缓冲区。第2种形式不对缓冲区进行初始化。
不论采用哪种方式,都是由流对象本身动态管理内存,当同样可以使用str函数返回一个string类临时对象时,该临时对象使用缓冲区中的内容初始化,其原型如下所示。
string str()const;
注意
返回临时string对象的同时,流对象不会被冻结。
此外,ostringstream类中还重载了另一种str函数形式,如下所示。
void str(const string&s);
这种调用形式首先将流缓冲区清空(Deallocate),而后重新开辟缓冲区,用string对象s初始化,此时put指针位于ostringstream流对象的头部,如示例代码14.34所示。
代码14.34 ostringstream类流对象的用法OstringstreamSample
<———————————-文件名:example1434.cpp———————————————-> 01 #include<iostream> 02 #include<sstream> 03 #include<string>//使用string必须包括此头文件 04 using namespace std; 05 int main() 06 { 07 string str("Hello"); 08 ostringstream os(str);//用str为os缓冲区初始化 09 os<<"I Love China"<<endl;//输出字符串,从流指针(当前指向头部)开始 10 cout<<os. str(); 11 os. str("123456789"); 12 cout<<os. str();//输出缓冲区中的string对象值 13 cout<<endl;//换行 14 os<<"NUDT";//也可使用seekp函数移动put指针,调节位置 15 cout<<os. str()<<endl;//不会冻结,后面的输出仍采纳 16 return 0; 17 }
输出结果如下所示。
I Love China 123456789 NUDT56789
注意
上述代码在VC6下编译通过,但运行时会出现内存错误,而在其他编译器上没有这种问题,这可能是VC6的bug,建议使用VC 2005编译运行本例。
【代码解析】创建了ostreamstring对象os,并用string类对象os初始化其缓冲区,则可以像使用cout一样使用os将格式化信息写入os的缓冲区中,通过“os.str()”形式即可返回一个由os缓冲区数据初始化的string临时对象,完成对缓冲区的访问。代码第11行语句“os.str("123456789");”首先清空了os的缓冲区,而后重新用字符串“123456789”初始化新的缓冲区,此时put指针重新回到流的头部,因此,后面“os<<NUDT”操作将覆盖缓冲区中的前4个字符,输出结果为“NUDT56789”。
注意
ostringstream类流对象同样涉及结尾标识ends,即'\0'的添加问题。
2.istringstream类流对象
istringstream类流对象将string类对象作为信息输入源,istringstream构造函数同样有两种重载形式,如下所示。
istringstream(openmode which=ios_base:in); istringstream(const string&str,openmode which=ios_base:in);
常用的是第2种形式。如示例代码14.35所示。
代码14.35 istringstream类流对象的使用IstringstreamSample
<————————————-文件名:example1435.cpp——————————————-> 01 #include<iostream> 02 #include<sstream> 03 using namespace std; 04 int main() 05 { 06 string str("123H3. 1415");//创建string类对象 07 istringstream is(str);//创建istringstream类流对象is 08 int i; 09 char c; 10 double d; 11 is>>i>>c>>d;//格式化输入 12 cout<<"i is"<<i<<",c is"<<c<<",d is"<<d<<endl; 13 return 0; 14 }
输出结果如下所示。
i is 123,c is H,d is 3.1415
【代码解析】代码第7行创建了istringstream类的对象is,并使用string类对象str对is的缓冲区进行了初始化,可以像使用cin一样使用is,从其缓冲区中格式化输入信息到变量i、c和d中,使用cout对3个变量的标准输出来验证程序的正确性。
对第1种形式的构造函数来说,istringstream类流对象的缓冲区为空,因此在输入操作前需要使用“void str(const string&s)”成员函数来对其缓冲区赋值,以便格式化输入,如代码14.36所示。
代码14.36 使用str函数改写istringstream类流对象缓冲区FuncStr
<———————————-文件名:example1436.cpp———————————————-> 01 #include<iostream> 02 #include<sstream> 03 using namespace std; 04 int main() 05 { 06 istringstream is;//创建istringstream类流对象is 07 is. str("123A9.2"); 08 int i; 09 char c; 10 double d; 11 is>>i>>c>>d;//格式化输入 12 cout<<"i is"<<i<<",c is"<<c<<",d is"<<d<<endl; 13 return 0; 14 }
输出结果如下所示。
i is 123,c is A,d is 9.2
【代码解析】代码第6行虽然调用无参构造函数创建了istringstream类流对象is,但随后通过str函数改写了is的缓冲区,从而实现了信息的格式化输入。