Using scanf for Keyboard Input

Summary: Pass a variable address to scanf, not a variable value.

While printf is the most widely used output function, scanf is the most popular for input. The arguments and format strings passed to scanf resemble the arguments for printf, except for one requirement: the scanf function always takes pointers. You never pass a variable value to scanf, you always pass the variable address so that scanf can store data in the memory location that contains the input variable.

The first argument for scanf is always a format string. Additional arguments include the addresses of variables to which values will be assigned.

The program below demonstrates several ways to use scanf and various other I/O functions:

/* INPUT.C: Reads keyboard. */

#include <stdio.h>

#include <ctype.h>

main()

{

int num, c;

char name[80];

float rb;

puts( "** Type \"Name:\" and your name" );

scanf( "Name: %40s", name );

printf( "** You typed this:\n%s", name );

puts( "\n\n** Try again, with the gets function." );

fflush( stdin );

gets( name );

printf( "** You typed this:\n%s\n", name );

printf( "\n** Now type an integer.\n" );

scanf( "%i", &num );

sprintf( name, "** You typed this number: %i\n", num );

puts( name );

fflush( stdin );

printf( "** Enter a floating-point value.\n" );

scanf( "%f", &rb );

printf( "** The answer is %f or %e\n", rb, rb );

printf( "** Continue? Y or N\n" );

do

{

c = getchar();

c = tolower( c );

} while( c != 'y' && c != 'n' );

}

First, the puts function prints a string that requests input from the user. Then scanf reads the input:

puts( "** Type \"Name:\" and your name" );

scanf( "Name: %40s", name );

Unfortunately, the use of scanf for string input creates some difficulties. For one thing, you're forced to type Name: before typing the rest of the string. If you don't type Name:, scanf won't put a value into the name variable because it matches strings letter-for-letter.

A solution to this problem is to rewrite these lines as:

printf( "Type your name: " );

scanf( "%40s", name );

A second problem is that scanf reads the input stream until it finds a white-space character: a SPACE, TAB, or ENTER.

The following prompt appears on the screen:

** Type "Name:" and your name

You might type this (you must begin the line with "Name:"):

Name: F. Scott Fitzgerald

The next line takes effect:

printf( "** You typed this:\n%s", name );

Which prints the following line:

** You typed this:

F.

The string passed to the scanf function told it to expect "Name:" and then to read a string, storing it in the name variable.

Since the scanf function reads strings until it finds a white-space character, the value of name is F. In addition, the words Scott Fitzgerald are waiting in the input stream. To clear any stream, use the fflush function:

puts( "\n\n** Now try it again, with the gets function." );

fflush( stdin );

gets( name );

To clear the buffer associated with a stream (including disk files), call fflush, passing the pointer to the file or stream. In the example above, stdin is the standard input device, the keyboard.

The puts function acts like a limited version of printf. It prints a string to the standard output device, but can't insert formatted variable values. You pass it a string constant or the name of a string. Also, it always adds a new line to the end of the string it prints.

Summary: It is usually preferable to use gets when working with string input.

The gets function receives an entire line from the standard input device and places the line in an array of characters. It does not include the newline character typed by the user. It does, however, add a null to the end of the line, to make the series of characters into a string. When you're working with string input, gets is generally preferable to scanf.

For numeric values, scanf is the function of choice:

printf( "\n** Now type an integer.\n" );

scanf( "%i", &num );

sprintf( name, "** You typed the number: %i\n", num );

puts( name );

The format string %i forces scanf to treat the input as an integer. The second
argument is the address of the variable num.

The letter s in sprintf marks it as a string function. (There is also a sscanf function that handles strings, but we won't discuss it here.) Instead of printing the format string to the screen, as printf would do, sprintf prints the results to another string. Note that scanf requires the address of num, but sprintf uses its value.

The next scanf in program INPUT.C treats the input as a floating-point number:

scanf( "%f", &rb );

printf( "** The answer is %f or %e\n", rb, rb );

If you enter –555.12, the computer responds:

** The answer is -555.119995 or -5.551200e+002

Finally, the program uses getchar to receive a character from the input stream:

printf( "** Continue? Y or N\n" );

do

{

c = getchar();

c = tolower( c );

} while( c != 'y' && c != 'n' );

The getchar function returns a character. That value, in turn, is passed to tolower, which converts any uppercase characters to lowercase (in case the CAPS LOCK key is on). Then, the byte is assigned to the variable c. The do loop continues processing characters until you type y or n and press ENTER. The program then ends. This simple example ends no matter which key (y or n) you press. A real program would take some action based on the value returned by the getchar function.