If a line does not match a [fsv]scanf format, does scanf guarantee not to touch the provided pointers that are not matched?
For example, if
int int1 = 3;
int int2 = 5;
sscanf(line, "%d %d", &int1, &int2);
returns 0, are the integers guaranteed to be still 3 and 5, or can int1 have been changed?
You are correct: sscanf indeed does not "move", because there is nothing to move. If you need to scan a bunch of ints, you can use strtol - it tells you how much it read, so you can feed the next pointer back to the function on the next iteration.
sscanf takes as arguments a string to scan, a format string, and pointers to variables where to store the results of the scan. So, your 0 and 1 numbers would be stored on the corresponding variables, assuming the scan was successful. EAX contains the return value.
In the case of printf() function the %n assign the number of characters printed by printf(). When we use the %n specifier in scanf() it will assign the number of characters read by the scanf() function until it occurs. Key points: It is an edit conversion code.
The scanf function reads data from standard input stream stdin into the locations given by each entry in the argument list. The argument list, if it exists, follows the format string. The sscanf function reads data from buffer into the locations given by argument list.
The short answer is yes, in your case you can guarantee that int1
and int2
have not changed.
However, I would advise against relying on this behaviour, as it's likely to produce code that is difficult to read - and because:
The long answer is it depends on your format string. Looking at the C11 standard for fscanf
(s7.21.6.2.16), we have:
The fscanf function returns the value of the macro EOF if an input failure occurs before the first conversion (if any) has completed. Otherwise, the function returns the number of input items assigned, which can be fewer than provided for, or even zero, in the event of an early matching failure.
Critically important is this definition of input items from later in 7.21.6.2:
An input item is defined as the longest sequence of input characters which does not exceed any specified field width and which is, or is a prefix of, a matching input sequence
So. The number returned by scanf is the number of items read from the stream, not the number of pointers written to.
Additionally relevant is 7.21.6.2.2:
If the format is exhausted while arguments remain, the excess arguments are evaluated (as always) but are otherwise ignored.
The behaviour of ignoring arguments that aren't written to is also made explicit in an example at the end of that section:
In:
#include <stdio.h> /* ... */ int d1, d2, n1, n2, i; i = sscanf("123", "%d%n%n%d", &d1, &n1, &n2, &d2);
the value
123
is assigned tod1
and the value3
ton1
. Because%n
can never get an input failure the value of3
is also assigned ton2
. The value ofd2
is not affected. The value1
is assigned toi
.
In case you're not familiar with %n
, it's "the number of characters read from the stream so far".
This is a great example to illustrate your question - here we have three pointers written to, and one pointer untouched. But, fscanf
only returns 1 here - because it only assigned one "input item" from the stream.
So, in your example, yes, if you've got %d %d
and you pass it something which causes 0 reads, then yes, the pointers will be untouched.
But, if you've got a %n
in there, then your function could still return 0 or EOF while still consuming some input and writing to pointers. For example:
sscanf("aaa","aaa%n%d",&n1,&n2);
This writes 3
to n1
, leaves n2
untouched, and returns EOF
. And:
sscanf("aaa bbb","aaa%n%d",&n1,&n2);
This writes 3
to n1
, leaves n2
untouched, and returns 0.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With