奇怪的行为或可能是c ++中sprintf()中的错误

时间:2014-05-24 18:59:33

标签: string pointers printf cstring

我刚发现sprintf()(c ++库函数)的奇怪之处。

看看这两个解决方案

Time limit Exceeded solution

Accepted Solution

他们之间的唯一区别是,我用了

sprintf(a,"%d%c",n,'\0');

在TLE解决方案中,
在AC解决方案中,我将sprintf()替换为

sprintf(a,"%d",n);

您还可以观察到ACed解决方案仅需0.01秒和2.8MB内存 但TLE解决方案大约需要11.8MB check here

另外还有一个让TLE运行的程序在IDEONE中以极端输入数据运行 这是CODECHEF本身的错误

有人请解释一下,这是一个错误,或者在这里发生了一些相当大的未知操作。

提前致谢。

1 个答案:

答案 0 :(得分:0)

首先,代码中的差异<{>>不与sscanf,但sprintf。代码的差异解释了:

--- ac.c        2014-05-24 14:31:18.074977661 -0500
+++ tle.c       2014-05-24 14:30:52.270650109 -0500
@@ -4,7 +4,7 @@

string mul(string m, int n){
char a[4];
-sprintf(a,"%d",n);
+sprintf(a,"%d%c",n,'\0');
int l1 = strlen(a);
//printf("len : %d\n",l1);
int l2 = m.length();

其次,通过使用%c'\0'明确打包字符串,您将减少可以存储在1中的整数的大小。您需要检查sprintf的返回值。 man printf:

成功返回后,这些函数会返回打印的字符数(不包括用于结束输出到字符串的尾随&#39; \ 0;用于结束输出到字符串)。

在您的情况下,您最有可能在a[4]字符串的末尾写作并且遇到未定义的结果。使用a[4],您只有999\0的空间。明确添加%c + '\0'后,您将其减少为99\0\0。如果您的号码超过99,那么sprintf将写入超出字符串末尾的内容,因为您明确地打包了一个额外的&#39; \ 0&#39;。在原始情况下sprintf(a,"%d",n); 999可以存储而不依赖于sprintf来附加&#39; \ 0&#39;作为[3]。

使用n = 9999进行测试,sprintf仍会将数字存储在a中,但会返回超出可用空间5的{​​{1}},这意味着您的代码行为是骰子 - 在那一点滚动。