Reputation: 345
I just started learning the very basics of c++, I have experience with vb.net and c#
Now I thought to get the basics covered some Project euler problems would be a good excercise. I ran into a very strange problem by trying to solve Problem 4, probably because of a lack of understanding of c++ yet.
I got 2 scenario's, one is working, one is not(> the a variable just jumps from 999 to 768 when the sprintf command is executed as shown below), now my question is: Why is this happening in solution 1? The only difference is the loop variables a and b are declared before the loop as in solution 2 they are declared with the loop.
Solution 1 (not working):
int a =999;
int b =999;
int lb = 100;
int c = 0;
char strNumber[6];
int result = 0;
int ra = 0;
int rb = 0;
for (a=999; a>=100; a--){
for (b = a; b>=lb; b--){
c = a * b;
sprintf(strNumber, "%d", c);
if (isPalindrome(strNumber)){
if (c > result){
result = c;
lb = b;
rb = b;
ra = a;
}
b = 0;
}
}
}
Solution 2 (working):
int lb = 100;
int c = 0;
char strNumber[6];
int result = 0;
int ra = 0;
int rb = 0;
for (int a=999; a>=100; a--){
for (int b = a; b>=lb; b--){
c = a * b;
sprintf(strNumber, "%d", c);
if (isPalindrome(strNumber)){
if (c > result){
result = c;
lb = b;
rb = b;
ra = a;
}
b = 0;
}
}
}
Upvotes: 1
Views: 135
Reputation: 361412
Actually both has same problem, namely undefined behavior. The problem stems from here:
char strNumber[6];
This variable cannot accomodate the value of 999 x 999
in string representation, bevause there is also a null character '\0'
at the end. So when you call sprintf
to convert the integer into its string representation, right there inside the function it invokes undefined behaviour when it tries to put the character'\0'
at index 6
, because the indices 0
to 5
are already occupied by six digits of 998001
which is the product of 999 x 999
.
You should define it at least of size 7
:
char strNumber[7]; //one char for null-character.
As for why your second code is working is because you're being lucky (rather unlucky). That is what undefined behavior means: anything could happen. It may run, or may not. Neither the language specification nor the compiler gives any guarantee of the behavior, hence undefined behavior.
As @James Kanze pointed out in the comment that the real solution is to forget about sprintf
, and better use std::ostringstream
and std::string
as:
#include <sstream> //for std::ostringstream
#include <string> //for std::string
std::ostringstream ss;
ss << number;
std::string s = ss.str(); //get the string representation of the number
Upvotes: 4
Reputation: 206689
The first time through the loop, c
is going to be a 6-digit number (999²).
The sprintf(strNumber, "%d", c);
will thus write 7 chars to strNumber
: the six digits and the famous null terminator. Since you only reserved six chars for strNumber
, that last write will clobber something.
It happens not to appear to clobber something important in your second case, but that's just "luck", your code's behavior is undefined in both cases.
Reserve an extra char in strNumber
and both versions should work the same as far as I can tell.
Upvotes: 3