在C语言中,我们如果希望进行格式化进行输出,一般我们用 sprintf 来字符串。
例如:
char temp[100];
sprintf(temp, "%s", "HelloWorld" );
通常上面的操作应该没有任何问题。但是,在某些情况下,是有意想不到的结果产生。
比如:在进行出错信息进行输出时,我们采取如下写法:
char temp[64];
sprintf( temp, "Error at file %s , line %d , column %d , Message: %s", strFile, lineNumber, columnNumber, strMessage);
一般情况下,如果出错信息较少,上面程序没有任何问题,如果出错信息很长,上面的数据会越界,从而导致改写其他内存中的内容,引发一些你想象不到的错误。
这时,估计你的解决方案就是增大temp的空间,比如:temp[1000]。
没错,这样改正之后,造成上面出错的概率会较少很多,但是还没有完全解决此问题。
在用户如果提供比较多的出错信息时,还是有问题产生。
那么我们有没有办法来完全解决此问题呢????
在C++中,有个string类,可以用来动态存储字符串,它会根据当前字符串的长度来调整它的长度。
且string.begin() 相当于char*指针。
说到这,你是不是有一种冲动改写上面的程序?( I so ).
string strTemp;
strTemp.reserve(64); //优化string的内存分配策略
sprintf( strTemp.begin(), "Error at file %s , line %d , column %d , Message: %s", strFile, lineNumber, columnNumber, strMessage);
编译通过,^_^(窃喜) !
测试一下,在较短的出错消息(没有超过64)时,没有任何问题,但是在超过64之后,会进行出错!!!(是不是比上面的比较‘安全’? )
为什么上面会出错???string 不是动态进行扩展存储空间吗?
没错,如果超过64之后,string会进行动态分配空间,由于string一般确保它的存储空间连续性,所以它是重新分配一块足够大的空间,然后将数据copy过去,这个过程类似于realloc 来分配空间。这必然导致我们现在的string.begin()和以前的begin()所指向的地址不一样。
而我们sprintf指向的地址是以前的string.begin(),不是重新分配之后的空间,一般以前分配的空间会被释放,所以会导致程序出错。
哪我们还有没有别的办法来改善上面的问题???
MFC中的CString类有个成员函数Format就可以用来格式化字符串,并且可以动态扩展此字符串。
是不是很酷???
但是,对于我来说,凡是不在UI地方(即界面显示部分),尽量避免使用MFC中的内容,使得以后的移植比较方便(可能有点杞人忧天的感觉),嘿嘿!!
难道就没有别的解决方案???
毕竟格式化字符串是非常常见的事情,连C中都有一个特定的函数来完成(sprintf)。难道C++里面就没有解决方案吗?
记得在C++的IO输出流中,标准的cout,就可以用来格式化输出到屏幕。
如果是fstream就可以用于格式化输出到文件中。(说到这里,好像记得有个字符串流?)
赶快进行msdn搜索,呵呵,找到了这个家伙。
不再多说了,直接进行示例.
std::ostringstream strOut( ios_base::out);
strOut << "Error at file " << file
<< " line " << lineNumber << " column " << columnNumber << endl;
strOut << " Message:" << CErrorMsg(errorCode).getErrorMsg() << endl;
strOut << " UserMessage: " << errStr << endl;
然后我们可以把上面的字符串提取出来.
string strValue = strOut.str();
到了这一步,你应该知道如何来使用string类型的值了吧。
呵呵,终于将它进行解决了,并且解决的如此彻底( 嘘,不要告诉别人,告诉你一个秘密,以前碰到此问题,没有很好的进行解决过,只是适当的将temp的数组增大,即将出错的概率进行了降低!)。
什么??? 你无法编译???? 加入相关头文件不就可以了吗???不知道哪个头文件,那去msdn中查找啊。
什么你没有查到?耐心一点会有的(不过在比较隐蔽的地方)。
Use <sstream> to work with objects of type basic_string.
Use <strstream> work with char *, which are C strings
即:在上面中,我们只要加入下面一句就可以了:
#include <sstream>