Input and Output in C: Stream Functions

Input and Output in C

The standard way of handling all input and output is done with streams in C programming regardless of where input is coming from or where output is going to. This approach has definite advantages for the programmer. A library package has been evolved which is known as known as the Standard I/O Library which is used in any C program by using stdio.h header. Of course, now that we know its importance, it is essential that we understand what streams are and how they work. First, however, we need to understand exactly what the terms input and output mean in context of C.

The C programming language provides input and output support using library functions, which gives an advantage to system designers to tailor their input and output on their own.

The rest of the article is organized as below.

Table of Contents

What Exactly is Program Input/Output?

A C program keeps data in random access memory (RAM) while executing. This data is in the form of variables, structures, and arrays that have been declared by the program. The question is where did this data come from, and what can the program do with it?

  1. Data can come from some location external to the program. Data moved from an external location into RAM, where the program can access it, is called input. The keyboard and disk files are the most common sources of program input.
  2. Data can also be sent to a location external to the program; this is called output. The most common destinations for output are the screen, a printer, and disk files.

Input sources and output destinations are collectively referred to as devices. The keyboard is a device; the screen is a device, and so on. Some devices (the keyboard) are for input only, others (the screen) are for output only, and still others (disk files) are for both input and output. Whatever the device, and whether it’s performing input or output, C carries out all input and output operations by means of streams.

What is a Stream?

A stream is a sequence of characters. More exactly, it is a sequence of bytes of data. A sequence of bytes flowing into a program is an input stream; a sequence of bytes flowing out of a program is an output stream. By focusing on streams, we don’t have to worry as much about where they’re going or where they originated.

The major advantage of streams, therefore, is that input/output programming is device independent. Programmers don’t need to write special input/output functions for each device (keyboard, disk, and so on). The program sees input/output as a continuous stream of bytes no matter where the input is coming from or going to.

Every C stream is connected to a file. In this context, the term file doesn’t refer to a disk file. Rather, it is an intermediate step between the stream that the program deals with and the actual physical device being used for input or output. For the most part, the beginning C programmer doesn’t need to be concerned with these files, because the details of interactions between streams, files, and devices are taken care of automatically by the C library functions and the operating system.

Modes of Streams in C Programming

Streams in C programming can be divided into two modes: text and binary.

Text Stream

A text stream consists only of characters, such as text data being sent to the screen. Text streams are organized into lines, which can be up to 255 characters long and are terminated by an end-of-line, or newline, character. Certain characters in a text stream are recognized as having special meaning, such as the newline character.

Binary Stream

A binary stream can handle any sort of data, including, but not limited to, text data. Bytes of data in a binary stream aren’t translated or interpreted in any special way; they are read and written exactly as-is. Binary streams are used primarily with disk files.

Predefined Streams in ANSI C Language

ANSI C has three predefined streams, also referred to as the standard input/output files. If you’re programming for an IBM-compatible PC running DOS, two additional standard streams are available to you. These streams are automatically opened when a C program starts executing and are closed when the program terminates. The programmer doesn’t need to take any special action to make these streams available. Table lists the standard streams and the devices they normally are connected with. All five of the standard streams are text-mode streams.

NAMESTREAMDEVICE
stdinStandard InputKeyboard
stdoutStandard OutputScreen
stderrStandard ErrorScreen
stdprn*Standard PrinterPrinter (LPT1)
stdaux*Standard AuxiliarySerial Port (COM1)
The five standard streams. (*) Supported only under DOS

Whenever we have to use the printf() or puts() functions to display text on-screen, we use the stdout stream. Likewise, when we use gets() or scanf() to read keyboard input, we use the stdin stream. The standard streams are opened automatically, but other streams, such as those used to manipulate information stored on disk, must be opened explicitly.

Stream Functions in C

The C standard library has a variety of functions that deal with stream input and output. Most of these functions come in two varieties: one that always uses one of the standard streams, and one that requires the programmer to specify the stream.

These functions are listed in table below. This table doesn’t list all of C’s input/output functions.

Uses One of the Standard StreamsRequires a Stream NameDescription
printf()fprintf()Formatted output
vprintf()vfprintf()Formatted output with a variable argument list
puts()fputs()String output
putchar()putc(), fputc()Character output
scanf()fscanf()Formatted input
gets()fgets()String input
getchar()getc(), fgetc()Character input
perror()String output to stderr only
The standard library’s stream input/output functions.

All these functions require that we include stdlib.h. The function perror() may also require stdlib.h. The functions vprintf() and vfprintf() also require stdargs.h. On UNIX systems, vprintf() and vfprintf() may also require VARARGS.H. The compiler”s Library Reference will state whether any additional or alternative header files are needed.

An Example of Stream functions

The short program that demonstrates the equivalence of streams input and output.

#include  <stdio.h>

 main()
 {
 char buffer[256];

 //Input a line, then immediately output it.

  puts(gets(buffer));

 return 0;
 }

On line 10, the gets() function is used to input a line of text from the keyboard (stdin). Because gets() returns a pointer to the string, it can be used as the argument to puts(), which displays the string on-screen (stdout). When run, this program inputs a line of text from the user and then immediately displays the string on-screen.

Accepting Keyboard Input

Most C programs require some form of input from the keyboard (that is, from stdin). Input functions are divided into a hierarchy of three levels: character input, line input, and formatted input.

Character Input

The character input functions read input from a stream one character at a time. When called, each of these functions returns the next character in the stream, or EOF if the end of the
file has been reached or an error has occurred. EOF is a symbolic constant defined in stdio.h as -1. Character input functions differ in terms of buffering and echoing.

  1. Some character input functions are buffered. This means that the operating system holds all characters in a temporary storage space until you press Enter, and then the system sends the characters to the stdin stream. Others are unbuffered, meaning that each character is sent to stdin as soon as the key is pressed.
  2. Some input functions automatically echo each character to stdout as it is received. Others don’t echo; the character is sent to stdin and not stdout. Because stdout is assigned to the screen, that’s where input is echoed.

The uses of buffered, unbuffered, echoing, and nonechoing character input are explained in the following sections.

The getchar() Function

The function getchar() obtains the next character from the stream stdin. It provides buffered character input with echo, and its prototype is

 int getchar(void);

The use of getchar() is demonstrated below. Notice that the putchar() function, explained in detail, simply displays a single character on-screen.

The getchar() function

This C program demonstrates the getchar() function.

  #include <stdio.h>

 main()
  {
 int ch;
 while ((ch = getchar()) != '\n')
  putchar(ch);

 return 0;
 }

On line 9, the getchar() function is called and waits to receive a character from stdin. Because getchar() is a buffered input function, no characters are received until we press Enter. However, each key we press is echoed (showed) immediately on the screen.

When we press Enter, all the characters we entered, including the newline, are sent to stdin by the operating system. The getchar() function returns the characters one at a time, assigning each in turn to ch.

Each character is compared to the newline character \n and, if not equal, displayed on-screen with putchar(). When a newline is returned by getchar(), the while loop terminates.

The getchar() function can be used to input entire lines of text, as shown below. However, other input functions are better suited for this task

Using the getchar() function to input an entire line of text

 #include <stdio.h>
 #define MAX  80

 main()
 {
 char ch, buffer[MAX+1];
 int x =  0;

 while ((ch = getchar()) != '\n' && x < MAX)
  buffer[x++] = ch;

 buffer[x] = '\0';

 printf("%s\n",  buffer);

 return 0;
 }

This program is similar to the previous function in the way that it uses getchar(). An extra condition has been added to the loop. This time the while loop accepts characters from getchar() until either a newline character is reached or 80 characters are read. Each character is assigned to an array called buffer. When the characters have been input, line 15 puts a null on the end of the array
so that the printf() function on line 17 can print the entered string.

On line 9, why was buffer declared with a size of MAX + 1 instead of just MAX? If we declare buffer with a size of MAX + 1, the string can be 80 characters plus a null terminator. So don’t forget to include a place for the null terminator at the end of the strings.

The getch() Function

The getch() function obtains the next character from the stream stdin. It provides unbuffered character input without echo. The getch() function isn’t part of the ANSI standard. This means
that it might not be available on every system. Additionally, it might require that different header files be included. Generally, the prototype for getch() is in the header file CONIO.H, as follows:

int getch(void);

Because it is unbuffered, getch() returns each character as soon as the key is pressed, without waiting for the user to press Enter. Because getch() doesn’t echo its input, the characters aren’t displayed on-screen. Listing 14.4 illustrates the use of getch().

The following function uses getch(), which is not ANSI-compliant. There is no guarantee that all compilers support non-ANSI functions.

Using the getch() function

This C program demonstrates the getch() function using Non-ANSI code.

 #include <stdio.h>
 #include <conio.h>

 main()
  {
 int ch;

 while ((ch = getch()) != '\r')
  putchar(ch);

 return 0;
}

When this program runs, getch() returns each character as soon as we press a key–it doesn’t wait for us to press Enter. There’s no echo, so the only reason that each character is displayed on-screen is the call to putchar(). To get a better understanding, add a semicolon to the end of line 10 and remove line 11 (putchar(ch)). When we rerun the program, you will find that nothing
we type is echoed to the screen. The getch() function gets the characters without echoing them to the screen. We know the characters are being gotten because the original listing used putchar() to display them.

Why does this program compare each character to \r instead of to \n? The code \r is the escape sequence for the carriage return character. When we press Enter, the keyboard device sends a carriage return to stdin. The buffered character input functions automatically translate the carriage return to a newline, so the program must test for \n to determine whether Enter has been pressed. The
unbuffered character input functions don’t translate, so a carriage return is input as \r, and that’s what the program must test for.

The next function uses getch( ) to input an entire line of text. Running this program clearly illustrates that getch( ) doesn’t echo its input.

Using the getch( ) function to input an entire line

This C program demonstrates the getch() function to input strings using Non-ANSI code.

 #include <stdio.h>
 #include <conio.h>

 #define MAX 80

 main()
 {
 char ch,  buffer[MAX+1];
 int x = 0;

 while ((ch = getch()) != '\r'  && x < MAX)
 buffer[x++] = ch;

 buffer[x] =  '\0';

 printf("%s", buffer);

 return  0;
}

Remember that getch() isn’t an ANSI-standard command. This means that your compiler (and other compilers) might or might not support it. getch() is supported by Symantec and Borland. Microsoft supports _getch().

The getche() Function

getche() is exactly like getch(), except that it echoes each character to stdout. Modify the first program in the getch() portion to use getche() instead of getch() and when the program runs, each key we press is displayed on-screen twice–once as echoed by getche(), and once as echoed by putchar(). getche() is not an ANSI-standard command, but many C compilers support it.

The getc() and fgetc() Functions

The getc() and fgetc() character input functions don’t automatically work with stdin. Instead, they let the program specify the input stream. They are used primarily to read characters from disk files. See Day 16 for more details.

Ungetting a Character with ungetc()

Suppose that the program is reading characters from an input stream and can detect the end of input only by reading one character too many. For example, we might be inputting digits only, so we know that input has ended when the first non digit character is encountered. That first non digit character might be an important part of subsequent data, but it has been removed from the input
stream. Is it lost? No, it can be “ungotten” or returned to the input stream, where it is then the first character read by the next input operation on that stream.

To “unget” a character, we use the ungetc() library function. Its prototype is

int ungetc(int ch, FILE *fp);

The argument ch is the character to be returned. The argument *fp specifies the stream that the character is to be returned to, which can be any input stream. For now, simply specify stdin as the second argument: ungetc(ch, stdin);. The notation FILE *fp is used with streams associated with disk files.

We can unget only a single character to a stream between reads, and can’t unget EOF at any time. The function ungetc() returns ch on success and EOF if the character can’t be returned to the stream.

Reading a Line

The line input functions read a line from an input stream. They read all characters up to the next newline character ‘\n’. The standard library has two line input functions, gets() and fgets().

The gets() Function

This is a straight forward function, reading a line from stdin and storing it in a string. The function prototype is

char *gets(char *str);

gets() takes a pointer to type char as its argument and returns a pointer to type char. The gets() function reads characters from stdin until a newline (\n) or end-of-file is encountered; the newline is replaced with a null character, and the string is stored at the location indicated by str.

The return value is a pointer to the string (the same as str). If gets() encounters an error or reads end-of-file before any characters are input, a null pointer is returned.

Before calling gets(), we must allocate sufficient memory space to store the string. This function has no way of knowing whether space pointed to by ptr is allocated; the string is input and stored starting at ptr in either case. If the space hasn’t been allocated, the string might overwrite other data and cause program errors.

Using gets() to input string data from the keyboard

This C program demonstrates using the gets() library function.

 #include <stdio.h>

 // Allocate a character array to hold input. 
 char input[81];

 main()
 {
 puts("Enter some text, then press Enter: ");
 gets(input);
 printf("You entered: %s\n", input);

 return 0;
 }

Enter some text, then press Enter:

This is a test

You entered: This is a test

In this example, the argument to gets() is the expression input, which is the name of a type char array and therefore a pointer to the first array element. The array is declared with 81 elements in line 7. Because the maximum line length possible on most computer screens is 80 characters, this array size provides space for the longest possible input line (plus the null character that gets()
adds at the end).

The gets() function has a return value. gets() returns a pointer to type char with the address where the input string is stored. This is the same value that is passed to gets(), but having the value returned to the program in this way lets your program test for a blank line.

Using the gets() return value to test for the input of a blank line

This C program demonstrates using the gets() return value to see if an input line is blank?

 #include <stdio.h>

 // Declare a character array to hold input, and a pointer.
 char input[81], *ptr;

 main()
 {
 //Display instructions. 
 puts("Enter text a line at a time, then press Enter.");
 puts("Enter a blank line when done.");

 //Loop as long as input is not a blank line. 
 while ( *(ptr = gets(input)) != NULL)
 printf("You entered %s\n", input);

 puts("Thank you and good-bye\n");

 return 0;
 }

Enter text a line at a time, then press Enter.
Enter a blank line when done.
First string
You entered First string
Two
You entered Two
Asfia Firdaus
You entered Asfia Firdaus
Thank you and good-bye

If we enter a blank line (that is, if we simply press Enter) in response to line 18, the string (which contains 0 characters) is still stored with a null character at the end. Because the string has a length of 0, the null character is stored in the first position. This is the position pointed to by the return value of gets(), so if we test that position and find a null character, we know
that a blank line was entered.

The fgets() Function

The fgets() library function is similar to gets() in that it reads a line of text from an input stream. It’s more flexible, because it lets the programmer specify the specific input stream to use and the maximum number of characters to be input. The fgets() function is often used to input text from disk files. To use it for input from stdin, we specify stdin as the input stream. The prototype of fgets() is

char *fgets(char *str, int n, FILE *fp);

The last parameter, FILE *fp, is used to specify the input stream. Simply specify the standard input stream, stdin, as the stream argument.

The pointer str indicates where the input string is stored. The argument n specifies the maximum number of characters to be input. The fgets() function reads characters from the input stream until a newline or end-of-line is encountered or n – 1 characters have been read. The newline is included in the string and terminated with a \0 before it is stored. The return values of fgets() are the
same as described earlier for gets().

Strictly speaking, fgets() doesn’t input a single line of text (if you define a line as a sequence of characters ending with a newline). It can read less than a full line if the line contains more than n -1 characters. When used with stdin, execution doesn’t return from fgets() until you press Enter, but only the first n-1 characters are stored in the string. The newline is included in the string only if it falls within the first n-1 characters.

Using the fgets() function for keyboard input

This program Demonstrates the fgets() function

 #include <stdio.h>
 #define MAXLEN 10

 main()
 {
 char buffer[MAXLEN];

 puts("Enter text a line at a time; enter a blank to exit.");

 while (1)
 {
 fgets(buffer, MAXLEN, stdin);

 if (buffer[0] == `\n')
 break;

 puts(buffer);
 }
 return 0;
 }

Enter text a line at a time; enter a blank to exit.

Roses are red

Roses are

red

Violets are blue

Violets a

re blue

Programming in C

Programmi

ng in C

Is for people like you!

Is for pe

ople like

you!

Line 15 contains the fgets() function. When running the program, enter lines of length less than and greater than MAXLEN to see what happens. If a line greater than MAXLEN is entered, the first MAXLEN – 1 characters are read by the first call to fgets(); the remaining characters remain in the keyboard buffer and are read by the next call to fgets() or any other function that reads from stdin. The program exits when a blank line is entered (lines 17 and 18).

Formatted Input

The input functions covered up to this point have simply taken one or more characters from an input stream and put them somewhere in memory. No interpretation or formatting of the input has been done, and you still have no way to input numeric variables. For example, how would you input the value 12.86 from the keyboard and assign it to a type float variable? Enter the scanf() and fscanf() functions.

These two functions are identical, except that scanf() always uses stdin, whereas the user can specify the input stream in fscanf(). This section covers scanf(); fscanf() generally is used with disk file input.

The scanf() Function’s Arguments

The scanf() function takes a variable number of arguments; it requires a minimum of two. The first argument is a format string that uses special characters to tell scanf() how to interpret the input. The second and additional arguments are the addresses of the variable(s) to which the input data is assigned. Here’s an example:

scanf("%d", &x);

The first argument, “%d”, is the format string. In this case, %d tells scanf() to look for one signed integer value. The second argument uses the address-of operator (&) to tell scanf() to assign the input value to the variable x.
The scanf() format string can contain the following:

  1. Spaces and tabs, which are ignored (they can be used to make the format string more readable).
  2. Characters (but not %), which are matched against non-white-space characters in the input.
  3. One or more conversion specifications, which consist of the % character followed by special characters. Generally, the format string contains one conversion specification for each variable.

The only required part of the format string is the conversion specifications. Each conversion specification begins with the % character and contains optional and required components in a
certain order. The scanf() function applies the conversion specifications in the format string, in order, to the input fields. An input field is a sequence of non-white-space characters that ends when the next white space is encountered or when the field width, if specified, is reached. The conversion specification components include the following:

  1. The optional assignment suppression flag (*) immediately follows the %. If present, this character tells scanf() to perform the conversion corresponding to the current conversion specifier but to ignore the result (not assign it to any variable).
  2. The next component, the field width, is also optional. The field width is a decimal number specifying the width, in characters, of the input field. In other words, the field width specifies how many characters from stdin scanf() should examine for the current conversion. If a field width isn’t specified, the input field extends to the next white space.
  3. The next component is the optional precision modifier, a single character that can be h, l, or L. If present, the precision modifier changes the meaning of the type specifier that follows it.
  4. The only required component of the conversion specifier (besides the %) is the type specifier. The type specifier is one or more characters that tell scanf() how to interpret the input. These characters are listed and described in the table given below. The Argument column lists the required type of the corresponding variable.

For example, the type specifier d requires int * (a pointer to type int).

TypeArgumentMeaning of Type
dint *A decimal integer.
iint *An integer in decimal, octal (with leading 0), or hexadecimal (with leading 0X or 0x) notation.
oint *An integer in octal notation with or without the leading 0.
uunsigned int *An unsigned decimal integer.
xint *A hexadecimal integer with or without the leading 0X or 0x.
cchar *One or more characters are read and assigned sequentially to the memory location indicated by the argument. No terminating \0 is added. If a field width argument isn’t given, one character
is read. If a field width argument is given, that number of characters, including white space (if any), is read.
schar *A string of nonwhitespace characters is read into the specified memory location, and a terminating \0 is added.
e,f,gfloat *A floating-point number. Numbers can be input in decimal or scientific notation.
[…]char *A string. Only the characters listed between the brackets are accepted. Input ends as soon as a nonmatching character is encountered, the specified field width is reached, or
Enter is pressed. To accept the ] character, list it first:[]…]. A \0 is added at the end of the string.
[^…]char *The same as […], except that only characters not listed between the brackets are accepted.
%NoneLiteral %: Reads the % character. No assignment is made.
The type specifier characters used in scanf() conversion specifiers.

Before seeing some examples of scanf(), we need to understand the precision modifiers.

Precision ModifierMeaning
hWhen placed before the type specifier d, i, o, u, or x, the modifier h specifies that the argument is a pointer to type short instead of type int. On a PC, the type short is the same as type int, so the h precision modifier is never needed.
lWhen placed before the type specifier d, i, o, u, or x, the modifier l specifies that the argument is a pointer to type long. When placed before the type specifier e, f, or g, the modifier l specifies that the argument is a pointer to type double.
LWhen placed before the type specifier e, f, or g, the modifier L specifies that the argument is a pointer to type long double.

Handling Extra Characters

Input from scanf() is buffered; no characters are actually received from stdin until the user presses Enter. The entire line of characters then “arrives” from stdin, and is processed, in order, by scanf(). Execution returns from scanf() only when enough input has been received to match the specifications in the format string. Also, scanf() processes only enough characters from stdin to
satisfy its format string. Extra, unneeded characters, if any, remain waiting in stdin. These characters can cause problems.

When a call to scanf() is executed and the user has entered a single line, we can have three situations. For these examples, assume that scanf(“%d %d”, &x, &y); is being executed; in other words, scanf() is expecting two decimal integers. Here are the possibilities:

  1. The line the user inputs matches the format string. For example, suppose the user enters 12 14 followed by Enter. In this case, there are no problems.
  2. scanf() is satisfied, and no characters are left over in stdin. The line that the user inputs has too few elements to match the format string. For example, suppose the user enters 12 followed by Enter. In this case, scanf() continues to wait for the missing input. Once the input is received, execution continues, and no characters are left over in stdin.
  3. The line that the user enters has more elements than required by the format string. For example, suppose the user enters 12 14 16 followed by Enter. In this case, scanf() reads the 12 and the 14 and then returns. The extra characters, the 1 and the 6, are left waiting in stdin.

It is this third situation (specifically, those leftover characters) that can cause problems. They remain waiting for as long as the program is running, until the next time the program reads input from stdin. Then the leftover characters are the first ones read, ahead of any input the user makes at the time. It’s clear how this could cause errors. For example, the following code asks the user to input an integer and then a string:

puts("Enter your  age.");
scanf("%d", &age);
puts("Enter your first  name.");
scanf("%s", name);

Say, for example, that in response to the first prompt, the user decides to be precise and enters 21.00 and then presses Enter. The first call to scanf() is looking for an integer, so it reads the characters 21 from stdin and assigns the value 21 to the variable age. The characters .00 are left waiting in stdin. The next call to scanf() is looking for a string. It goes to stdin for input and finds .00 waiting there. The result is that the string .00 is assigned to name.
A solution is to make sure there are no extra characters waiting in stdin before prompting the user for input. We can do this by calling gets(), which reads any remaining characters from stdin,
up to and including the end of the line. Rather than calling gets() directly from the program, we can put it in a separate function with the descriptive name of clear_kb().

Clearing stdin of extra characters to avoid errors.

 #include <stdio.h>
 void clear_kb(void);

  main()
 {
 int age;
 char name[20];

 // Prompt for  user's age. 

 puts("Enter your age.");
 scanf("%d",  &age);

 // Clear stdin of any extra characters.  

 clear_kb();

 // Now prompt for user's name.  

 puts("Enter your first name.");
 scanf("%s",  name);
 // Display the data. 

 printf("Your age is %d.\n",  age);
 printf("Your name is %s.\n", name);

 return 0;
  }

 void clear_kb(void)

 // Clears stdin of any waiting  characters. 
 {
 char junk[80];
 gets(junk);
  }

Enter your age.

21 and never older LOL!

Enter your first  name.

Asfia

Your age is 21.

Your name is Asfia.

When running this, enter some extra characters after the age, before pressing Enter. Make sure the program ignores them and correctly prompts for the name. Then modify the program by removing the call to clear_kb(), and run it again. Any extra characters entered on the same line as your age are assigned to name

Handling extra characters with fflush()

If we are using the buffered streams with files or disk operations, means that we are using the buffers to store the information and then process it. So here in this case if we use the fflush() function then it will flushes all the data and clears the buffers. This function has no effect on the streams which are not using the buffers.

There is a second way through which we can clear the extra characters that were typed in. The fflush() function flushes the information in a stream–including the standard input stream. fflush() is generally used with disk files.

The next program uses the fflush() function instead of the clear_kb() function.

Clearing stdin of extra characters using fflush().

This C programs demonstrates clearing stdin of extra characters by using the fflush() function

#include <stdio.h>

 main()
 {
 int age;
 char name[20];

 // Prompt for user's age. 
 puts("Enter your age.");
 scanf("%d", &age);

 // Clear stdin of any extra characters. 
 fflush(stdin);

 // Now prompt for user's name. 
 puts("Enter your first name.");
 scanf("%s", name);

 // Display the data. 
 printf("Your age is %d.\n", age);
 printf("Your name is %s.\n", name);

 return 0;
 }

Enter your age.

21 and never older LOL!

Enter your first name.

Asfia

Your age is 21.

Your name is Asfia.

As can be seen in line 15, the fflush() function is being used. The prototype for the fflush() function is as follows:

 int fflush( FILE *stream);

The stream is the stream to be flushed. In the above function, the standard input stream, stdin, is being passed for stream.

The C Program with scanf() examples

It’s a powerful function, but it can be a bit confusing at times. Try it and see what happens. Compile and run this program and then experiment by making changes to the scanf() format strings.

#include <stdio.h>
int main(void)
{
 int i1, i2;
 long l1;

 double d1;
 char buf1[80], buf2[80];

 // Using the l modifier to enter long integers and doubles.
 puts("Enter an integer and a floating point number.");
 scanf("%ld %lf", &l1, &d1);
 printf("\nYou entered %ld and %lf.\n",l1, d1);
 puts("The scanf() format string used the l modifier to store");
 puts("your input in a type long and a type double.\n");

 fflush(stdin);

 // Use field width to split input. 
 puts("Enter a 5 digit integer (for example, 54321).");
 scanf("%2d%3d", &i1, &i2);

 printf("\nYou entered %d and %d.\n", i1, i2);
 puts("Note how the field width specifier in the scanf() format");
 puts("string split your input into two values.\n");

 fflush(stdin);

 // Using an excluded space to split a line of input into 
 // two strings at the space. 
 puts("Enter your first and last names separated by a space.");
 scanf("%[^ ]%s", buf1, buf2);
 printf("\nYour first name is %s\n", buf1);
 printf("Your last name is %s\n", buf2);
 puts("Note how [^ ] in the scanf() format string, by excluding");
 puts("the space character, caused the input to be split.");

 return 0;
}

Output of the Program
Enter an integer and a floating point number.
123 45.6789
You entered 123 and 45.678900.
The scanf() format string used the l modifier to store
your input in a type long and a type double.
Enter a 5 digit integer (for example, 54321).
54321
You entered 54 and 321.
Note how the field width specifier in the scanf() format
string split your input into two values.
Enter your first and last names separated by a space.
Asfia Firdaus
Your first name is Asfia
Your last name is Firdaus
Note how [^ ] in the scanf() format string, by excluding
the space character, caused the input to be split.

This program starts by defining several variables in lines 9 through 13 for data input. The program then goes through various types of data. Lines 17 through 21 print long integers and a double. Line 23 calls the fflush() function to clear any unwanted characters from the standard input stream. Lines 27 and 28 get the next value, a five-character integer. Because there are width specifiers, the five-digit integer is split into two integers–one that is two characters, and one that is three characters. Line 34 calls fflush() to clear the keyboard again. The final example, in lines 36 through 44, uses the exclude character. Line 40 uses “%[^ ]%s”, which tells scanf() to get a string but to stop at any spaces. This effectively splits the input.

Play with this program, change it around a bit and see what happens ?

The scanf() function can be used for most of the input needs, particularly those involving numbers (strings can be input more easily with gets()).

Screen Output

Screen output functions are divided into three general categories along the
same lines as the input functions.

  1. Character output
  2. Line output
  3. Formatted output

Character Output with putchar(), putc(), and fputc()

The C library’s character output functions send a single character to a stream. The function putchar() sends its output to stdout (normally the screen). The functions fputc() and putc() send their output to a stream specified in the argument list.

Using the putchar() Function

The prototype for putchar(), which is located in STDIO.H, is as follows:

int putchar(int c);

This function writes the character stored in C to stdout. Although the prototype specifies a type int argument, we pass putchar() a type char. We can also pass it a type int as long as its value is appropriate for a character (that is, in the range 0 to 255). The function returns the character that was just written, or EOF if an error has occurred.

The putchar() function

 #include  <stdio.h>
 main()
 {
 int count;

 for (count = 14;  count < 128; )
 putchar(count++);

 return 0;
  }

We can also display strings with the putchar() function. Here is a C program displaying a string with  putchar().

#include  <stdio.h>
#define MAXSTRING 80

char message[] =  "Displayed with putchar().";
int main(void)
{
    int  count;

    for (count = 0; count < MAXSTRING; count++)
    {

        // Look for the end of the string. When it's found, 
        // write a newline character and exit the loop. 
        if (message[count]  == `\0')
        {
            putchar(`\n');
            break;
        }
        else
        {
            // If end of string not found, write the next character.  
            putchar(message[count]);
        }
    return 0;
}

Using the putc() and fputc() Functions

These two functions perform the same action–sending a single character to a specified stream. putc() is a macro implementation of fputc().Its prototype is

int fputc(int c, FILE *fp);

The FILE *fp part might puzzle you. If wespecify stdout as the stream, fputc() behaves exactly the same as putchar(). Thus, the following two statements are equivalent:

putchar(`x');
fputc(`x',  stdout);

Using puts() and fputs() for String Output

The programs display strings on-screen more often than they display single characters. The library function puts() displays strings. The function fputs() sends a string to a specified
stream; otherwise, it is identical to puts(). The prototype for puts() is

int puts(char *cp);

*cp is a pointer to the first character of the string that we want displayed. The puts() function displays the entire string up to but not including the terminating null character, adding a newline at the end. Then puts() returns a positive value if successful or EOF on error. (Remember, EOF is a symbolic constant with the value -1; it is defined in STDIO.H.)

The puts() function can be used to display any type of string. Here is a C program using the puts() function to display strings

#include <stdio.h>
//Declare and initialize an array of pointers. 
char *messages[5] = { "This", "is", "a", "short", "message."  };
int main(void)
{
  int x;

  for (x=0; x<5;  x++)
    puts(messages[x]);
  puts("And this is the  end!");

  return 0;
}
This is a short message. And this is the end!

This program declares an array of pointers. Lines 13 and 14 print each of the strings stored in the message array.

Using printf() and fprintf() for Formatted Output

To display numbers, we must use the C library’s formatted output functions, printf() and fprintf(). These functions can also display strings and characters.

The two functions printf() and fprintf() are identical, except that printf() always sends output to stdout, whereas fprintf() specifies the output stream. fprintf() is generally used for output to disk files.

The printf() function takes a variable number of arguments, with a minimum of one. The first and only required argument is the format string, which tells printf() how to format the output. The optional arguments are variables and expressions whose values we want to display. Take a look at these simple examples:

  1. The statement printf(“Hello, world.”); displays the message Hello, world. on-screen. This is an example of using printf() with only one argument, the format string. In this case, the format string contains only a literal string to be displayed on-screen.
  2. The statement printf(“%d”, i); displays the value of the integer variable i on-screen. The format string contains only the format specifier %d, which
    tells printf() to display a single decimal integer. The second argument is the name of the variable whose value is to be displayed.
  3. The statement printf(“%d plus %d equals %d.”, a, b, a+b); displays 2 plus 3 equals 5 on-screen (assuming that a and b are integer variables with the values of 2 and 3, respectively). This use of printf() has four arguments: a format string that contains literal text as well as format specifiers, and two variables and an expression whose values are to be displayed.

The printf() format string can contain the following:

  1. Zero, one, or more conversion commands that tell printf() how to display a value in its argument list. A conversion command consists of % followed by one or more characters.
  2. Characters that are not part of a conversion command and are displayed as-is.

The third example’s format string is %d plus %d equals %d. In this case, the three %ds are conversion commands, and the remainder of the string, including the spaces, is literal characters that are displayed directly.

Now we can discuss the conversion command. The components of the command are given here and explained next. Components in brackets are optional.

%[flag][field_width][.[precision]][l]conversion_char

The conversion_char is the only required part of a conversion command (other than the %). Table lists the conversion characters and their meanings.

The printf() and fprintf() conversion characters.

Conversion CharacterMeaning
d,iDisplay a signed integer in decimal notation.
uDisplay an unsigned integer in decimal notation.
oDisplay an integer in unsigned octal notation.
x,XDisplay an integer in unsigned hexadecimal notation. Use x for lowercase output and X for uppercase output.
cDisplay a single character (the argument gives the character’s ASCII code).
e,EDisplay a float or double in scientific notation (for example, 123.45 is displayed as 1.234500e+002). Six digits are displayed to the right of the decimal point unless another precision
is specified with the f specifier. Use e or E to control the case of output.
fDisplay a float or double in decimal notation (for example, 123.45 is displayed as 123.450000). Six digits are displayed to the right of the decimal point unless another precision is specified.
g, GUse e, E, or f format. The e or E format is used if the exponent is less than -3 or greater than the precision (which defaults to 6). f format is used otherwise. Trailing zeros are truncated.
nNothing is displayed. The argument corresponding to an n conversion command is a pointer to type int. The printf() function assigns to this variable the number of characters output so far.
sDisplay a string. The argument is a pointer to char. Characters are displayed until a null character is encountered or the number of characters specified by precision (which defaults to 32767) is displayed. The terminating null character is not output.
%Display the % character.

We can place the l modifier just before the conversion character. This modifier applies only to the conversion characters o, u, x, X, i, d, and b. When applied, this modifier specifies that the argument is a type long rather than a type int. If the l modifier is applied to the conversion characters e, E, f, g, or G, it specifies that the argument is a type double. If an l is placed before any other conversion character, it is ignored.

The precision specifier consists of a decimal point (.) by itself or followed by a number. A precision specifier applies only to the conversion characters e, E, f, g, G, and s. It specifies the number of digits to display to the right of the decimal point or, when used with s, the number of characters to output. If the decimal point is used alone, it specifies a precision of 0.

The field-width specifier determines the minimum number of characters output. The field-width specifier can be the following:

  1. A decimal integer not starting with 0. The output is padded on the left with spaces to fill the designated field width.
  2. A decimal integer starting with 0. The output is padded on the left with zeros to fill the designated field width.
  3. The * character. The value of the next argument (which must be an int) is used as the field width. For example, if w is a type int with a value of 10, the statement printf(“%*d”, w, a); prints the value of a with a field width of 10.

If no field width is specified, or if the specified field width is narrower than the output, the output field is just as wide as needed.

The last optional part of the printf() format string is the flag, which immediately follows the % character. There are four available flags:

?-? This means that the output is left-justified in its field rather than right-justified, which is the default.

?+? This means that signed numbers are always displayed with a leading + or -.

` ` A space means that positive numbers are preceded by a space.

?#? This applies only to x, X, and o conversion characters. It specifies that nonzero numbers are displayed with a leading 0X or 0x (for x and X) or a leading 0 (for o).

When we use printf(), the format string can be a string literal enclosed in double quotes in the printf() argument list. It can also be a null-terminated string stored in memory, in
which case we pass a pointer to the string to printf(). For example, this statement:

char *fmt = "The answer is  %f.";
printf(fmt, x);

is equivalent to this statement:

printf("The answer is %f.",  x);

The printf() format string can contain escape sequences that provide special control over the output. Table below lists the most frequently used escape sequences. For example, including the newline sequence (\n) in a format string causes subsequent output to appear starting on the next screen line.

The most frequently used  escape sequences.
Sequence Meaning
\a Bell (alert)
\b Backspace
\n  Newline
\t Horizontal tab
\\ Backslash
\? Question mark
\' Single  quote
\" Double quote

printf() is somewhat complicated. The best way to learn how to use it is to look at examples and then experiment on your own but don?t be alarmed, it?s easy ?

Different ways to use the printf() function

 #include <stdio.h>

 char *m1 = "Binary";
 char *m2 = "Decimal";
 char *m3 = "Octal";
 char *m4 = "Hexadecimal";

 main()
{
 float d1 = 10000.123;
 int n, f;

  puts("Outputting a number with different field widths.\n");

 printf("%5f\n", d1);
 printf("%10f\n", d1);
 printf("%15f\n",  d1);
 printf("%20f\n", d1);
 printf("%25f\n", d1);

  puts("\n Press Enter to continue...");
 fflush(stdin);
  getchar();

 puts("\nUse the * field width specifier to obtain field  width");
 puts("from a variable in the argument list.\n");

  for (n=5;n<=25; n+=5)
    printf("%*f\n", n, d1);

 puts("\n  Press Enter to continue...");
 fflush(stdin);
 getchar();

 puts("\nInclude leading zeros.\n");

 printf("%05f\n", d1);
 printf("%010f\n", d1);
 printf("%015f\n",  d1);
 printf("%020f\n", d1);
 printf("%025f\n", d1);

 puts("\n Press Enter to continue...");
 fflush(stdin);
 getchar();

 puts("\nDisplay in octal, decimal, and  hexadecimal.");
 puts("Use # to precede octal and hex output with 0 and  0X.");
 puts("Use - to left-justify each value in its field.");
 puts("First display column labels.\n");

 printf("%-15s%-15s%-15s",  m2, m3, m4);

 for (n = 1;n< 20; n++)
    printf("\n%-15d%-#15o%-#15X", n, n, n);

 puts("\n Press Enter to  continue...");
 fflush(stdin);
 getchar();

 puts("\n\nUse the %n conversion command to count characters.\n");

 printf("%s%s%s%s%n", m1, m2, m3, m4, &n);
 printf("\n\nThe last  printf() output %d characters.\n", n);

 return 0;
}
 Outputting a number with different field widths.
   10000.123047
   10000.123047
       10000.123047
            10000.123047
   10000.123047
   Press Enter to continue...
   Use the * field width specifier to obtain field width
   from a variable in the argument list.
   10000.123047
   10000.123047
       10000.123047
            10000.123047
                 10000.123047
   Press Enter to continue...
   Include leading zeros.
   10000.123047
   10000.123047
   00010000.123047
   0000000010000.123047
   000000000000010000.123047
   Press Enter to continue...
   Display in octal, decimal, and hexadecimal.
   Use # to precede octal and hex output with 0 and 0X.
   Use - to left-justify each value in its field.
   First display column labels.
 Decimal Octal Hexadecimal
   1      01      0X1
   2      02      0X2
   3      03      0X3
   4      04      0X4
   5      05      0X5
   6      06      0X6
   7      07      0X7
   8      010     0X8
   9      011     0X9
   10     012     0XA
   11     013     0XB
   12     014     0XC
   13     015     0XD
   14     016     0XE
   15     017     0XF
   16     020     0X10
   17     021     0X11
   18     022     0X12
   19     023     0X13
Press Enter to  continue...
Use the %n conversion command to count  characters.
BinaryDecimalOctalHexadecimal
The last printf() output 29  characters.

Redirecting Input & Output

A program that uses stdin and stdout can utilize an operating-system feature called redirection. Redirection allows you to do the following:

  1. Output sent to stdout can be sent to a disk file or the printer rather than to the screen.
  2. Program input from stdin can come from a disk file rather than from the keyboard.

We don’t code redirection into our programs; we specify it on the command line$ when we run the program. In DOS, as in UNIX, the symbols for redirection are < and >.

Remember the first C program, HELLO.C? It used the printf() library function to display the message Hello, world on-screen. As we now know, printf() sends output to stdout, so it can be redirected. When we enter the program name at the command-line prompt, follow it with the > symbol and the name of the new destination:

hello > destination

Thus, if we enter hello >prn, the program output goes to the printer instead of to the screen (prn is the DOS name for the printer attached to port LPT1:). If we enter hello >hello.txt, the output is placed in a disk file with the name HELLO.TXT.
When we redirect output to a disk file, be careful. If the file already exists, the old copy is deleted and replaced with the new file. If the file doesn’t exist, it is created. When redirecting output to a file, we can also use the >> symbol. If the specified destination file already exists, the program output is appended to the end of the file.

The redirection of input and output.
// Can be used to demonstrate redirection of stdin and stdout.

 #include <stdio.h>
 main()
 {
     char buf[80];
     gets(buf);
     printf("The input was: %s\n", buf);
     return 0;
 }

This program accepts a line of input from stdin and then sends the line to stdout, preceding it with The input was:. After compiling and linking the program, run it without redirection (assuming that the program is named TRIAL) by entering TRIAL at the command-line prompt. If we then enter I am teaching myself C, the program displays the following on-screen:

The input was: I am teaching myself C

If we run the program by entering TRIAL >test.txt and make the same entry, nothing is displayed on-screen. Instead, a file named TEST.TXT is created on the disk. If we use the DOS TYPE (or an equivalent) command to display the contents of the file:

type test.txt

We’ll see that the file contains only the line The input was: I am teaching myself C. Similarly, if we had run the program by entering TRIAL >prn, the output line would have been printed on the printer (prn is a DOS command name for the printer).
Just for the sake of it run the program again, this time redirecting output to TEST.TXT with the >> symbol. Instead of the file’s getting replaced, the new output is appended to the end of TEST.TXT. Give it a try ?

Redirecting Input

First we need a source file. Use the editor to create a file named INPUT.TXT that contains the single line “Redirecting input in C language”. Now run the previous program by entering the following at the DOS prompt:

trial < INPUT.TXT

The program doesn’t wait for you to make an entry at the keyboard. Instead, it immediately displays the following message on-screen:

The input was: Redirecting input in C language

The stream stdin was redirected to the disk file INPUT.TXT, so the program’s call to gets() reads one line of text from the file rather than the keyboard.

We can redirect input and output at the same time. Try running the program with the following command to redirect stdin to the file INPUT.TXT and redirect stdout to JUNK.TXT:

trial < INPUT.TXT > JUNK.TXT

Redirecting stdin and stdout can be useful in certain situations. A sorting program, for example, could sort either keyboard input or the contents of a disk file. Likewise, a mailing list program could display addresses on-screen, send them to the printer for mailing labels, or place them in a file for some other use.

Using stderr Stream

One of C’s predefined streams is stderr (standard error). A program’s error messages traditionally are sent to the stream stderr and not to stdout. Output to stdout can be redirected to a destination other than the display screen. If stdout is redirected, the user might not be aware of any error messages the program sends to stdout. Unlike stdout, stderr can’t be redirected and is always connected to the screen (at least in DOS–UNIX systems might allow redirection of stderr). By directing error messages to stderr, we can be sure the user always sees them. We do this with fprintf():

fprintf(stderr, "An error has occurred.");

We can write a function to handle error messages and then call the function when an error occurs rather than calling fprintf():

error_message("An error has occurred.");
void error_message(char *msg)
{
fprintf(stderr, msg);
}

By using our own function instead of directly calling fprintf(), we provide additional flexibility (one of the advantages of structured programming). For example, in special circumstances we might want a program’s error messages to go to the printer or a disk file. All we need to do is modify the error_message() function so that the output is sent to the desired destination.

Printer output under DOS

On a DOS or Windows system, we send output to the printer by accessing the predefined stream stdprn. To use stdprn, you need to turn ANSI compatibility off in your compiler. The program presents a simple example.

#include <stdio.h>
main()
{
 float f = 2.0134;

 fprintf(stdprn, "\nThis message is printed.\r\n");
 fprintf(stdprn, "And now some numbers:\r\n");
 fprintf(stdprn, "The square of %f is %f.", f, f*f);

 /* Send a form feed. */ fprintf(stdprn, "\f");

 return 0;
}

This message is printed.

And now some numbers:

The square of 2.013400 is 4.053780.

This output is printed by the printer. It won’t appear on-screen If DOS system has a printer connected to port LPT1:, we can compile and run this program. It prints three lines on the page. Line 14 sends an “\f” to the printer. \f is the escape sequence for a form feed, the command that causes the printer to advance a page (or, in the case of a laser printer, to eject the current page).

Do’s and Don’ts for input/output streams

  1. Do use fprintf() to create programs that can send output to stdout, stderr, stdprn, or any other stream.
  2. Do use fprintf() with stderr to print error messages to the screen.
  3. Do take advantage of the standard input/output streams that C provides.
  4. Do understand the difference between echoed and nonechoed input.
  5. Do understand the difference between buffered and unbuffered input
  6. Do create functions such as error_message to make your code more structured and maintainable.
  7. Do take advantage of extended characters in your programs. When using extended characters, you should try to be consistent with other programs.
  8. Do use the gets() and scanf() functions instead of the fgets() and fscanf() functions if you’re using the standard input file (stdin) only.
  9. Don’t use stderr for purposes other than printing error messages or warnings.
  10. Don’t ever try to redirect stderr.
  11. Don’t use non-ANSI standard functions if portability is a concern
  12. Don’t rename or change the standard streams unnecessarily.
  13. Don’t try to use an input stream such as stdin for an output function such as fprintf().
  14. Don’t forget to check the input stream for extra characters.

Input & Output in C – Final Words

This tutorial taught you about how C uses streams, treating all input and output as a sequence of bytes. You also learned that C has five predefined streams:

   stdin        The keyboard
   stdout       The screen
   stderr       The screen
   stdprn       The printer
   stdaux       The communications port

Input from the keyboard arrives from the stream stdin. Using C’s standard library functions, you can accept keyboard input character by character, a line at a time, or as formatted numbers and strings. Character input can be buffered or unbuffered, echoed or unechoed.

Output to the display screen is normally done with the stdout stream. Like input, program output can be by character, by line, or as formatted numbers and strings. For output to the printer, you use fprintf() to send data to the stream stdprn.

When you use stdin and stdout, you can redirect program input and output. Input can come from a disk file rather than the keyboard, and output can go to a disk file or to the printer rather than to the display screen.

Finally, you learned why error messages should be sent to the stream stderr instead of stdout. Because stderr is usually connected to the display screen, you are assured of seeing error messages even when the program output is redirected.

M. Saqib: Saqib is Master-level Senior Software Engineer with over 14 years of experience in designing and developing large-scale software and web applications. He has more than eight years experience of leading software development teams. Saqib provides consultancy to develop software systems and web services for Fortune 500 companies. He has hands-on experience in C/C++ Java, JavaScript, PHP and .NET Technologies. Saqib owns and write contents on mycplus.com since 2004.
Related Post