C++学习笔记:ostringstream

当初写程序的时候需要动态的根据一个int型的索引来产生一个字符串,试了很多方法都不能如愿,我当时想到的是使用#和##宏:

#define str(i) #i

#define STR(i) str(string)##str(i)

这样当我写:

int i=3;

cout<<STR(3)<<endl;

时,我期待着给我输出string3,事实是输出的为stringi。。。

ostringstream就可以实现我的目的,下面有详细的介绍,原文地址:《ostringostream

***********************************************************************************************************************************************************

当存在未知数据大小的时候,可以使用 ostringstream 来代替 sprintf , 避免总是申请大量的缓冲区.用法可以参照下面转载的文章.

另外解决今天遇到的一个问题,如果要重复使用一个ostringstream对象,并且需要在下次使用前清空缓冲区,则可以使用str()函数重设置缓冲区. 如:
ostringstream  osSql;
//first time
osSql<<"SELECT  COUNT(*) FROM t_XXXX";
...
clsConnection.Query( osSql );
....
//second time
osSql.str("");//重新使用一个空的缓冲区
osSql<<"INSERT INTO **********"<<  strBigText  ;
.......
以下转载 一篇关于 ostringstream 的用法 的文章
在写程序的时候,我们往往需要对字符串进行格式化, 比如写SQL语句的时候. 在ANSI C 中可以sprintf(), 在MFC中可以用CString::Format()对字符串进行格式化. 但前者无法实现字符串的动态增加,比如你定义的字符缓存为100个字节,如果你格式化以后的内容超出了100个字节,那边后面的内容就无法看见. 所以一般来讲都为定义一个足够的字符缓冲,但这样的效率是很差的. 后者虽然可以解决这个问题,但有一点, 他和前者一样,存在着安全隐患. 比如下面的代码
       char buf[100]={0};
       const char* str = "string";
       sprintf(buf,"this is a string : %s , %s", str);
或者
       CString s;
        s.Format("this is a string: %s, %s",str);
前面那个%s对应第一个参数str,那么第二个%s呢, 指针指向何方? 如果你幸运的话,什么事也不会发生或者你仅仅获得一个你觉得莫名奇妙的字符串值. 但更严重的情况呢, 不用说----访问越界!你的程序就等着迎接臭名远扬的Windows红框吧!
       如果你使用STL的sstream,那么一切将归于寂然:
      #include<sstream>
...
      ostringstream str;
     str<<"this is a str" << "string"<<"and this is a interger<<3<<endl;
     你不必考虑字符串的增长问题, 也不用在写程序时去一一匹配你的format函数的format参数是否一一匹配(如果你的参数很多,那么这项检查工作将是一个让你头痛万分的工作). 
     一切都是如此的简单. 
    如果你想获取格式化好的字符串, 通过ostringstream::str()函数就可以返回一个string对象, 调用string::c_str() 或string::data()函数就可以获得一个指向字符缓冲的char*变量.
    另外, 我坚决建议用string替代CString . 因为CString在设计时考虑到效率问题, 内存是重复利用的, 即:一个进程中所有的CString对象都使用同一个内存缓冲区,且这个内存区运行时不会释放,直到进程结束为止. 如果缓冲不够,他会无限制往上增长. 如果你设计的系统是一个7*24运行的系统且字符串分析工作量很大,程序中产生了大量的CString对象的话, 你可能会发现你的内存会不断的上涨. string同样有一个很优秀且高效率的内存管理机制,但他不会死守着你的内存不放,这一点你看看STL的源码就知道了. 

     如果你觉定采用STL,那么建议你使用VC7.0作为开发环境或者GCC , 因为这两款开发工具对STL支持是还算不错.尤其是GCC. 如果你坚持用VC6的话,那么你最好打上SP5补丁包, VC6对STL的支持不够理想. 

**************************************************************************************************************************************************************************

下面的文章介绍ostringstream、istringstream、stringstream,

原文地址:http://zhouruijun163.blog.163.com/blog/static/10771562008279344176/

C++引入了ostringstream、istringstream、stringstream这三个类,要使用他们创建对象就必须包含sstream.h头文件。 

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

  istringstream类是从istream(输入流类)和stringstreambase(c++字符串流基类)派生而来,ostringstream是从ostream(输出流类)和stringstreambase(c++字符串流基类)派生而来,stringstream则是从iostream(输入输出流类)和和stringstreambase(c++字符串流基类)派生而来。 

  他们的继承关系如下图所示:



  istringstream是由一个string对象构造而来,istringstream类从一个string对象读取字符。 
  istringstream的构造函数原形如下: 
  istringstream::istringstream(string str);

//程序作者:管宁 
//站点:www.cndev-lab.com 
//所有稿件均有版权,如要转载,请务必著名出处和作者 
#include<iostream> 
#include<sstream> 
usingnamespacestd; 
intmain() 

istringstreamistr; 
istr.str("156.7",); 
//上述两个过程可以简单写成istringstreamistr("156.7");
cout<<istr.str()<<endl; 
inta; 
floatb; 
istr>>a; 
cout<<a<<endl; 
istr>>b; 
cout<<b<<endl; 
system("pause"); 
}


  上例中,构造字符串流的时候,空格会成为字符串参数的内部分界,例子中对a,b对象的输入"赋值"操作证明了这一点,字符串的空格成为了整型数据与浮点型数据的分解点,利用分界获取的方法我们事实上完成了字符串到整型对象与浮点型对象的拆分转换过程。 

  str()成员函数的使用可以让istringstream对象返回一个string字符串(例如本例中的输出操作(cout<<istr.str();)。

  ostringstream同样是由一个string对象构造而来,ostringstream类向一个string插入字符。 
  ostringstream的构造函数原形如下: 
  ostringstream::ostringstream(string str); 

  示例代码如下:

//程序作者:管宁 
//站点:www.cndev-lab.com 
//所有稿件均有版权,如要转载,请务必著名出处和作者 
#include<iostream> 
#include<sstream> 
#include<string> 
usingnamespacestd; 
intmain() 

ostringstreamostr; 
//ostr.str("abc");//如果构造的时候设置了字符串参数,那么增长操作的时候不会从结尾开始增加,而是修改原有数据,超出的部分增长
ostr.put('d'); 
ostr.put('e'); 
ostr<<"fg"; 

stringgstr=ostr.str(); 
cout<<gstr; 
system("pause"); 
}


  在上例代码中,我们通过put()或者左移操作符可以不断向ostr插入单个字符或者是字符串,通过str()函数返回增长过后的完整字符串数据,但值得注意的一点是,当构造的时候对象内已经存在字符串数据的时候,那么增长操作的时候不会从结尾开始增加,而是修改原有数据,超出的部分增长。

  对于stringstream了来说,不用我多说,大家也已经知道它是用于C++风格的字符串的输入输出的。 

  stringstream的构造函数原形如下: 

  stringstream::stringstream(string str);

  示例代码如下:

//程序作者:管宁 
//站点:www.cndev-lab.com 
//所有稿件均有版权,如要转载,请务必著名出处和作者 
#include<iostream> 
#include<sstream> 
#include<string> 
usingnamespacestd; 

intmain() 

stringstreamostr("ccc"); 
ostr.put('d'); 
ostr.put('e'); 
ostr<<"fg"; 
stringgstr=ostr.str(); 
cout<<gstr<<endl; 

chara; 
ostr>>a; 
cout<<a 

system("pause"); 
}


  除此而外,stringstream类的对象我们还常用它进行string与各种内置类型数据之间的转换。 

  示例代码如下:

//程序作者:管宁 
//站点:www.cndev-lab.com 
//所有稿件均有版权,如要转载,请务必著名出处和作者 
#include<iostream> 
#include<sstream> 
#include<string> 
usingnamespacestd; 

intmain() 

stringstreamsstr; 
//--------int转string-----------
inta=100; 
stringstr; 
sstr<<a; 
sstr>>str; 
cout<<str<<endl; 
//--------string转char[]--------
sstr.clear();//如果你想通过使用同一stringstream对象实现多种类型的转换,请注意在每一次转换之后都必须调用clear()成员函数。
stringname="colinguan"; 
charcname[200]; 
sstr<<name; 
sstr>>cname; 
cout<<cname; 
system("pause"); 
}

接下来我们来学习一下输入/输出的状态标志的相关知识,C++中负责的输入/输出的系统包括了关于每一个输入/输出操作的结果的记录信息。这些当前的状态信息被包含在io_state类型的对象中。io_state是一个枚举类型(就像open_mode一样),以下便是它包含的值。 

  goodbit 无错误 

  Eofbit 已到达文件尾 

  failbit 非致命的输入/输出错误,可挽回 

  badbit 致命的输入/输出错误,无法挽回 

  有两种方法可以获得输入/输出的状态信息。一种方法是通过调用rdstate()函数,它将返回当前状态的错误标记。例如,假如没有任何错误,则rdstate()会返回goodbit. 

  下例示例,表示出了rdstate()的用法:

//程序作者:管宁 
//站点:www.cndev-lab.com 
//所有稿件均有版权,如要转载,请务必著名出处和作者 

#include<iostream> 
usingnamespacestd; 

intmain() 

inta; 
cin>>a; 
cout<<cin.rdstate()<<endl; 
if(cin.rdstate()==ios::goodbit) 

cout<<"输入数据的类型正确,无错误!"<<endl; 

if(cin.rdstate()==ios_base::failbit) 

cout<<"输入数据类型错误,非致命错误,可清除输入缓冲区挽回!"<<endl; 

system("pause"); 
}

 

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页