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 |
| | | | | | | | | | |
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.
- Normally, numbers are printed using the smallest number of characters possible, no leading zeros or spaces.
putting a number between % and d (the number must not be written with a leading zero) specifies a minimum number
of characters to be used. Numbers that are not naturally big enough are padded out with leading spaces.
For example, with the format %4d numbers between 0 and 9 are preceeded by three spaces; numbers between
10 and 99, or between -1 and -9 are preceeded by two spaces (the minus sign is counted in the size); numbers
between 100 and 999 or between -10 and -99 are preceeded by a single space; all other numbers are printed as normal.
- An alternative form of padding is to use leading zeros instead of spaces. If the number between the % and the d
is itself written with a leading zero, the number printed will be padded with leading zeros instead of spaces.
For example, with the format %05d, numbers between 10 and 99 are printed with 3 leading zeros.
- If a - (a minus sign) appears between the % and the number, making it appear to be negative, padding is
added to the right of the output instead of to the left. This provides for left justification of numbers.
- If a + (a plus sign) appears between the % and the number, the sign of the number will always be printed.
Normally, negatives are printed with a - sign, but positives are printed without any sign.
- If a space appears between the % and the number (instead of a +), a space will be left in front of all positive
values printed.
- If a dot (or decimal point) appears, followed by a number, that provides the minimum number of digits to be printed.
The normal number described above specifies the minimum for the total number of characters to be used. %3d
will print 3 digits for positive numbers, but only two for negatives. %.3d prints at least 3 digits
regardless of the sign.
%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.
- Normally, numbers are printed in a default format which is not very pleasing to the eye.
- The most commonly used format specification follows the form %.6f (the 6 could be replaced by any number).
This specifies that the number should be printed with exactly 6 digits after the decimal point.
- The format %.0f printd a floating point value rounded to the nearest integer; no decimal point is printed.
- Another commonly used format specification follows the form %14.6f (the 14 and 6 could be replaced by any numbers).
This specifies that the number should be printed with exactly 6 digits after the decimal point, and should occupy
at least 14 characters in total; padding consists of spaces added to the left.
- Other format modifying characters as decribed above for the %d format are also allowed.
%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.
- A number, as used to specify the minimum size with %d, also specifies the minimum size for a string. If the string
is shorter than this minimum size, it is padded to the left with spaces. printf("%9s", "cat"); prints six
spaces before the letters cat. The size is a minimum not a maximum, long strings are not truncated.
- The number may be preceeded by a minus sign, in which case padding is added to the right instead.
- If a decimal point appears before the number, then the number becomes a maximum size. Strings longer than the maximum
are truncated, and do not need to be properly zero terminated.
- There may be two numbers with a decimal point between them: the first number gives the minimum size, and the second
gives the maximum. For example, printf("%-9.9s", xxx); prints the string xxx in exactly nine
characters. If it is longer, only the first 9 are printed; if it is shorter, spaces are added to the right (right
because of the minus sign).
*: 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:
- scanf("%d", &x); (requires that x is an int variable), reads an integer consisting of
any number of digits from the input, and stores its value in the variable x. It is willing to skip any amount
of whitespace in the input stream.
- scanf("%d %d", &x, &y); reads two integers consisting of
any number of digits from the input, and stores their values in the variables x and y. The two
values do not need to be on the same line of input.
- scanf("%1d%1d%1d", &x, &y, &z); reads three single digit integers from the input.
It is assumed that the three digits will be run together without separation (i.e. they look like a single three-digit
number), but they will be read as separate numbers. When a size is specified, no separating spaces are needed.
- scanf("%d %s", &x, y); (assuming x is an int variable, and y is a char array; array
names are automatically treated as pointers) will skip any amount of space before reading an integer int x,
then skip any further amount of white space (including newlines) before reading a string into y. The string
may not contain any white space; %s stops reading as soon as it reaches a space or newline.
- scanf("%5s%5s",x, y); (assuming x and y are char arrays)
will read two strings of at most 5 characters into x and y. If a string of more than 5 characters
is encountered, the first 5 will be read into x, and the remainder up to a further 5 into y.
Separating spaces are not needed when a string size is specified.
- scanf("%s %d/%d/%d", day, &year, &month, &day); is suiable for reading dates in this format:
"sat 2000/12/02".
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:
- "r": read only. The file must already exist.
- "w": write only. If the file does not exist, it is created; if it does already exist,
its contents are lost.
- "a": (append) write only. If the file does not exist, it is created; if it does
already exist, the contents are kept, the first thing written by this program is added to the end of
the file.
Less commonly used access strings are:
- "r+": reading and writing are both allowed, but beware: writing
overwrites anything already in the file. The file must already exist.
- "w+": same as "r+" except that the file is created if it does not exist,
and all contents of already existing files are lost.
- "a+": same as "r+", except that the contents of an existing file are not lost;
the first write adds data to the end of the file.
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