I've been trying to scan integers with sscanf() from strings with leading zeros (e.g. '03').
However, it works fine but only until '07'. Starting with '08', the strings will be read as 0.
Below you'll find my code and the output. Thank you for your help!
#include <stdio.h>
#include <stdlib.h>
int main() {
char string_six[3] = "06";
char string_seven[3] = "07";
char string_eight[3] = "08";
char string_nine[3] = "09";
int six = -1;
int seven = -1;
int eight = -1;
int nine = -1;
sscanf(string_six, "%i", &six);
sscanf(string_seven, "%i", &seven);
sscanf(string_eight, "%i", &eight);
sscanf(string_nine, "%i", &nine);
printf("Six: %i\n",six);
printf("Seven: %i\n",seven);
printf("Eight: %i\n",eight);
printf("Nine: %i\n",nine);
return 0;
}
Output:
Six: 6
Seven: 7
Eight: 0
Nine: 0
CodePudding user response:
You need to use the conversion specifier %d instead of %i.
From the C Standard (7.21.6.2 The fscanf function)
d Matches an optionally signed decimal integer, whose format is the same as expected for the subject sequence of the strtol function with the value 10 for the base argument. The corresponding argument shall be a pointer to signed integer.
i Matches an optionally signed integer, whose format is the same as expected for the subject sequence of the strtol function with the value 0 for the base argument. The corresponding argument shall be a pointer to signed integer.
And (7.22.1.4 The strtol, strtoll, strtoul, and strtoull functions)
3 If the value of base is zero, the expected form of the subject sequence is that of an integer constant as described in 6.4.4.1, optionally preceded by a plus or minus sign, but not including an integer suffix.
And at last (6.4.4.1 Integer constants)
integer-constant:
decimal-constant integer-suffixopt
octal-constant integer-suffixopt
hexadecimal-constant integer-suffixopt
CodePudding user response:
"08" is being interpreted as the octal number 0, followed by a character that cannot be part of an octal number. If you do this instead:
int n;
char c;
sscanf("08", "%i%c", &n, &c);
you should observe n being set to 0 and c to '8'.
This behavior is by design: %i accepts decimal, octal, and hexadecimal numbers in the input, using the same syntax as C source code (that is, leading '0' means octal, leading '0x' or '0X' means hexadecimal).
If you don't want to accept octal or hexadecimal numbers, you can use %d instead; 'd' means to accept only decimal numbers. Similarly, %o accepts only octal numbers (but the '0' prefix is not required) and %x accepts only hexadecimal (but the '0x' or '0X' prefix is not required). There is no way to get sscanf to accept decimal and 0x-prefix hex but not also 0-prefix octal.
However, because the *scanf functions are broken as specified and should never be used at all, what you should really be doing is using strtol with third argument 10. (Pay careful attention to the part of the strtol manpage about checking for invalid input.) (There is no way to get strtol to accept decimal and 0x-prefix hex but not also 0-prefix octal, either.)
