博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
c++的输入输出 [三](istringstream,ostringstream,stringstream)
阅读量:6077 次
发布时间:2019-06-20

本文共 5681 字,大约阅读时间需要 18 分钟。

写在最前面

我这篇博文是根据别人的博文整理而成的,所以出现和别人一样的地方是我摘抄的,我会注明。

这份笔记我分成了三章,分别讲下面的三个部分。

基础介绍

c++的输入输出分为三种:

1.基于控制台的I/O

r_1.jpg

2.基于文件的I/O

r_2.jpg

3.基于字符串的I/O

r_3.jpg

第三种 基于字符串的I/O

这部分参考 以及

在过去,我们使用的是原始的<stdio.h>中的接口,但是今天我想讲的是一个新的库<sstream>,这个库拥有拥有类型安全和不会溢出这样抢眼的特性,很有理由让我们使用它。下面我将详述。

头文件

#include

作用

istringstream类用于执行C++风格的字符串流的输入操作。

ostringstream类用于执行C++风格的字符串流的输出操作。
strstream类同时可以支持C++风格的串流的输入输出操作。

为什么我们要学

如果你已习惯了<stdio.h>风格的转换,也许你首先会问:为什么要花额外的精力来学习基于<sstream>的类型转换呢?也许对下面一个简单的例子的回顾能够说服你。假设你想用sprintf()函数将一个变量从int类型转换到字符串类型。为了正确地完成这个任务,你必须确保证目标缓冲区有足够大空间以容纳转换完的字符串。此外,还必须使用正确的格式化符。如果使用了不正确的格式化符,会导致非预知的后果。下面是一个例子:

int n=10000;chars[10];sprintf(s,”%d”,n);// s中的内容为“10000”

到目前为止看起来还不错。但是,对上面代码的一个微小的改变就会使程序崩溃:

int n=10000;char s[10];sprintf(s,”%f”,n);// 看!错误的格式化符

在这种情况下,程序员错误地使用了%f格式化符来替代了%d。因此,s在调用完sprintf()后包含了一个不确定的字符串。要是能自动推导出正确的类型,那不是更好吗?

进入stringstream

由于n和s的类型在编译期就确定了,所以编译器拥有足够的信息来判断需要哪些转换。<sstream>库中声明的标准类就利用了这一点,自动选择所必需的转换。而且,转换结果保存在stringstream对象的内部缓冲中。你不必担心缓冲区溢出,因为这些对象会根据需要自动分配存储空间。

具体分析

istringstream类

描述:从流中提取数据,支持 >> 操作

这里字符串可以包括多个单词,单词之间使用空格分开

istringstream的构造函数原形:  istringstream::istringstream(string str);

初始化:使用字符串进行初始化

istringstream istr("1 56.7");  istr.str("1 56.7");//把字符串"1 56.7"存入字符串流中

使用:我们可以使用分解点获取不同的数据,完成 字符串 到 其他类型 的转换

常用成员函数:

str():使istringstream对象返回一个string字符串

举例:把字符串类型的数据转换为其他类型

#include 
#include
using namespace std; int main() { istringstream istr("1 56.7"); cout<
<
>n;//第一个数为整型数据,输出1 istr>>d;//第二个数位浮点数,输出56.7 //假设换下存储类型 istr>>d;//istringstream第一个数要自动变成浮点型,输出仍为1 istr>>n;//istringstream第二个数要自动变成整型,有数字的阶段,输出为56 //测试输出 cout<
<

举例2:把一行字符串放入流中,单词以空格隔开。之后把一个个单词从流中依次读取到字符串

#include 
#include
using namespace std; int main() { istringstream istr; string line,str; while (getline(cin,line))//从终端接收一行字符串,并放入字符串line中 { istr.str(line);//把line中的字符串存入字符串流中 while(istr >> str)//每次读取一个单词(以空格为界),存入str中 { cout<
<

ostringstream类

描述:把其他类型的数据写入流(往流中写入数据),支持<<操作

ostringstream的构造函数原形:  ostringstream::ostringstream(string str);

初始化:使用字符串进行初始化

ostringstream ostr("1234");  ostr.str("1234");//把字符串"1234"存入字符串流中

举例:

#include 
#include
using namespace std; int main() { //初始化输出字符串流ostr ostringstream ostr("1234"); cout<
<

上面这个实例可能看起来有点奇怪,其实是不了解put的使用,看看下面这段代码应该就懂了。

/*---------------------------------------------------------------------------- *** 建议:在用put()方法时,先查看当前put pointer的值,防止误写 ----------------------------------------------------------------------------*/      long curPos = ostr2.tellp(); //返回当前插入的索引位置(即put pointer的值),从0开始       cout << "curPos = " << curPos << endl;        ostr2.seekp(2); // 手动设置put pointer的值      ostr2.put('g');     // 在put pointer的位置上写入'g',并将put pointer指向下一个字符位置      cout << ostr2.str() << endl;

下面有个很实用很技巧的应用:

在类型转换中使用模板

你可以轻松地定义函数模板来将一个任意的类型转换到特定的目标类型。例如,需要将各种数字值,如int、long、double等等转换成字符串,要使用以一个string类型和一个任意值t为参数的to_string()函数。to_string()函数将t转换为字符串并写入result中。使用str()成员函数来获取流内部缓冲的一份拷贝:

template
void to_string(string & result,const T& t){ ostringstream oss;//创建一个流 oss<

这样,你就可以轻松地将多种数值转换成字符串了:

to_string(s1,10.5);//double到stringto_string(s2,123);//int到stringto_string(s3,true);//bool到string

可以更进一步定义一个通用的转换模板,用于任意类型之间的转换。函数模板convert()含有两个模板参数out_type和in_value,功能是将in_value值转换成out_type类型:

template
out_type convert(const in_value & t){ stringstream stream; stream<
>result;//向result中写入值 return result;}

这样使用convert():

double d;string salary;string s=”12.56”;d=convert
(s);//d等于12.56salary=convert
(9000.0);//salary等于”9000”

stringstream类

描述:是对istringstream和ostringstream类的综合,支持<<, >>操作符,可以进行字符串到其它类型的快速转换

stringstream的构造函数原形如下:  stringstream::stringstream(string str);

初始化:使用字符串进行初始化

stringstream str("1234");  str.str("1234");//把字符串"1234"存入字符串流中

作用:

  1. stringstream通常是用来做数据转换的

  2. 将文件的所有数据一次性读入内存

举例1:基本数据类型变字符串

/*基本数据类型变字符串*/  #include 
#include
#include
using namespace std; int main() { /*整型变字符串*/ int n = 10; string str; stringstream stream; stream << n; stream >> str; cout<
<
> str; cout<
<

举例2:字符串变基本数据类型

/*字符串变基本数据类型*/  #include 
#include
#include
using namespace std; int main() { /*字符串 变 double*/ double n; string str = "12.5"; stringstream stream; stream << str; stream >> n; cout<
<
> cStr; cout<
<

注意:

#include 
#include
using namespace std; int main(int argc,char *argv[]) { std::stringstream stream; string str; while(1) { //clear(),这个名字让很多人想当然地认为它会清除流的内容。 //实际上,它并不清空任何内容,它只是重置了流的状态标志而已! stream.clear(); // 去掉下面这行注释,清空stringstream的缓冲,每次循环内存消耗将不再增加! //stream.str(""); stream<<"sdfsdfdsfsadfsdafsdfsdgsdgsdgsadgdsgsdagasdgsdagsadgsdgsgdsagsadgs"; stream>>str; //测试输出每次循环,你的内存消耗增加了多少! cout<<"Size of stream = "<
<

由于stringstream构造函数会特别消耗内存,似乎不打算主动释放内存(或许是为了提高效率),但如果你要在程序中用同一个流,反复读写大量的数据,将会造成大量的内存消耗,因些这时候,需要适时地清除一下缓冲 (用 stream.str("") )。

另外不要企图用 stream.str().resize(0),或 stream.str().clear() 来清除缓冲,使用它们似乎可以让stringstream的内存消耗不要增长得那么快,但仍然不能达到清除stringstream缓冲的效果,内存的消耗还在缓慢的增长!,至于stream.flush(),则根本就起不到任何作用。

转载地址:http://efagx.baihongyu.com/

你可能感兴趣的文章
android下载封装类
查看>>
[node] 用 node-webkit 开发桌面应用
查看>>
Nginx访问控制和虚拟主机
查看>>
report widget not working for external users
查看>>
windows phone 摄像头得到图片是旋转90°
查看>>
三个半小时考试,三个小时调试-----巨容易写炸的nlogn数据结构专题
查看>>
ShellExecute的各种用法
查看>>
install s2plot -MacOS
查看>>
hadoop分布式存储(2)-hadoop的安装
查看>>
opengl中绘制文字的时候遇到了乱码问题
查看>>
得到自己账号的私钥
查看>>
yarn的学习-2-从 npm 迁移到 yarn-包管理工具
查看>>
Video about Agile Testing
查看>>
EL表达式隐式对象
查看>>
理解面向对象过程中创造一个对象的步骤
查看>>
资料汇总--java开发程序员必备技能
查看>>
grunt使用入门
查看>>
事件委托
查看>>
关于position:absolute定位实现响应式效果
查看>>
mongodb系列3 mongo mongoskin 连接以及连接数的问题进阶
查看>>