I'm trying to figure out exactly how scanf
works. If I code something like this:
scanf("%s %d %f", name, &age, &wage);
enter this as standard input:
james 20 34000.25
and then print out name, age, and wage respectively, I get exactly what one would expect, the same thing as I put into standard input. However, if I enter something like this:
scanf("%s/%d/%f", name, &age, &wage);
and I enter this as standard input:
james/20/34000.25
I get the string james/20/34000.25
for the string value and 0 and 0.00000 respectively for the integer and float values. I thought scanf
would treat the slashes the same as it would treat the spaces in the first version. How would I get it so if a user enters a slash separated value, I can appropriately assign the values to variables?
In the C Programming Language, the scanf function reads a formatted string from the stdin stream.
The secret to getting scanf to perform this way is to put a blank in the format string before the %c format specifier. The blank tells scanf to skip white space and it will actually skip any number of white space characters before reading and storing a character.
The scanf("%d",&number) statement reads integer number from the console and stores the given value in number variable. The printf("cube of number is:%d ",number*number*number) statement prints the cube of number on the console.
Several library functions help you convert data values from text sequences that are generally readable by people to encoded internal representations. You provide a format string as the value of the format argument to each of these functions, hence the term formatted input.
%s
matches non-whitespace characters (and it's a greedy match: it's not going to backtrack to see if some other match is possible) To match non-forward slash characters, use %[^/]
(also, note that the space character (match zero or more whitespace characters) in the scanf string has a very different behavior from a non-space non-percent character, such as '/'
(match exactly '/'
)
To match both the space-separated and the slash-separated inputs, you'll need a modestly complex format string:
if (scanf("%[^ /]%*1[ /]%d%*1[ /]%f", name, &age, &wage) == 3)
...data was read properly...
else
...something went wrong...
The first conversion specification is a scan set that accepts a sequence of non-blanks, non-slashes (so it will stop at the first blank or slash). It would be best to specify an upper bound on how many characters will be accepted so as to avoid stack overflow; for example, if char name[32];
, then %31[^ /]
(note the off-by-one). The second conversion specification %*1[ /]
accepts a single character (1
) that is either a blank or slash [ /]
, and does not assign it to any variable (*
). The third conversion specification is a standard numeric input, skipping leading blanks, allowing for negative numbers to be entered, etc. The fourth conversion specification is the same as the second, and the fifth is a standard format for a float
(which means that 34000.25
with 7 significant digits is at the outer end of the range of representable values).
Note that the 'something went wrong' part has a difficult time reporting the error coherently to the user. This is why many people, myself included, recommend against using scanf()
or fscanf()
and prefer to use fgets()
or perhaps POSIX getline
to read a line from the user and then use sscanf()
to analyze it. You can report the problems much more easily. Also note that the return value from scanf()
is the number of successful assignments; it does not count the conversion specifications that include *
.
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