The ANSI library provides a suite of high-level functions to manage all kinds of input and output, with the appropriate buffering, as uniform data streams.
When a file is opened, for example, a new stream is created along with a file pointer, which is a pointer to a structure of type FILE that contains information about the stream. This information includes the address of the buffer, the number of bytes not yet read, and other information about the file itself. The file pointer is used to identify the file in all subsequent operations.
Devices such as the display are addressed in the same way as files. When the program starts, three streams are open by default, with the following file pointers:
The standard input device
stdout
The standard output device
stderr
The standard output device for error messages
stdin is generally associated with the keyboard, while stdout and stderr are associated with the display, unless redirection has been performed using the function freopen() or by the environment in which the program is running.
There is no predefined file structure in C: every file is assumed to contain simply a sequence of bytes. The internal structure of a file is completely left up to the program that uses it.
All read and write operations are applied at the current file position , which is the position of the next character to be read or written, and is always recorded in the FILE structure. When the file is opened, the file position is 0. It is increased by 1 with every character that is read or written. Random file access is achieved by means of functions that adjust the current file position.
In ANSI C99, characters in the extended character set can also be written to files. Thus any file used in read or write functions can be either byte-oriented or wide-oriented. After a file is opened and before any read or write access takes place, the file has no orientation. As soon as a byte input/output function is performed on the file, it becomes byte-oriented. If the first function that reads from or writes to the file is a wide-character input or output function, the file becomes wide-oriented. The function fwide() can also be used before the first access function to set the file's orientation, or to obtain its orientation at any time.
Only wide characters can be written to a wide-oriented file. The appropriate read and write functions thus perform conversion between wide characters with type wchar_t and the multibyte character encoding of the stream. For every wide-oriented stream, the momentary multibyte character parsing state is stored in an object with type mbstate_t. Byte access to wide-oriented files, and wide-character access to byte-oriented files, are not permitted.
Errors on file access are indicated by the return value of the file access function. When the end of a file is encountered by a read function, for example, the symbolic constant EOF (for byte-oriented files) or WEOF (for wide-oriented files) is returned. If a read or write error has occurred, an error flag is also set in the FILE structure.
Furthermore, in reading or writing wide-oriented streams, errors can occur in the conversion between wide characters of type wchar_t and multibyte characters in the stream. This is the case if one of the conversion functions mbrtowc() and wcrtomb() does not return a permissible value. The global error variable errno then has the value EILSEQ ("error: illegal sequence").
The following functions, macros, and symbolic constants are declared in the header file stdio.h. In the descriptions below, fp designates the file pointer. Functions with type int return 0 to indicate success, or a value other than 0 in case of errors.
void clearerr ( FILE *fp );
Clears the error and end-of-file flags.
int fclose ( FILE *fp );
Closes the file.
int feof ( FILE *fp );
Tests whether the end of the file has been reached. Returns a value not equal to 0 if the end-of-file flag is set, or 0 if it is not.
int ferror ( FILE *fp );
Tests whether an error occurred during file access. Returns a value not equal to 0 if the error flag is set, or 0 if it is not.
int fflush ( FILE *fp );
Causes any unwritten data in the file buffer to be written to the file. Returns EOF if an error occurs, or 0 on success.
int fgetpos ( FILE *fp , fpos_t *ppos );
Determines the current file position and copies it to the variable addressed by ppos. The type fpos_t is generally defined as long.
FILE *fopen ( const char *name , const char *mode );
Opens the file name with the access mode mode. Possible access mode strings are "r" (read), "r+" (read and write), "w" (write), "w+" (write and read), "a" (append), and "a+" (append and read). For modes "r" and "r+", the file must already exist. Modes "w" and "w+" create a new file, or erase the contents of an existing file. Text or binary access mode can be specified by appending t or b to the mode string. If neither is used, the file is opened in text mode.
The maximum length of a filename is the constant FILENAME_MAX. The maximum number of files that can be open simultaneously is FOPEN_MAX.
int fsetpos ( FILE *fp , const fpos_t *ppos );
Sets the file position to the new value referenced by ppos.
long ftell ( FILE *fp );
Returns the current file position.
FILE *freopen ( const char *name , const char *mode ,
FILE *fp );
Closes and reopens the file name with the access mode mode using the existing file pointer fp.
int fseek ( FILE *fp , long offset , int origin );
Moves the file position to offset bytes from the beginning of the file (if origin = SEEK_SET), or from the current file position (if origin = SEEK_CUR), or from the end of the file (if origin = SEEK_END). The constants SEEK_SET, SEEK_CUR, and SEEK_END are usually defined as 0, 1, and 2.
void perror ( const char *string );
After a system function call has resulted in an error, you can use perror() to write the string pointed to by string to stderr, followed by a colon and the appropriate system error message.
int remove ( const char *filename );
Makes the file named filename unavailable by that name. If no other filenames are linked to the file, it is deleted.
int rename ( const char *oldname , const char *newname );
Changes the name of the file whose name is addressed by oldname to the string addressed by newname.
void rewind ( FILE *fp );
Sets the file position to the beginning of the file, and clears the end-of-file and error flags.
void setbuf ( FILE *fp , char *buf );
Defines the array addressed by buf as the input/output buffer for the file. The buffer must be an array whose size is equal to the constant BUFSIZ. If buf is a null pointer, then the input/output stream is not buffered.
int setvbuf ( FILE *fp , char *buf , int mode , size_t sz );
Defines the array buf with length sz as the input/output buffer for the file. The parameter mode is one of the following constants: _IOFBF (full input/output buffering), _IOLBF (line-wise input/output buffering), or _IONBF (no input/output buffering). If buf is a null pointer, then a buffer of size sz is dynamically allocated.
FILE *tmpfile( void );
Opens a temporary file in binary read/write mode. The file is automatically deleted at the end of the program. The program should be able to open at least TMP_MAX temporary files. The symbolic constant TMP_MAX is greater than or equal to 25.
char *tmpnam ( char *s );
Generates a unique filename that can be used to create a temporary file. If s is a null pointer, the filename generated is stored in an internal static buffer. Otherwise, s must point to a char array with a length of at least L_tmpnam bytes, in which the function stores the new name.
The classic functions for reading from and writing to files are declared in the header file stdio.h. In the descriptions that follow in Table 1-23, fp designates the file pointer. Those functions that have no parameter with the file pointer type read from stdin or write to stdout.
For each of these input/output functions, there is also a corresponding function for wide-oriented access. The wide functions are declared in the header file wchar.h(*). Their names are formed with wc (for wide character) in place of c (for character), or with ws (for wide string) in place of s (for string).
The following file access functions can be used to read or write a block of characters:
size_t fwrite ( const void *buf , size_t sz , size_t n ,
FILE *fp );
Writes n objects of length sz from the buffer addressed by buf to the file.
size_t fread ( void *buffer , size_t sz , size_t n ,
FILE *fp );
Reads up to n objects of length sz from the file and copies them to the memory location pointed to by buf.
Both functions return the number of objects transferred. If the return value is less than the argument n, then an error occurred, or fread() encountered the end of the file.
The printf functions provide formatted output:
int printf ( const char *format , ... /*arg1 , ... , argn */ );
Writes the format string pointed to by format to the standard output stream, replacing conversion specifications with values from the argument list arg1, ... , argn.
int fprintf ( FILE *fp , const char *format , ... );
Like printf(), but writes the format string format to the file indicated by the file pointer fp.
int vprintf ( const char *format , va_list arg );
Like printf(), but with the variable argument list replaced by an object of type va_list that has been initialized using the va_start macro.
int vfprintf ( FILE *fp , const char *format , va_list arg );
Like fprintf(), but with the variable argument list replaced by an object of type va_list that has been initialized using the va_start macro.
All of the printf functions return the number of characters written, or EOF if an error occurred.
In the following example, the function printf() is called with one conversion specification:
printf( "%+10.2f", sin( 1.2 ) );
The resulting output displays the signed value of sin(1.2) to two decimal places, right-justified in a field 10 spaces wide.
The general format of the conversion specifications used in the printf functions is as follows:
%[flags][field width][.precision]specifier
The flags consist of one or more of the characters +, ' ' (space), - , 0 , or #. Their meanings are:
The plus sign is prefixed to positive numbers.
' ' (space)
A leading space is prefixed to positive numbers.
-
The output is left-justified in the field.
0
The field is filled with leading zeroes to the left of the number.
#
Alternate conversion rules are used as follows: If specifier is A(*), a(*), E, e, G, or g, floating-point numbers are formatted with a decimal point. If specifier is X, x, or o, hexadecimal integers are formatted with the 0X or 0x prefix, and octal integers with the 0 prefix.
The field width is a positive integer that fixes the length of the field occupied by the given conversion specification in the output string. If the flags include a minus sign, the converted value appears left-justified in the field; otherwise, it is right-justified. The excess field length is filled with space characters. If the output string is longer than the field width, the field width is increased as necessary to print the string in its entirety.
An asterisk (*) may also be specified for the field width. In this case, the field width is determined by an additional argument of type int, which immediately precedes the argument to be converted in the argument list.
.precision determines the number of decimal places printed in the output of floating-point numbers, when specifier is f or e. If specifier is g, .precision determines the number of significant digits. Rounding is performed if necessary. For floating-point numbers, the default value for .precision is 6.
For integers, .precision indicates the minimum number of digits to be printed. Leading zeroes are prefixed as necessary. For integers, the default value for .precision is 1.
If the argument to be converted is a string, then .precision indicates the maximum number of characters of the string that should appear.
specifier is the conversion specifier, indicating how the given argument is to be interpreted and converted. Note that specifier must correspond to the actual type of the argument to be converted. The possible conversion specifiers are listed in Table 1-24.
The letter l (that's an ell) can be prefixed to the c or s conversion specifiers to indicate a wide character or a wide string.
The letters l or ll(*) can also be prefixed to the conversion specifiers d , i , u , o , x , and X to indicate an argument of type long or long long(*). Similarly, h or hh can be prefixed to the same conversion specifiers to indicate an argument of type short or char.
An argument of type long double can be converted by using the prefix L with the conversion specifier f , e , E , g , G , a, or A.
Furthermore, ANSI C99 has introduced the following extensions:
· The new conversion specifiers A and a can be used to print a number of type double in hexadecimal exponential notation (0Xh.hhhhP±d or 0xh.hhhhp±d). This conversion uses FLOAT_RADIX, which is generally defined as 2, as the base. If no precision is specified, the number is printed with as many decimal places as necessary for exact representation.
· Arguments of type intmax_t(*) or uintmax_t(*) can be converted by prefixing the letter j to the conversion specifiers d, i, o, u, x, or X. Similarly, the argument type size_t is indicated by the prefix z, and the type ptrdiff_t by the prefix t.
· For the integer types defined in the header file stdint.h(*) (such as int16_t and int_least32_t), there are separate conversion specifiers for use in printf() format strings. These conversion specifiers are defined as macros in the header file inttypes.h(*). The macro names for the conversion specifiers corresponding to d, i, o, x, and X begin with the prefixes PRId, PRIi, PRIo, PRIu, PRIx, and PRIX. For example, the macro names beginning with PRId are:
PRIdN PRIdLEASTN PRIdFASTN PRIdMAX PRIdPTR
where N is the width in bits (usually 8, 16, 32, or 64). For example:
intmax_t i = INTMAX_MAX;
printf("Largest integer value: %20" PRIdMAX "\n",i );
The scanf() input functions are the counterparts to the printf() formatted output functions. They are used to read file input under control of a format string and convert the information for assignment to variables.
int scanf ( const char *format , ... /*arg1 , ... , argn */ );
Reads characters from standard input and saves the converted values in the variables addressed by the pointer arguments arg1, ... , argn. The characters read are converted according to the conversion specifications in the format string format.
int fscanf ( FILE *fp , const char *format , ... );
Like scanf(), but reads from the file specified by fp rather than standard input.
int vfscanf ( FILE *fp , const char *format , va_list arg );
Like fscanf(), but with the variable argument list replaced by an object (arg) of type va_list that has been initialized using the va_start macro. See "Functions with Variable Numbers of Arguments" earlier in this book for information on va_list and va_start.
int vscanf ( const char *format , va_list arg );
Like scanf(), but with the variable argument list replaced by an object (arg) of type va_list that has been initialized using the va_start macro. See "Functions with Variable Numbers of Arguments" earlier in this book for information on va_list and va_start.
All of the scanf functions return the number of successfully converted input fields. The return value is EOF if the first input field could not be read or converted, or if the end of the input file was reached.
The general format of the conversion specifications used in the scanf functions is as follows:
%[field width]specifier
For example:
scanf( "%5d", &var ); // var has type int
For each conversion specification in the format string, the next input item is read, converted, and assigned to the variable pointed to by the corresponding argument. Input fields are separated by whitespace characters (space, tab, and newline characters).
field width indicates the maximum number of characters to be read and converted. The next input field begins with the first character not yet processed.
specifier corresponds to the conversion specifiers in output format strings, except for the following differences:
· %i is used to read decimal, octal, and hexadecimal integers. The base is determined by the number's prefix, as for constants in source code.
· %f converts input for assignment to a variable of type float, and %lf to a variable of type double.
· %c reads the next character, which may also be a space. All other conversion specifiers read the next input item, skipping over any spaces that precede it.
· %s reads a string and appends the string terminator character '\0'. The conversion specifier for a string, s, may be replaced by a sequence of characters in square brackets, called the scanlist. In this case, each character read must match one of these characters. For example, use %[1234567890] to read only digits. The first character that does not match any of the characters in the scanlist terminates the input item. If the scanlist begins with a caret (^), then the input item is terminated by the first character in the input stream that does match one of the other characters in the scanlist. A hyphen can be used to indicate a sequence of consecutive search characters. For example, the scanlist [a-f] is equivalent to [abcdef].
If a conversion specification contains an asterisk (*) after the percent sign (%), then the input item is read as specified, but not assigned to a variable. In effect, that input field is skipped. Such a conversion specification corresponds to no variable argument.
Any character that cannot be interpreted according to the conversion specification terminates the current input field, and is put back into the input buffer. This character is then the first one read for the next input item.
The format string can also contain other characters that do not form part of a conversion specification and are not whitespace. The scanf functions expect such characters to be matched in the input stream, but do not convert or save them. If non-matching characters occur in the input, the function stops reading from the file. However, a whitespace character in the format string matches any sequence of whitespace characters in the input. For example, if the format string " %c" is used to read an individual character, any leading whitespace is skipped.
As for printf(), ANSI C99 defines separate conversion specifiers for reading fixed-width integer variables, such as int_least32_t. The corresponding macro names, defined in the header file inttypes.h(*), have the prefix SCN (for "scan") rather than PRI (for "print").
The header file wchar.h(*) contains the declarations of wprintf(), wscanf(), and related functions. These functions provide input and output controlled by a wide format string. The conversion specifications and their interpretation are identical to those of the printf() and scanf() functions.