分享
 
 
 

如何安全动态格式化字符串

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

在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>

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有