分类: C/C++
2007-04-26 12:41:36
sprintf这个函数,在msdn上的解释是
Write
formatted data to a string,即将格式化数据写入字符串。其原型是这样的:
int sprintf( char
*buffer, const char *format [,
argument] ... );
buffer为存放格式化后的字符串的缓冲区
format为格式化字符串,比如整形就是 %d,浮点就是%f,字符串就是%s
比如:
char buffer[256];
char res[256];
int result = 200 * 5;
float f = 3.1415926 * 8;
sprintf(buffer, “The result is %d”, result);
sprintf(res, “%s”, f);
sprintf(buffer, “This is just a test”); // 对于常量字符串,一般情况下这样也可以,我说的是一般,可如果不是一般,而是二般,就可能导致致命的错误,我就遇到了这个二般。
在公司的一个项目中,因为需要要用c写cgi程序。Cgi程序大家都知道,是网站后台程序,用来生成动态的页面。在网页中,我们常常会看到这样的情况,如果你输入的是中文,那么通过网页传递的参数就会变成了类似“%DC%BD%C8%D8%C3%C3%C3%C3”这样的字符串,为了获取传递过来的参数(通过截取从stdin获取的字符串),用到了sprintf这个函数。在程序中,其中获取了一个字符串参数就是类似“%DC%BD%C8%D8%C3%C3%C3%C3”这样的字符串,我用这样的代码把这个获取的字符串填充到缓冲区中:
char buffer[256];
char param[] = “%DC%BD%C8%D8%C3%C3%C3%C3”;
sprintf(buffer, param); // 我当时想,获取的这个param是个字符串,于是我就省了中间那个”%s”,结果正是这样偷懒,造成了重大的错误,而且历时一个多星期都没有找出来这个致命的错误。把这段代码中的字符串放进去一看:
sprintf(buffer, “%DC%BD%C8%D8%C3%C3%C3%C3”);
你就会发现,本来我想的是把这个字符串“%DC%BD%C8%D8%C3%C3%C3%C3”复制到buffer中,结果,这个字符串比较特殊,里面带有sprintf格式化的%d,%c,有时候会有%f,这样sprintf就把它当作格式化的字符串了,结果在生成的网页中莫名其妙的出现了Internal
Server Error的错误,查看Apache错误日志,上面都是C
Run-Time Error R6002
floating-point support not loaded, 我一直在想,我没有用到浮点数呀,怎么查都没有想到最后的问题居然就出现在这个sprintf上,在R6002这个错误中,查看MSDN,上面有这么一个解释:
A
format string for a printf or scanf function contained a
floating-point format specification, and the program did not contain any
floating-point values or variables.
上面的意思大概就是你在printf或者scanf中指定了浮点的格式化串,但是却没有提供浮点变量,对照这个sprintf(buffer, “%DC%BD%C8%D8%C3%C3%C3%C3”);
我们发现如果在这个sprintf中有%F的话,那么后面又没有提供浮点变量或常量值,就会出现这个错误。
问题终于找到了,于是把原来的sprintf的代码都改一下,中间加一个%s即可,
sprintf(buffer, “%s”, “%DC%BD%C8%D8%C3%C3%C3%C3”);
这样就不会让sprintf有“误会”了。你再把这个buffer打印出来就是:
printf(“%s”, buffer);
看到的结果就是%DC%BD%C8%D8%C3%C3%C3%C3。这个是在网页的url中汉字的编码,百度上采用的字符集是gb2312,google采用的uft-8。至于如何识别这一串16进制数,请参看我的另一篇文章: