rashok
rashok

Reputation: 13474

C sscanf behaviour

I am trying to understand sscanf behaviour for that I have executed below two program.

void main()
{
        char *a = "225.311";
        int x = 0, y = 0;
        sscanf(a, "%d.3%d", &x, &y);
        printf("x is %d, y is %d\n", x, y);
}

output is

x is 255, y is 11

Below program is not working as per my expectation.

void main()
{
        char *a = "225.311";
        int x = 0, y = 0;
        sscanf(a, "%d5.3%d", &x, &y);
        printf("x is %d, y is %d\n", x, y);
}

I am expecting 25,11, but the output is

x is 255, y is 0

I am expecting sscanf behaviour should exact same as sprintf in reverse manner. But its not working in my second program. If the format specifed is %d5.3%d, then it has to consider 5 as delimeter. But its not considering and reading all digits for x, and then dot is not matching with 5.3%d so it quits there.

Can somebody please explain this.

Upvotes: 0

Views: 120

Answers (2)

chux
chux

Reputation: 154218

Suggest using a different format and checking the results of sscanf(). Also to distinguish fractions like "0.001" and "0.1", note positions.

const char *a = "225.0311";
int ipart = 0;
unsigned fractionpart;
int n1, n2;
if (sscanf(a, "%d.%n%u%n", &ipart, &n1, &fractionpart, &n2) != 2) {
  Handle_BadInput();
}

printf("ipart is %d, fractionpart is %0*u\n", ipart, n2 - n1, fractionpart);
// ipart is 225, fractionpart is 0311

As @ajay discusses, "%d5.3%d" looks for an int, then "5.3" then another int.

Upvotes: 1

ajay
ajay

Reputation: 9680

That's because the %d conversion specifier means sscanf will keep reading from the buffer pointed to by a till it encounters a non-numeric character in the buffer. This means that %d will consume up till 225 in the string literal "225.311" in your second example.

If the format specifed is %d5.3%d, then it has to consider 5 as delimeter.

No, that's not true. 5 in the format string means sscanf will match it exactly (after reading an int) in the buffer it reads from. If it fails to match it, then sscanf will return and the value of y is left unchanged. You can check for this by storing the result of sscanf. The return value is equal to the number of input items successfully matched and assigned.

char *a = "225.311";
int x = 0, y = 0;
int retval = sscanf(a, "%d5.3%d", &x, &y);
printf("%d\n", retval); // prints 1

However, note that if the sequence of numeric characters in the buffer is too long to fit into an int, then the behaviour is undefined because of signed integer overflow.

Upvotes: 4

Related Questions