-2

I just found strange thing about sprintf() (c++ library function).

have a look at these two solutions

Time limit Exceeded solution

Accepted Solution

the only difference between them is that, I used

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

in TLE solution,
in AC solution I replaced above sprintf() with

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

You can also observe that ACed solution took only 0.01s and 2.8MB memory
but TLE solution took around 11.8MB check here

And one more thing program that gave TLE runs in 0s in IDEONE with extreme input data so is it a bug in CODECHEF itself

Somebody please explain me is this a bug or some considerable unknown operation is happening here.

Thanks in advance.

Community
  • 1
  • 1
hkbharath
  • 317
  • 7
  • 15
  • 1
    Neither of those code snippets contains `sscanf` at all. And the first `sscanf` is obviously wrong (trying to read into a character constant?) and the second one is questionable (is `n` a pointer?) – hobbs May 24 '14 at 19:13
  • sorry the issue was about `sprintf()` not `sscanf()`. and n is a integer variable which is always less than 100 – hkbharath May 24 '14 at 20:30

1 Answers1

0

First of all, the differences in the codes is not with sscanf, but with sprintf. A diff of the code explains:

--- 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();

Second, by explicitly packing the string with %c and '\0', you are reducing the size of the integer that can be stored in a by 1. You need to check the return of sprintf. man printf:

Upon successful return, these functions return the number of characters printed (not including the trailing '\0' used to end output to strings).

In your case you are most likely writing beyond the end of your a[4] string and are experiencing undefined results. With a[4] you have space for only 999\0. When you explicitly add %c + '\0', you reduce that to 99\0\0. If your number exceeds 99, then sprintf will write beyond the end of the string because you are explicitly packing an additional '\0'. In the original case sprintf(a,"%d",n); 999 can be stored without issue relying on sprintf to append '\0' as a[3].

test with n = 9999, sprintf will still store the number in a, but will return 5 which exceeds the space available a[4], meaning that the behavior of your code is a dice-roll at that point.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • ok i agree with your idea but why do I get TLE it should be Wrong Answer. Or is this unusual behaviours is caused by adding extra null character in the string ?? – hkbharath May 24 '14 at 20:23
  • The undefined behavior means that your code could do anything from print out the integer properly to segfault (it's just undefined). I do not know what the values of `n` are, but in your case I suspect they are in the 100 range. That means that at any point after sprintf returns more than 4, anything can happen later on in your code (like a read process reading beyond the end of a boundary and sucking up an additional 11.8 M of stuff you didn't expect. (it's just undefined). Insuring that you are not overwriting the end of `a[4]` is a good start to prevent surprises. – David C. Rankin May 24 '14 at 20:36