Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding Scanf - dealing with formatted input

Tags:

c

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?

like image 969
user1427661 Avatar asked Mar 11 '13 01:03

user1427661


People also ask

What is formatted input scanf in C?

In the C Programming Language, the scanf function reads a formatted string from the stdin stream.

How do I get scanf to ignore spaces?

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.

What is the correct format of scanf statement?

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.

What do you mean by formatted input?

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.


2 Answers

%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 '/')

like image 82
Cubbi Avatar answered Nov 15 '22 18:11

Cubbi


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 *.

like image 39
Jonathan Leffler Avatar answered Nov 15 '22 16:11

Jonathan Leffler