stdio - Standard Input/Output Library

Although stdio.h has supposedly been replaced by iostream.h for C++ programs, it is still much easier to use and control, and remains available. For the vast majority of programming tasks stdio.h is the superior tool.








Using stdio

Simply add the directive "#include <stdio.h>" at the beginning of your program file.

Although stdio is compatible with other input/output libraries (you do not have to remove other #includes), they should not be used together. stdio, iostream, and vital may use different buffering schemes, and using more than one of them concurrently could result in inputs and outputs being processed out of order, or possibly not at all.
(back to top)



Most useful stdio function prototypes


int putchar(int c);
int getchar(void);
int puts(char s[]);
char *gets(char s[]);
int printf(char format[], ...);
int scanf(char format[], ...);
int sprintf(char string[], char format[], ...);
int sscanf(char string[], char format[], ...);
int fprintf(FILE *fileref, char format[], ...);
int fscanf(FILE *fileref, char format[], ...);
FILE *fopen(char filename[], char access[]);
int fclose(FILE *fileref);
int fputc(int c, FILE *fileref);
int fgetc(FILE *fileref);
int ungetc(int c, FILE *fileref);
char *fgets(char str[], int length, FILE *fileref);
int fputs(char str[], FILE *fileref);

(back to top)



int putchar(int c)

The putchar function writes the single character whose ascii code is equal to its integer parameter c. It usually returns that same integer value as its result, which is not very useful, so the function's result is usually ignored. However, if the output operation fails, it returns EOF (defined to be -1) instead.
        All spoecial control characters have their normal effects: putchar('\n') starts a new line of output, putchar('\a') rings the keyboard bell (if there is one), etc. You can not use putchar(EOF) to "write an end-of-file mark".

Example: This function prints all the characters with ascii codes between 32 and 126.
void main(void)
{ int i;
  for (i=32; i<=126; i+=1)
    putchar(i);
  putchar('\n'); }

(back to top)



int getchar(void)

The getchar function returns the ascii code of the next available character. If no characters are currently available, it waits until one is typed. (In fact, it waits until a whole line (with ENTER at the end) is typed, otherwise the backspace key would be useless).
        If the input stream is at end-of-file (unix: control-D, dos/windows: control-Z), getchar returns EOF, which is defined to be -1. This is why getchar is defined as returning an int rather than a char: -1 is not a proper character code.
        Control characters are interpreted correctly: when newline/ENTER is typed, the return value is '\n', which is 10. Backspace, Delete, and Control-C, etc, can not be read by getchar, as they are processed by the operating system before the line of input is made available to user programs.

Example: This function echoes whatever the user types, replacing spaces by underlines.
void main(void)
{ while (1)
  { int c=getchar();
    if (c==EOF)
      break;
    if (c==' ')
      c='_';
    putchar(c); }
  putchar('\n'); }

(back to top)



int puts(char s[]);

The puts function prints the entire string passed to it, followed by a newline character. The string should not have a '\n' at the end unless you want a blank line to be left.
        puts returns EOF (defined to be -1) if the output operation fails. On success, it returns an indeterminate (but guaranteed not to be negative) value.

Example: This function prints four lines of text: "First Line", "Second Line", "Third Line", and "Fourth and Final Line".
void main(void)
{ puts("First Line");
  putchar('S'); puts("econd line"); putchar('T');
  puts("hird Line");
  puts("Fourth and Final Line"); }

(back to top)



char *gets(char s[]);

NOTE gets is an insecure function, its careless use can lead to errors. If you want to use gets, consider using fgets instead, supplying stdin as the file reference parameter.

The gets function waits until a line of input is available (unless one is already available), and consumes the whole line including the ENTER/newline at the end. The characters on the line are stored in the string parameter, except for the ENTER/newline, which is discarded.
        The parameter given to gets must be a string (i.e. an array of characters), not an uninitialised char * pointer.
          { char a[100]; gets(line);            // This is correct
          { char a[100]; char *s; s=a; gets(s); // This is correct
          { char *s; s=new char[100]; gets(s);  // This is correct
          { char *s; gets(s);                   // This is WRONG
        The string parameter given to gets must be big enough to hold any line that could conceivably be input. C++ (and C) is incapable of telling how long an array is. If it is not long enough for the data that is read, other data (and perhaps program code) will be overwritten. gets is not a safe function for use in critical applications.
        The return value is always a pointer to the parameter string, unless the input operation fails (most usual reason is being at end-of-file), in which case it returns NULL.
        Note that gets consumes the newline character typed at the end of the line, but does not put it in the string: it is permanently discarded. The puts function always prints an extra newline character after its string is printed. This makes puts and gets mutually compatible, but frequently annoying.
        gets reads a whole line, but if part of that line has already been consumed by another input function, it will not be re-read by gets.

Example: This function echoes whatever the user types.
void main(void)
{ char LineBuffer[1000];
  while (1)
  { char *s=gets(LineBuffer);
    if (s==NULL) break;
    puts(LineBuffer); } }

(back to top)



int printf(char format[], ...)

The printf function allows numeric and character data to be printed in (almost) any desired format. printf must be given at least one parameter when it is called, but there is no maximum. The first parameter is the format string. Printf works by simply printing its format string character-by-character, except that whenever it finds a '%' character, the next remaining parameter is printed in the format described by the character(s) immediately following the '%'. The most commonly used formats are %d which causes an integer parameter to be printed in the usual decimal style, and %s which prints a string. For example:
  printf("Hello, you."); prints  Hello, you.
  printf("6 times 9 is %d", 6*9); prints  6 times 9 is 54
  printf("%d times %d is %d", a, b, a*b); prints something like 12 times 102 is 1224
  printf("The %dth of %s", 22, "March"); prints  The 22th of March
  printf(s); prints the string s, unless it contains a %
  printf("one\ntwo\nthree"); prints  
one
two
three
Because printf gives complete control over the placement of newline characters, it is generally preferred over puts for the output of strings. Beware: printf(s) is normally thought of as equivalent to puts(s) (apart from the placement of the newline), but if the string ever contains a % symbol, it will fail. printf("%s", s) should be used instead.

Format Variations

%d: Integers in Decimal

The actual parameter corresponding to any variety of %d must be an int or char (signed and short are also accepted). Between the % and the d, other characters may be added to control the printing more exactly.

%u: Unsigned Integers in Decimal

The actual parameter corresponding to any variety of %u must be an int or char (unsigned, signed, and short are also accepted). All numbers are interpreted as being unsigned. Between the % and the u, other characters may be added to control the printing more exactly. These other characters are exactly as described above for the %d format.

%x and %X: Integers in Hexadecimal

The actual parameter corresponding to any variety of %x must be an int or char (unsigned, signed, and short are also accepted). All numbers are interpreted as being unsigned. Between the % and the x, other characters may be added to control the printing more exactly. These other characters are exactly as described above for the %d format.

%x prints a number in base 16, using the characters 0123456789abcdef for digits.
%X prints a number in base 16, using the characters 0123456789ABCDEF for digits.
A # character after the % forces the sequence 0x or 0X to appear in front of all non-zero values printed.

%o: Integers in Octal

The actual parameter corresponding to any variety of %o must be an int or char (unsigned, signed, and short are also accepted). All numbers are interpreted as being unsigned. Between the % and the o, other characters may be added to control the printing more exactly. These other characters are exactly as described above for the %d format.

%x prints a number in base 8, using the characters 01234567 for digits.
A # character after the % forces a leading zero to be printed.

%f: Floating Point Numbers

The actual parameter corresponding to any variety of %f must be a double or a float (NOT int: no automatic conversions are performed, failure will ensue). BEWARE: some systems get this wrong, and only accept a float. To be safe, use %f only for floats, and %lf only for doubles. (that is a lower case L, not the digit 1). The L appears immediately before the F if any extra formatting characters are added (e.g. %15.9lf). Between the % and the f, other characters may be added to control the printing more exactly.

%e and %E: Floating Point Numbers Almost in Scientific Notation

The actual parameter corresponding to any variety of %e must be a double or a float (NOT int: no automatic conversions are performed, failure will ensue). BEWARE: some systems get this wrong, and only accept a float. To be safe, use %e only for floats, and %le only for doubles. (that is a lower case L, not the digit 1). The L appears immediately before the E if any extra formatting characters are added (e.g. %15.9le). Between the % and the e, other characters may be added to control the printing more exactly.

%e and %E work in exactly the same way as %f, except that the number is always printed in scientific notation using the letter e or E to stand for "times ten to the power of". The e or E is always followed by a sign (+ or -) and some digits. The extra formatting characters described above for %f apply exactly to %e and %E.

%g and %G: Floating Point Numbers in Scientific Notation

The actual parameter corresponding to any variety of %g must be a double or a float (NOT int: no automatic conversions are performed, failure will ensue). BEWARE: some systems get this wrong, and only accept a float. To be safe, use %g only for floats, and %lg only for doubles. (that is a lower case L, not the digit 1). The L appears immediately before the G if any extra formatting characters are added (e.g. %15.9lg). Between the % and the g, other characters may be added to control the printing more exactly.

%g and %G work in exactly the same way as %e and %E, except that the number after the decimal point specifies the number of significant digits to be printed, instead of the number of digits to be printed after the decimal point.

%c: Single Characters

The actual parameter corresponding to any variety of %c must be an int or char (unsigned, signed, and short are also accepted). A single character (whose ascii code is equal to the parameter being printed) is printed.
      printf("%c", x);  is equivalent to  putchar(x); 

%s: Strings

The actual parameter corresponding to any variety of %s must be (a pointer to) an array of char. The array must be properly terminated with a zero. All characters from the beginning of the array, up to but not including the zero marker, are printed as with the %c format. Between the % and the e, other characters may be added to control the printing more exactly.

*: Computed Sizes

Anywhere in the above descriptions where a number appears (e.g. in %5d and %10.3f), the number may be replaced by a star (e.g. %*d, %10.*f, %*.3f, and %*.*f). When a star is encountered, it is replaced by the value of the next unused parameter, which must be an integer. For example, the following code prints 3, 3.1, 3.14, 3.142, 3.1416:
      const float pi=3.141592654;
      int i;
      for (i=0; i<=3; i+=1)
        printf("%10.*f\n", i, pi);

%n: Measuring the Output

When a %n format is encountered, it does not cause any additional printing. Instead, the total number of characters printed by the current call to printf is calculated, and stored in the variable indicated by the next unused parameter, which must be a pointer to an int. For example:
      int len, x=123, y=98989;
      printf("%d plus %d is %d%n\n", x, y, x+y, &len);
      printf("That line was %d characters long\n", len);

%i and %p: Unnecessary Formats

%i is an obsolete equivalent to %d
%p is used for printing pointers in a "sensible" format; it is usually equivalent to %08X

(back to top)



int scanf(char format[], ...)

Scanf is almost the opposite of printf. Its first parameter is a string of formats, almost exactly the same as the formats used with printf, but instead of printing its parameters according to the format, it scans input from the user, extracting data from it according to the format. All of the parameters must be pointers to variables of the appropriate type.
This means that when you wnt to read a value for any simple variable (i.e. not a string), you must put an ampersand & in front of its name in the parameter list. All of the examples below show this.

Inside a format string, % codes indicate the format for a value to be read; they may cause any number of input characters to be consumed. spaces and other invisible characters simply indicate that any amount of whitespace in the input stream should be consumed, so a single space in the format could result in 97 spaces and 14 blank lines being read. Any other character is expected to be exactly matched by the same character in the input.

Normally, it is not desirable to specify sizes and precisions with input formats: %d will read an integer of any size, %f will read a float of any size and any precision. However, sizes may be specified for special purposes. With input formats, sizes represent the maximum number of characters that will be consumed.

Examples:

Important Notes


(back to top)



int sprintf(char string[], char format[], ...)

The sprintf function is absolutely identical to the printf function, except for its extra first parameter. To understand sprintf, read it as printf, and gnore the first parameter. Whatever output printf would would produce is instead stored in the extra string that is provided to sprintf. For example, these two functions produce identical output:
    void main(void)
    { int x=3, y=12;
      printf("%d x %d = %d\n", x, y, x*y); }

    void main(void)
    { int x=3, y=12;
      char sss[100];
      sprintf(sss, "%d x %d = %d", x, y, x*y);
      puts(sss); }

(back to top)



int sscanf(char string[], char format[], ...)

The relationship between sscanf and scanf is the same as the relationship between sprintf and printf. To understand sscanf, read it as scanf and ignore the extra first argument. Whatever scanf would attempt to read from the input stream, sscanf instead attempts to read out of the string it is given.

sscanf will never read any input for itself, it can only read from the string it is given.

Because of this, a combinations of gets and sscanf is very often preferable to scanf alone; the programmer gains complete control over the reading of input lines. For example:
      char line[100];
      int x, y;
      gets(line);
      sscanf(line, "%d %d", &x, &y);
reads two integers from the user, so long as they are both entered on the same line. If the line does not contain two integers, it will not consume any further input.

(back to top)



int fprintf(FILE *fileref, char format[], ...)

Once you know how to print things normally using printf, there is almost nothing new to learn about writing data to a file. The fprintf function works exactly the same way (yes, exactly) as printf, except that it takes an extra parameter that describes a file. The output that fprintf produces is written to that file instead of to your terminal.

Before fprintf can be used on a file, a program must open that file, so that it is ready for use. Opening a file is very simple. The function
fopen takes two parameters, both strings. The first is the name of the file, the second is either "r" or "w", depending on whether you want to read from, or write to the file. The fopen function returns a special result which you use in all future function calls to refer to the file. The result returned from fopen is the special extra parameter that must be provided to fprintf.

Once you have a file open, you may use fprintf (and a number of other file output functions) as much as you need, to write data into the file. When you have finished, before the program terminates, the file should be closed; this ensures that whatever you wrote to the file is securely saved on disc before it is too late. The function fclose is used to close a file.

The only non-straight-forward thing is that the value returned by fopen is of a special system defined type called FILE&nbps;* (the star is an essential part of the type). There is nothing you need to know about the FILE * type, just use it with the file input/output functions as it is required. If for some reason the file you request can not be opened, fopen returns the special value NULL which is easy to detect.

Example program that prints the six times table in a file called sixes.txt:

      FILE *outfile = fopen("sixes.txt", "w");
      if (outfile==NULL)
      { printf("Error: Could not open the file!\n");
        return; }
      fprintf(outfile, "The six times table:\n");
      for (int i=1; i<=12; i+=1)
        fprintf(outfile, "%d times %d is %d\n", i, 6, 6*i);
      fclose(outfile);

There are other functions that can be used for file output, but fprintf is the most important, and can handle almost every need.

(back to top)



int fscanf(FILE *fileref, char format[], ...)

Once you know how to
print things to a file, reading things from a file is trivial. Just as there is an fprintf function that works exactly like printf except that it writes to a file, there is an fscanf function that works exactly like scanf, except that it reads things from a file.

The use of scanf follows the pattern of the use of printf exactly. First you must use fopen to open the file (this time specifying "r" for read instead of "w" for write as the second parameter), fopen returns a special FILE * value that is used as a reference to the file. To read data from the file, use fscanf exactly as you would use scanf, but with that file reference added as an extra first parameter. When you have finished with the file, use fclose to release it.

Example: the file numbers.txt contains a very large number of numbers; you want to find and report their average: (remember that scanf and fscanf return the number of items they successfully read, so failure to read anything can be used as an end-of-file test)

      FILE *infile = fopen("numbers.txt", "r");
      if (infile==NULL)
      { printf("Error: Could not open the file!\n");
        return; }
      int total=0, count=0;
      while (1)
      { int n, x;
        n=fscanf(infile, "%d", &x);
        if (n!=1) break;
        total+=x;
        count+=1; }
      fclose(infile);
      printf("The average of the %d numbers is %f\n", count, ((float)total)/count);

There are other functions that can be used for file input, but fscanf is the most important, and can handle almost every need.

(back to top)



FILE *fopen(char filename[], char access[])

A file must be opened before a program can read or write its contents. The file's name alone is not enough, all of the stdio functions that operate on files must be provided with a File Reference as an additional parameter. fopen opens a file, prepares it for processing, and returns just such a file reference. The result of fopen must be kept in a variable of type FILE * and passed to any function that needs to access that file.

fopen takes two parameters, both strings. The first is simply the name of the file. The second parameter describes the kind of access that you want. If you specify read access when opening a file, the program will be unable to write to that file, and vice-versa. The common strings that may be used to specify access types are: Less commonly used access strings are: If the fopen operation fails (the file does not exist, or is protected, or whatever), the function returns the special value NULL, which is easy to test for. See the
example for fprintf.

(back to top)



int fclose(FILE *fileref)

Every file that is opened by a program should, at some point, be closed by that program. Once a file is closed, it can no longer be accessed. However, after closing a file it is always possible to open it again. If a program is to write data to a file then read that same data back, it is usually best to open the file for writing only, then write the data, then close the file, then open it again for reading only, then read the data, then close it again.

The parameter given to fclose is the file reference produced by fopen when the file was opened. The result returned by fclose is normally ignored, but is in fact an error signal. If the result is zero, that means that the close operation was successful. Non-zero means something went wrong. It is difficult to deal with a failure to close a file, so the result is usually completely ignored.

See the
example for fprintf.

(back to top)



int fputc(int c, FILE *fileref)

The fputc function works in exactly the same was as
putchar, except that it writes the character to a file instead of to the standard output stream. The first parameter, int integer, must be the ASCII code for the character to be printed, the second is the file reference for the file, as returned by fopen.

Normally, the value returned by fputc is exactly the same as the first parameter: it returns the ascii value of the character that it wrote. However, if the output operation failed for some reason, it returns the special constant EOF instead. It is very rare to test for this kind of error.

(back to top)



int fgetc(FILE *fileref)

The fgetc function works in exactly the same was as
getchar, except that it reads a character from a file instead of from the standard input stream. The parameter is the file reference for the file, as returned by fopen.

The value returned by fgetc is an int, not a char. This is important. If there are no more characters in the file to bre read, fgetc returns the special constant EOF, which is defined to be -1. Normal char variables may not be capable of storing -1 (sometimes char is an unsigned type), and using a char may result in being unable to detect end of file.

Example: this program copies the file "in.txt" to the file "out.txt" exactly:

      FILE *infile = fopen("in.txt", "r");
      FILE *outfile = fopen("out.txt", "w");
      if (infile==NULL)
      { printf("Error: Could not read in.txt!\n");
        return; }
      if (outfile==NULL)
      { printf("Error: Could not create out.txt!\n");
        return; }
      while (1)
      { int c=fgetc(infile);
        if (c==EOF) break;
        fputc(c, outfile); }
      fclose(infile);
      fclose(outfile);

(back to top)



int ungetc(int c, FILE *fileref)

The ungetc reverses the effect of a single call to fgetc or getchar. After reading a character, ungetc can be used to un-read it. After using ungetc, the next call to getc will re-read the character that ungetc un-read.

For example, if a program is to red a file that contains a mixture of words (strings) and numbers. The words are to be ignored, but all the numbers are to be processed (perhaps added up). The simplest way is to read one character at a time, and look at that character. If it is not a digit just continue reading the file. If it is a digit, use fscanf with the "%d" format to read the number. But, after reading the first character and seeing that it is a digit, you have ruined the number; if the file contains "123", after reading the "1" the program would realise that there is a number, but then only the "23" would be left for scanf to process. Ungetc solves the problem.

Example, adding together all the numbers that appear in a text file:

    int total=0;
    while (1)
    { int c, n;
      c==fgetc(infile);
      if (c==EOF) break;
      if (c<'0' || c>'9') continue;
      ungetc(c, infile);
      fscanf(infile, "%d", &n);
      total+=n; }

(back to top)



char *fgets(char str[], int length, FILE *fileref)

fgets reads an entire line (up to a maxiumum length) from a file into a string (i.e. into an array of char). The three parameters are: the array of characters to be read into, the maximum number of characters to read, and the file reference (as returned by
fopen for the file. If you want to read from the terminal (standard input), the pre-defined value stdin should be used as the file reference.

The array should be at least 2 characters longer than the longest line that is expected as a possible input. This is because one extra character is always required to mark the end of a string, and because fgets reads the whole line including the "newline" or "enter" character at the end. The second parameter should be one less than the actual size of the array, because the end-of-string character is not counted.

Always remember that fgets reads the "newline" character '\n' and puts it at the end of the string as an extra character. If the file being read contains the three character line "CAT", fgets will read it as a four character string 'C', 'A', 'T', '\n'. It will need a five character array to store it: 'C', 'A', 'T', '\n', '\0'. Normally the first thing a program does after reading a line is to check for the '\n' at the end and remove it. The strlen function counts the number of characters in a char array, and can be used for this purpose.

Example: reading a file line-by-line:

    char line[1000];
    for (int n=1; 1; n+=1)
    { char *s = fgets(line, 999, infile);
      if (s==NULL) break;
      int len = strlen(line);
      if (line[len-1] != '\n')
      { printf("file contains a line >999 chacaters long\n");
        return; }
      line[len-1] = '\0';
      printf("line %d: '%s'\n", n, line); }
Important notes:
        If the line is too long to fit in the array size specified, fgets will read as much of it as will fit. When this happens, there is no "newline" '\n' at the end of the string. The "newlines" are not imagined by the system, they are only put into the array to represent a real end-of-line. So, a too-long line can be detected by finding that there is no '\n' at the end. In this case, the next fgets will attempt to read the rest of that line; it does not just skip to the beginning of the next line.
        If something goes wrong while reading the line (almost certainly this would mean reaching the end of the file), fgets returns the special constant NULL, which is easy to detect.

(back to top)



int fputs(char str[], FILE *fileref)

fputs is the counterpart of fgets; it is used for writing whole lines that already have a newline character '\n' at the end (as produced by fgets). fputs does not automatically start a new line.

The value returned by fputs is almost never used. It is zero if the operation was successful, or the special constant EOF otherwise. Example: reading a file line-by-line and displaying it on the user's terminal:

    char line[1000];
    while (1)
    { char *s = fgets(line, 999, infile);
      if (s==NULL) break;
      fputs(line, stdout); }
Note that in this example, it doesn't matter if a line in the file is too long, it will simply be read by multiple successive calls to fgets; only the last will provide a '\n' at the end and thus start a new line of output. Example: writing a three line file FILE *outfile=fopen("three.txt", "w"); fputs("This is the first line\n", outfile); fputs("This is the second line\n", outfile); fputs("This is the last line.\n", outfile); fclose(outfile);

(back to top)



The End