C langugae : File Input/Output

Data Organization
All data stored on the disk is in binary form. This binary data is stored on the disk varies from one OS to another. However, this does not affect the C programmer since he has to use only the library functions written for the particular OS to be able to perform input/output. It is the compiler vendor’s responsibility to correctly implement these library functions by taking the help of OS. This is illustrated in Figure
After storing data on the disk, the computer helps you enter, find, change, and delete the data. The computer and C are simply tools to help you manage and process data.
Why Use a Disk?
The typical computer system has much less memory storage than hard disk storage. Your disk drive holds much more data than can fit in your computer's RAM. The disk memory, because it is nonvolatile, lasts longer because the disk retains its contents when you power-off your computer. Also, when your data changes, you (or more important, your users) do not have to edit the program and look for a set of assignment statements. Instead, the users run previously written programs that make changes to the disk data.
Types of Disk File Access
The programs can access files in two ways: through sequential access or random access. Your application determines the method you should choose. The access mode of a file determines how you read, write, change, and delete data from the file. Some of your files can be accessed in both ways, sequentially and randomly.Your C compiler might offer additional ways to access disk files with a library of specific I/O functions.A sequential file must be accessed in the same order the file was written. This is analogous to cassette tapes: You play music in the same order it was recorded(You can quickly fast-forward or rewind through songs but It is difficult, and sometimes impossible, to insert song in the middle of a Cassette.Random access files in any order you want. Think of data in a random access file as you would think of songs on a compact disc or a record; you can go directly to any song you want without having to play or fast-forward through the other songs. If you want to play the first song, the sixth song, and then the fourth song, you can do so.
Communicating with Files
File : - A file represents a sequence of bytes. The fopen( ) function associates a file with a stream and initializes an object of the type FILE, which contains all the information necessary to control the stream. Such information includes a pointer to the buffer used; a file position indicator , which specifies a position to access in the file; and flags to indicate error and end-of-file conditions.
Each of the functions that open filesnamely fopen( ), freopen( ), and tmpfile( )returns a pointer to a FILE object for the stream associated with the file being opened. Once you have opened a file, you can call functions to transfer data and to manipulate the stream. Such functions have a pointer to a FILE objectcommonly called a FILE pointeras one of their arguments. The FILE pointer specifies the stream on which the operation is carried out.
The I/O library also contains functions that operate on the file system, and take the name of a file as one of their parameters. These functions do not require the file to be opened first. They include the following:
* The remove( ) function deletes a file (or an empty directory). The string argument is the file's name. If the file has more than one name, then remove( ) only deletes the specified name, not the file itself. The data may remain accessible in some other way, but not under the deleted filename.
* The rename( ) function changes the name of a file (or directory). The function's two string arguments are the old and new names, in that order. The remove( ) and rename( ) functions both have the return type int, and return zero on success, or a non-zero value on failure.
Text Streams and the Binary Streams
Text Streams: - A text stream transports the characters of a text that is divided into lines. A line of text consists of a sequence of characters ending in a newline character. A line of text can also be empty, meaning that it consists of a newline character only. The last line transported may or may not have to end with a newline character, depending on the implementation.
The internal representation of text in a C program is the same regardless of the system on which the program is running. Thus text input and output on a given system may involve removing, adding, or altering certain characters. For example, on systems that are not Unix-based, end-of-line indicators ordinarily have to be converted into newline characters when reading text files , as on Windows systems for instance, where the end-of-line indicator is a sequence of two control characters, \r (carriage return) and \n (newline). Similarly, the control character ^Z (character code 26) in a text stream on Windows indicates the end of the stream.
Binary Streams: - A binary stream is a sequence of bytes that are transmitted without modification. In other words, the I/O functions do not involve any interpretation of control characters when operating on binary streams . Data written to a file through a binary stream can always be read back unchanged on the same system. However, in certain implementations there may be additional zero-valued bytes appended at the end of the stream.
Binary streams are normally used to write binary datafor example, database recordswithout converting it to text. If a program reads the contents of a text file through a binary stream, then the text appears in the program in its stored form, with all the control characters used on the given system.

Although ANSI C provides for both a binary view and a text view, these views can be implemented identically. For example, because Unix uses just one file structure, both views are the same for Unix implementations.
Buffers
A stream has a buffer in which it collects characters, which are transferred as a block to or from the file. Sometimes you don't want buffering, however. For example, after an error has occurred, you might want to write data to a file as directly as possible.
Streams are buffered in one of three ways:
Fully buffered : - The characters in the buffer are normally transferred only when the buffer is full.
Line-buffered : - The characters in the buffer are normally transferred only when a newline character is written to the buffer, or when the buffer is full. A stream's buffer is also written to the file when the program requests input through an unbuffered stream, or when an input request on a line-buffered stream causes characters to be read from the host environment.
Unbuffered : - Characters are transferred as promptly as possible.
Standard I/O
The standard I/O package has two advantages, besides portability, over low-level I/O. First, it has many specialized functions that simplify handling different I/O problems. For example, printf() converts various forms of data to string output suitable for terminals. Second, input and output are buffered. That is, information is transferred in large chunks (typically 512 bytes at a time or more) instead of a byte at a time. When a program reads a file, for example, a chunk of data is copied to a buffer—an intermediate storage area. This buffering greatly increases the data transfer rate. The program can then examine individual bytes in the buffer. The buffering is handled behind the scenes, so you have the illusion of character-by-character access. (You can also buffer low-level I/O, but you have to do much of the work yourself.). If you're a Windows user, you might have to run the program in an MS-DOS window after compiling. If you're a Macintosh user, you should use console.h and the ccommand() function , "Character Strings and String Functions," and in the Code Warrior documentation. Alternatively, you can alter the program to use puts() and gets() instead of command-line arguments to get the filename.)
File Operations
There are different operations that can be carried out on a file. These are:
* Creation of a new file
* Opening an existing file Reading from a file
* Writing to a file
* Moving to a specific location in a file (seeking)
* Closing a file
Access Modes
The access mode specified by the second argument to fopen( ) or freopen( ) determines what input and output operations the new stream permits. The permissible values of the mode string are restricted. The first character in the mode string is always r for "read," w for "write," or a for "append," and in the simplest case, the string contains just that one character. However, the mode string may also contain one or both of the characters + and b (in either order: +b has the same effect as b+).
A plus sign (+) in the mode string means that both read and write operations are permitted. However, a program must not alternate immediately between reading and writing. After a write operation, you must call the fflush( ) function or a positioning function (fseek( ), fsetpos( ), or rewind( )) before performing a read operation. After a read operation, you must call a positioning function before performing a write operation.
A b in the mode string causes the file to be opened in binary modethat is, the new stream associated with the file is a binary stream. If there is no b in the mode string, the new stream is a text stream.
If the mode string begins with r, the file must already exist in the file system. If the mode string begins with w, then the file will be created if it does not already exist. If it does exist, its previous contents will be lost, because the fopen( ) function truncates it to zero length in "write" mode.
A mode string beginning with a (for append) also causes the file to be created if it does not already exist. If the file does exist, however, its contents are preserved, because all write operations are automatically performed at the end of the file.

Mode Strings for fopen()

Mode String

Meaning

"r" Open a text file for writing.
"w"

Open a text file for writing, truncating an existing file to zero length, or creating the file if it does not exist.

"a" Open a text file for writing, appending to the end of an existing file, or creating the file if it does not exist.
"r+" Open a text file for update (that is, for both reading and writing).
"w+" Open a text file for update (reading and writing), first truncating the file to zero length if it exists or creating the file if it does not exist.
"a+" Open a text file for update (reading and writing), appending to the end of an existing file, or creating the file if it does not yet exist; the whole file can be read, but writing can only be appended.

"rb", "wb", "ab",

"ab+", "a+b", "wb+",

"w+b", "ab+", "a+b"

Like the preceding modes, except it uses binary mode instead of text mode.


Reading and Writing
Byte-Oriented and Wide-Oriented Streams
In addition to the type char, C also provides a type for wide characters, named wchar_t. This type is wide enough to represent any character in the extended character sets that the implementation supports. Accordingly, there are two complete sets of functions for input and output of characters and strings: the byte-character I/O functions and the wide-character I/O functions. Functions in the second set operate on characters with the type wchar_t. Each stream has an orientation that determines which set of functions is appropriate.
Immediately after you open a file, the orientation of the stream associated with it is undetermined. If the first file access is performed by a byte-character I/O function, then from that point on the stream is byte-oriented. If the first access is by a wide-character function, then the stream is wide-oriented. The orientation of the standard streams, stdin, stdout, and stderr, is likewise undetermined when the program starts.
You can call the function fwide( ) at any time to ascertain a stream's orientation. Before the first I/O operation, fwide( ) can also set a new stream's orientation. To change a stream's orientation once it has been determined, you must first reopen the stream by calling the freopen( ) function.
The wide characters written to a wide-oriented stream are stored in the file associated with the stream as multibyte characters. The read and write functions implicitly perform the necessary conversion between wide characters of type wchar_t and the multibyte character encoding. This conversion may be stateful. In other words, the value of a given byte in the multibyte encoding may depend on control characters that precede it, which alter the shift state or conversion state of the character sequence. For this reason, each wide-oriented stream has an associated object with the type mbstate_t, which stores the current multibyte conversion state. The functions fgetpos( ) and fsetpos( ), which get and set the value of the file position indicator, also save and restore the conversion state for the given file position..
Error Handling
Return values and status flags
The I/O functions generally indicate any errors that occur by their return value. In addition, they also set an error flag in the FILE object that controls the stream if an error in reading or writing occurs. To query this flag, you can call the ferror( ) function. An example:
(void)fputc( '*', fp ); // Write an asterisk to the stream fp.
if ( ferror(fp) )
fprintf( stderr, "Error writing.\n" );
Furthermore, read functions set the stream's EOF flag on reaching the end of the file. You can query this flag by calling the feof( ) function. A number of read functions return the value of the macro EOF if you attempt to read beyond the last character in the file. (Wide-character functions return the value WEOF.) A return value of EOF or WEOF can also indicate an error.
The error variable errno
Several standard library functions support more specific error handling by setting the global error variable errno to a value that indicates the kind of error that has occurred. Stream handling functions that set errno include ftell( ), fgetpos( ), and fsetpos( ). Depending on the implementation, other functions may also set the errno variable. errno is declared in the header errno.h with the type int (see Chapter 15). errno.h also defines macros for the possible values of errno.
The perror( ) function prints a system-specific error message for the current value of errno to the stderr stream.
long pos = ftell(fp); // Get the current file position.
if ( pos < 0L ) // ftell( ) returns -1L if an error occurs.
perror( "ftell( )" );
The perror( ) function prints its string argument followed by a colon, the error message, and a newline character. The error message is the same as the string that strerror( ) would return if called with the given value of errno as its argument.
Reading characters
int fgetc( FILE * fp );
int getc( FILE *fp );
int getchar( void );
wint_t fgetwc( FILE *fp );
wint_t getwc( FILE *fp );
wint_t getwchar( void );
The fgetc( ) function reads a character from the input stream referenced by fp. The return value is the character read, or EOF if an error occurred. The macro getc( ) has the same effect as the function fgetc( ). The macro is commonly used because it is faster than a function call. However, if the argument fp is an expression with side effects (see Chapter 5), then you should use the function instead, because a macro may evaluate its argument more than once. The macro getchar( ) reads a character from standard input. It is equivalent to getc(stdin).
fgetwc( ), getwc( ), and getwchar( ) are the corresponding functions and macros for wide-oriented streams. These functions set the global variable errno to the value EILSEQ if an error occurs in converting a multibyte character to a wide character.
Putting a character back
int ungetc( int c, FILE *fp );
wint_t ungetwc( wint_t c, FILE *fp );
ungetc( ) and ungetwc( ) push the last character read, c, back onto the input stream referenced by fp. Subsequent read operations then read the characters put back, in LIFO (last in, first out) orderthat is, the last character put back is the first one to be read. You can always put back at least one character, but repeated attempts might or might not succeed. The functions return EOF (or WEOF) on failure, or the character pushed onto the stream on success
Reading characters
int fputc( int c, FILE *fp );
int putc( int c, FILE *fp);
int putchar( int c );
wint_t fputwc( wchar_t wc, FILE *fp );
wint_t putwc( wchar_t wc, FILE *fp );
wint_t putwchar( wchar_t wc );
The function fputc( ) writes the character value of the argument c to the output stream referenced by fp. The return value is the character written, or EOF if an error occurred. The macro putc( ) has the same effect as the function fputc( ). If either of its arguments is an expression with side effects , then you should use the function instead, because a macro might evaluate its arguments more than once. The macro putchar( ) writes the specified character to the standard output stream.
fputwc( ), putwc( ), and putwchar( ) are the corresponding functions and macros for wide-oriented streams. These functions set the global variable errno to the value EILSEQ if an error occurs in converting the wide character to a multibyte character.
Putting a character back
int ungetc( int c, FILE *fp );
wint_t ungetwc( wint_t c, FILE *fp );
ungetc( ) and ungetwc( ) push the last character read, c, back onto the input stream referenced by fp. Subsequent read operations then read the characters put back, in LIFO (last in, first out) orderthat is, the last character put back is the first one to be read. You can always put back at least one character, but repeated attempts might or might not succeed. The functions return EOF (or WEOF) on failure, or the character pushed onto the stream on success.
Writing characters
int fputc( int c, FILE *fp );
int putc( int c, FILE *fp);
int putchar( int c );
wint_t fputwc( wchar_t wc, FILE *fp );
wint_t putwc( wchar_t wc, FILE *fp );
wint_t putwchar( wchar_t wc );
The function fputc( ) writes the character value of the argument c to the output stream referenced by fp. The return value is the character written, or EOF if an error occurred. The macro putc( ) has the same effect as the function fputc( ). If either of its arguments is an expression with side effects , then you should use the function instead, because a macro might evaluate its arguments more than once. The macro putchar( ) writes the specified character to the standard output stream.
fputwc( ), putwc( ), and putwchar( ) are the corresponding functions and macros for wide-oriented streams. These functions set the global variable errno to the value EILSEQ if an error occurs in converting the wide character to a multibyte character.
Reading strings
char *fgets( char *buf, int n, FILE *fp );
char *gets( char *buf );
wchar_t *fgetws( wchar_t *buf, int n, FILE *fp );
The functions fgets( ) and fgetws( ) read up to n - 1 characters from the input stream referenced by fp into the buffer addressed by buf, appending a null character to terminate the string. If the functions encounter a newline character or the end of the file before they have read the maximum number of characters, then only the characters read up to that point are read into the buffer. The newline character '\n' (or, in a wide-oriented stream, L'\n') is also stored in the buffer if read.
gets( ) reads a line of text from standard input into the buffer addressed by buf. The newline character that ends the line is replaced by the null character that terminates the string in the buffer. fgets( ) is a preferable alternative to gets( ), as gets( ) offers no way to limit the number of characters read. There is no wide-character function corresponding to gets( ).
All three functions return the value of their argument buf, or a null pointer if an error occurred, or if there were no more characters to be read before the end of the file.
Writing strings
int fputs( const char *s, FILE *fp );
int puts( const char *s );
int fputws( const wchar_t *s, FILE *fp );
The three puts functions have some features in common as well as certain differences:
fputs( ) and fputws( ) write the string s to the output stream referenced by fp. The null character that terminates the string is not written to the output stream.
puts( ) writes the string s to the standard output stream, followed by a newline character. There is no wide-character function that corresponds to puts( ).
All three functions return EOF (not WEOF) if an error occurred, or a non-negative value to indicate success.
Reading and writing blocks
The fread( ) function reads up to n objects whose size is size from the stream referenced by fp, and stores them in the array addressed by buffer:
size_t fread( void *buffer, size_t size, size_t n, FILE *fp );
The function's return value is the number of objects transferred. A return value less than the argument n indicates that the end of the file was reached while reading, or that an error occurred.
The fwrite( ) function sends n objects whose size is size from the array addressed by buffer to the output stream referenced by fp:
size_t fwrite( const void *buffer, size_t size, size_t n, FILE *fp );
Again, the return value is the number of objects written. A return value less than the argument n indicates that an error occurred.
Because the fread( ) and fwrite( ) functions do not deal with characters or strings as such, there are no corresponding functions for wide-oriented streams. On systems that distinguish between text and binary streams, the fread( ) and fwrite( ) functions should be used only with binary streams.
The printf( ) function family
The printf( ) function and its various related functions all share the same capabilities of formatting data output as specified by an argument called the format string . However, the various functions have different output destinations and ways of receiving the data intended for output. The printf( ) functions for byte-oriented streams are:
int printf( const char * restrict format, ... );
Writes to the standard output stream, stdout.
int fprintf( FILE * restrict fp, const char * restrict format, ... );
Writes to the output stream specified by fp. The printf( ) function can be considered to be a special case of fprintf( ).
int sprintf( char * restrict buf, const char * restrict format, ... );
Writes the formatted output to the char array addressed by buf, and appends a terminating null character.
int snprintf( char * restrict buf, size_t n, const char * restrict format, ... );
Like sprintf( ), but never writes more than n bytes to the output buffer.
The ellipsis (...) in these function prototypes stands for more arguments, which are optional. Another subset of the printf( ) functions takes a pointer to an argument list, rather than accepting a variable number of arguments directly in the function call. The names of these functions begin with a v for "variable argument list":
int vprintf( const char * restrict format, va_list argptr );
int vfprintf( FILE * restrict fp, const char * restrict format,
va_list argptr );
int vsprintf( char * restrict buf, const char * restrict format,
va_list argptr );
int vsnprintf( char * restrict buffer, size_t n,
const char * restrict format, va_list argptr );
To use the variable argument list functions, you must include stdarg.h in addition to stdio.h.
There are counterparts to all of these functions for output to wide-oriented streams. The wide-character printf( ) functions have names containing wprintf instead of printf, as in vfwprintf( ) and swprintf( ), for example. There is one exception: there is no snwprintf( ). Instead, swprintf( ) corresponds to the function snprintf( ), with a parameter for the maximum output length.
The format string
One argument passed to every printf( ) function is a format string. This is a definition of the data output format, and contains some combination of ordinary characters and conversion specifications . Each conversion specification defines how the function should convert and format one of the optional arguments for output. The printf( ) function writes the format string to the output destination, replacing each conversion specification in the process with the formatted value of the corresponding optional argument.
A conversion specification begins with a percent sign % and ends with a letter, called the conversion specifier . (To include a percent sign % in the output, there is a special conversion specification: %%. printf( ) converts this sequence into a single percent sign.)
The syntax of a conversion specification ends with the conversion specifier. Throughout the rest of this section, we use both these terms frequently in talking about the format strings used in printf( ) and scanf( ) function calls.
Field widths
The field width option is especially useful in formatting tabular output. If included, the field width must be a positive decimal integer (or an asterisk, as described below). It specifies the minimum number of characters in the output of the corresponding data item. The default behavior is to position the converted data right-justified in the field, padding it with spaces to the left. If the flags include a minus sign (-), then the information is left-justified, and the excess field width padded with space characters to the right.
The following example first prints a line numbering the character positions to illustrate the effect of the field width option: printf("1234567890123456\n"); // Character positions.
printf( "%-10s %s\n", "Player", "Score" ); // Table headers.
printf( "%-10s %4d\n", "John", 120 ); // Field widths: 10; 4.
printf( "%-10s %4d\n", "Mary", 77 );
Printing characters and strings
The printf( ) conversion specifier for strings is s, as you have already seen in the previous examples. The specifier for individual characters is c (for char).

Conversion specifiers for printing characters and strings

Specifier

Argument types

Representation

c

int

A single character

s

Pointer to any char type

The string addressed by the pointer argument


char *team[ ] = { "Vivian", "Tim", "Frank", "Sally" };
char separator = ';';
for ( int i = 0; i < sizeof(team)/sizeof(char *); ++i )
printf( "%10s%c ", team[i], separator );
putchar( '\ n' );
Printing integers
The printf( ) functions can convert integer values into decimal, octal, or hexadecimal

Conversion specifiers for printing integers

Specifier

Argument types

Representation

d, i

int

Decimal

u

unsigned int

Decimal

o

unsigned int

Octal

x

unsigned int

Hexadecimal with lowercase a, b, c, d, e, f

X

unsigned int

Hexadecimal with uppercase A, B, C, D, E, F


Printing floating-point numbers

Conversion specifiers for printing floating-point numbers

Specifier

Argument types

Representation

f

double

Decimal floating-point number

e, E

double

Exponential notation, decimal

g, G

double

Floating-point or exponential notation, whichever is shorter

a, A

double

Exponential notation, hexadecimal


Formatted Input
To read in data from a formatted source, C provides the scanf( ) family of functions. Like the printf( ) functions, the scanf( ) functions take as one of their arguments a format string that controls the conversion between the I/O format and the program's internal data. This section highlights the differences between the uses of format strings and conversion specifications in the scanf( ) and the printf( ) functions.
The scanf( ) function family
The various scanf( ) functions all process the characters in the input source in the same way. They differ in the kinds of data sources they read, however, and in the ways in which they receive their arguments. The scanf( ) functions for byte-oriented streams are:
int scanf( const char * restrict format, ... );
Reads from the standard input stream, stdin.
int fscanf( FILE * restrict fp, const char * restrict format, ... );
Reads from the input stream referenced by fp.
int sscanf( const char * restrict src, const char * restrict format, ... );
Reads from the char array addressed by src.
The ellipsis (...) stands for more arguments, which are optional. The optional arguments are pointers to the variables in which the scanf( ) function stores the results of its conversions.
Like the printf( ) functions, the scanf( ) family also includes variants that take a pointer to an argument list, rather than accepting a variable number of arguments directly in the function call. The names of these functions begin with the letter v for "variable argument list": vscanf( ), vfscanf( ), and vsscanf( ). To use the variable argument list functions, you must include stdarg.h in addition to stdio.h.
There are counterparts to all of these functions for reading wide-oriented streams. The names of the wide-character functions contain the sequence wscanf in place of scanf, as in wscanf( ) and vfwscanf( ), for example.
The format string
The format string for the scanf( ) functions contains both ordinary characters and conversion specifications that define how to interpret and convert the sequences of characters read. Most of the conversion specifiers for the scanf( ) functions are similar to those defined for the printf( ) functions. However, conversion specifications in the scanf( ) functions have no flags and no precision options. The general syntax of conversion specifications for the scanf( ) functions is as follows:
%[*][field_width][length_modifier]specifier
Field widths
The field width is a positive decimal integer that specifies the maximum number of characters that scanf( ) reads for the given conversion specification. For string input, this item can be used to prevent buffer overflows:
char city[32];
printf( "Your city: ");
if ( scanf( "%31s", city ) < 1 ) // Never read in more than 31 characters!
fprintf( stderr, "Error reading from standard input.\ n" );
else
/* ... */
Unlike printf( ), which exceeds the specified field width whenever the output is longer than that number of characters, scanf( ) with the s conversion specifier never writes more characters to a buffer than the number specified by the field width.

Reading characters and strings
The conversion specifications %c and %1c read the next character in the input stream, even if it is a whitespace character. By specifying a field width, you can read that exact number of characters, including whitespace characters, as long as the end of the input stream does not intervene. When you read more than one character in this way, the corresponding pointer argument must point to a char array that is large enough to hold all the characters read. The scanf( ) function with the c conversion specifer does not append a terminating null character. An example:
scanf( "%*5c" );
This scanf( ) call reads and discards the next five characters in the input source.
The conversion specification %s always reads just one word, as a whitespace character ends the sequence read. To read whole text lines, you can use the fgets( ) function.
The following example reads the contents of a text file word by word. Here we assume that the file pointer fp is associated with a text file that has been opened for reading:
char word[128];
while ( fscanf( fp, "%127s", word ) == 1 )
{
/* ... process the word read ... */
}
In addition to the conversion specifier s, you can also read strings using the "scanset" specifier, which consists of an unordered set of characters between square brackets ([scanset]). The scanf( ) function then reads all characters, and saves them as a string (with a terminating null character), until it reaches a character that does not match any of those in the scanset. An example:
char strNumber[32];
scanf( "%[0123456789]", strNumber );
If the user enters 345X67, then scanf( ) stores the string 345\0 in the array strNumber. The character X and all subsequent characters remain in the input buffer.
To invert the scansetthat is, to match all characters except those between the square bracketsinsert a caret (^) immediately after the opening bracket. The following scanf( ) call reads all characters, including whitespace, up to a punctuation character that terminates a sentence; and then reads the punctuation character itself:
char ch, sentence[512];
scanf( "%511[^.!?]%c", sentence, &ch );
The following scanf( ) call can be used to read and discard all characters up to the end of the current line:
scanf( "%*[^\n]%*c" );
Reading integers
Like the printf( ) functions, the scanf( ) functions offer the following conversion specifiers for integers: d, i, u, o, x, and X. These allow you to read and convert decimal, octal, and hexadecimal notation to int or unsigned int variables. An example:
// Read a non-negative decimal integer:
unsigned int value = 0;
if ( scanf( "%u", &value ) < 1 )
fprintf( stderr, "Unable to read an integer.\n" );
else
/* ... */
For the specifier i in the scanf( ) functions, the base of the numeral read is not predefined. Instead, it is determined by the prefix of the numeric character sequence read, in the same way as for integer constants in C source code (see "Integer Constants" in Chapter 3). If the character sequence does not begin with a zero, then it is interpreted as a decimal numeral. If it does begin with a zero, and the second character is not x or X, then the sequence is interpreted as an octal numeral. A sequence that begins with 0x or 0X is read as a hexadecimal numeral.
To assign the integer read to a short, char, long, or long long variable (or to a variable of a corresponding unsigned type), you must insert a length modifier before the conversion specifier: h for short, hh for char, l for long, or ll for long long. In the following example, the FILE pointer fp refers to a file opened for reading:
unsigned long position = 0;
if ( fscanf( fp, "%lX", &position ) < 1 ) // Read a hexadecimal integer.
/* ... Handle error: unable to read a numeral ... */
Reading floating-point numbers
To process floating-point numerals, the scanf( ) functions use the same conversion specifiers as printf( ): f, e, E, g, and G. Furthermore, C99 has added the specifiers a and A. All of these specifiers interpret the character sequence read in the same way. The character sequences that can be interpreted as floating-point numerals are the same as the valid floating-point constants in C; see "Floating-Point Constants" in Chapter 3. scanf( ) can also convert integer numerals and store them in floating-point variables.
All of these specifiers convert the numeral read into a floating-point value with the type float. If you want to convert and store the value read as a variable of type double or long double, you must insert a length modifier: either l (a lowercase L) for double, or L for long double. An example:
float x = 0.0F;
double xx = 0.0;
// Read in two floating-point numbers; convert one to float and the other
// to double:
if ( scanf( "%f %lf", &x, &xx ) < 2 )
/* ... */
If this scanf( ) call receives the input sequence 12.3 7\n, then it stores the value 12.3 in the float variable x, and the value 7.0 in the double variable xx.
The following program creates a file called NAMES.DAT. The program writes five names to a disk file using fputs():
/* Filename: akb.C */ Writes five names to a disk file */ #include < stdio.h >
FILE *fp;
main()
{
fp = fopen(''NAMES.DAT", "w"); /* Creates a new file */
fputs("Anuj Bhargava\n", fp);
fputs("Babloo Bhargava\n", fp);
fputs("Prem Chand Bhargava\n", fp);
fputs("Mani Bhargava\n", fp);
fputs("Bhavya Bhargava\n", fp);
fclose(fp); /* Release the file */
return 0;
}
Output
NAMES.TXT is a text data file. If you like, you can read this file into any word processor such as the Windows WordPad (the file comes in as a text-based ASCII file). If you were to view NAMES.TXT, you would see
Anuj Bhargava
Babloo Bhargava
Prem Chand Bhargava
Mani Bhargava
Bhavya Bhargava
2. The following file writes the numbers from 1 to 100 to a file called Nums. 1:
/* Filename: anuj2.C
Writes 1 to 100 to a disk file */
#include < stdio.h >
FILE *fp;
main()
{
int ctr;
fp = fopen("NUMS. 1", "wt"); /* Creates a new file */
if (fp == NULL)
{ printf("Error opening file.\n"); }
else
{ for (ctr=1; ctr<101; ctr++)
{ fprintf(fp, ''%d ", ctr); } /* Writes the data */ }
fclose(fp);
return 0;
}
Writing to a Printer
The fopen() and other output functions were not designed to just write to files. They were designed to write to any device, including files, the screen, and the printer. If you need to write data to a printer, you can treat the printer as if it were a file. The following program opens a FILE pointer using the MS-DOS name for a printer located at LPT1 (the MS-DOS name for the first parallel printer port):
/* Filename: anuj3.C
Prints to the printer device */
#include
FILE *prnt; /* Points to the printer */
main()
{
prnt = fopen("LPT1", "w");
fprintf(prnt, "Printer line 1\n"); // 1st line printed
fprintf(prnt, "Printer line 2\n"); // 2nd line printed
fprintf(prnt, "Printer line 3\n"); // 3rd line printed
fclose(prnt);
return 0;
}
Reading from a File
3. This program asks the user for a filename and prints the contents of the file to the screen. If the file does not exist, the program displays an error message:
/* Filename: anuj3.C
Reads and displays a file */
#include < stdio.h >
FILE *fp;
main()
{
char filename[12]; // Holds user's filename
int inChar; // Input character
printf(''What is the name of the file you want to see? ");
gets(filename);
if ((fp=fopen(filename, "r"))==NULL)
{ printf("\n\n*** That file does not exist ***\n");
exit(); // Exits program
}
inChar = getc(fp); // Reads first character
while (inChar != EOF)
{ putchar(inChar);
inChar = getc(fp);
}
fclose(fp);
return 0;
}
4. The following program reads one file and copies it to another. You might want to use such a program to back up important data in case the original file gets damaged.: -
/* Filename: anuj4.C Makes a copy of a file */
#include < stdio.h >
FILE *inFp;
FILE *outFp;
main()
{
char inFilename[12]; /* Holds original filename */
char outFilename[12]; /* Holds backup filename */
int inChar; /* Input character */
printf(''What is the name of the file you want
to back up? ");
gets(inFilename);
printf("What is the name of the file ");
printf("you want to copy %s to? ", inFilename);
gets(outFilename);
if ((inFp=fopen(inFilename, "r"))==NULL)
{ printf("\n\n*** %s does not exist ***\n", inFilename);
exit(); /* Exits program */
} if ((outFp=fopen(outFilename, "w"))==NULL)
{ printf("\n\n*** Error opening %s ***\n'', outFilename);
exit(); /* Exits program */
} printf("\nCopying . . . \n"); /* Waiting message */
while ((inChar = getc(inFp)) != EOF) /* Gets input character */
{ putc(inChar, outFp); } /* Writes the character to the backup file */
printf("\nThe files are copied.\n");
fclose(inFp);
fclose(outFp);
return 0;
}


Free Web Hosting