BIT104 SLM Library - SLM - Unit 14
BIT104 SLM Library - SLM - Unit 14
Structure:
14.1 Introduction
Objectives
14.2 Defining and Opening a File
14.3 Closing Files
14.4 Input/output Operations on Files
Read or Write One Character at a Time
Read or Write One Line of Text at a Time
Formatted I/O
Predefined Streams
14.5 Error Handling during I/O Operations
14.6 Random Access to Files
14.7 Command Line Arguments
14.8 Summary
14.9 Terminal Questions
14.10 Answers
14.11 Exercises
14.1 Introduction
In the previous unit, we discussed the dynamic memory allocation in C.
Dynamic memory allocation is the process of allocating memory at run time.
We learned four memory management functions that can be used for
allocating and freeing memory during program execution. We also
discussed important data structure called linked list. A linked list is a chain
of nodes. Each node consists of data items and a pointer that points to the
next node in the list. The last item has a null pointer to signify the end of the
list.
In C, a file refers to a disk file, a terminal, a printer, or a tape drive. In other
words, a file represents a concrete device with which we want to exchange
information. Before we perform any communication to a file, we have to
open the file. We also need to close the opened file after we finish
exchanging information with it.
Objectives:
After studying this unit, you should be able to:
open file and control input and output
connect to file and able to read from the file and write to the file using file
pointers.
check for error during I/O operations on files.
implement the Random Access functions to allow control over the
implied read/write position in the file.
supply a parameter to a program when the program is invoked using a
command line arguments.
Opening a File: The C I/O function fopen() opens a file and associates a
stream with the opened file. We need to specify the method of opening the
file and the filename as arguments to the fopen() function. The syntax for
the fopen() function is
#include <stdio.h>
FILE *fopen(const char *filename, const char *mode);
Here filename is a char pointer that references a string containing a
filename. The filename is given to the file that is about to be opened by the
fopen() function. On the other hand, mode points to another string that
specifies the manner in which to open the file. The fopen() function returns a
pointer of type FILE. If an error occurs during the procedure of opening a file,
the fopen() function returns a null pointer.
The mode parameter is made by a combination of the characters r (read), w
(write), b(binary), a (append), and + (update). When we use append mode,
and the file already exists, the contents of the file will be preserved and new
data that we write will be added to the end. If the file does not already exist,
it will be created. This is in contrast to w, which always attempts to create a
new file, and will discard whatever data may already be in the file. Using the
+ character sets the mode to both reading and writing. When we use r, the
file must already exist; if it does not, the call will fail.
The following list shows the possible ways to open a file by various strings
of modes:
• “r” opens an existing text file for reading.
• “w” creates a text file for writing.
• “a” opens an existing text file for appending.
• “r+” opens an existing text file for reading or writing.
• “w+” creates a text file for reading or writing.
• “a+” opens or create a text file for appending.
• “rb” opens an existing binary file for reading.
• “wb” creates a binary file for writing.
• “ab” opens an existing binary file for appending.
• “r+b” opens an existing binary file for reading or writing.
• “w+b” creates a binary file for reading or writing.
• “a+b” opens or creates a binary file for appending.
Note that we might see code where the mode is given as “rb+” instead of
“r+b”. These two strings are equivalent. Similarly, “wb+” is the same as
“w+b”; “ab+” is equivalent to “a+b”.
The following statements try to open a file called test.txt:
FILE *fptr;
if ((fptr = fopen(“test.txt”, “r”)) == NULL){
printf(“Cannot open test.txt file.\n”);
exit(1);
}
Here “r” is used to indicate that a text file is about to be opened for reading
only. If an error occurs when the fopen() function tries to open the file, the
function returns a null pointer. However this happens if test.txt does not
already exist. Then an error message is printed out by the printf() function
and the program is aborted by calling the exit() function with a nonzero
value.
To open the file output.dat for writing we might call fopen() using mode "w"
which indicates writing:
ofptr = fopen("output.dat", "w");
It is common to collapse the call to fopen and the assignment in with the
test:
line[nch] = '\0';
return nch;
}
Now we could read one line from ifp by calling
char line[MAXLINE];
...
fgetline(ifp, line, MAXLINE);
#include <stdio.h>
main(void)
{
FILE *fp;
char filename[]= “Test.txt”;
if ((fp = fopen(filename, “r”)) == NULL){
printf(“Cannot open %s.\n”, filename);
exit(1);
}
else
{
while (1)
{
ch = fgetc (fp) ;
if ( ch == EOF )
break ;
printf ( "%c", ch ) ;
}
fclose(fp);
}
return 0;
}
If an error occurs when we try to open the text file, the fopen() function
returns a null pointer, and prints a warning message, and exit the program.
Otherwise, reads the content of file one character at time and display it on
screen.
what the gets() function does. The gets() function just replaces the newline
character with a null character.
The syntax for the fputs() function is
#include <stdio.h>
int fputs(const char *s, FILE *stream);
Here argument s points to the array that contains the characters to be
written to a file associated with the file pointer stream. The const modifier
indicates that the content of the array pointed to by s cannot be changed by
the fputs() function. If it fails, the fputs() function returns a nonzero value;
otherwise, it returns zero. Note that the character array must include a null
character at the end of the string as the terminator to the fputs() function.
Also, unlike the puts() function, the fputs() function does not insert a newline
character to the string written to the file.
14.4.3 Formatted I/O
We have dealt with reading and writing only characters and strings. What if
we want to read or write numbers from/to file? Further the question that
arises is what if we desire to read/write a combination of characters, strings
and numbers? As we have discussed, the two C library functions scanf()
and printf() can be used to read or write formatted data through the
standard I/O (that is, stdin and stdout). Among the C disk file I/O functions,
there are two equivalent functions, fscanf() and fprintf(), that can do the
same jobs as the scanf() and printf() functions. In addition, the fscanf() and
fprintf() functions allow the programmer to specify I/O streams other than
stdin and stdout.
The syntax for the fscanf() function is
#include <stdio.h>
int fscanf(FILE *stream, const char *format, …);
Here stream is the file pointer associated with an opened file. Here
argument format (whose usage is the same as in the scanf() function) is a
char pointer pointing to a string that contains the format specifiers. If
successful, the fscanf() function returns the number of data items read.
Otherwise, the function returns EOF.
The syntax for the fprintf() function is
#include <stdio.h>
int fprintf(FILE *stream, const char *format, ...);
Sikkim Manipal University B2074 Page No.: 307
Principles of C Programming Unit 14
Here stream is the file pointer associated with an opened file format, whose
usage is the same as in the printf() .function, is a char pointer pointing to a
string that contains the format specifiers. If successful, the fprintf() function
returns the number of formatted expressions. Otherwise, the function
returns a negative value.
Program 14.2: Writing a data to the file using fprintf() function.
#include <stdio.h>
main( )
{
FILE *fp;
char stuff[25];
int index;
fp = fopen("TENLINES.TXT","w"); /* open for writing */
strcpy(stuff,"This is an example line.");
for (index = 1; index <= 10; index++)
fprintf(fp,"%s Line number %d\n", stuff, index);
fclose(fp); /* close the file before ending program */
}
14.4.4 Predefined Streams
Besides the file pointers which we explicitly open by calling fopen, there are
also three predefined streams. In nearly all the previous units, we have
been calling printf to print formatted output to the “standard output''. We
have also been calling getchar to read single characters from the “standard
input,'' and putchar to write single characters to the standard output.
“Standard input'' and “standard output'' are two predefined I/O streams
which are implicitly available to us.
stdin is a constant file pointer corresponding to standard input, and stdout is
a constant file pointer corresponding to standard output. Both of these can
be used anywhere a file pointer is called for; for example, getchar() is the
same as getc(stdin) and putchar(c) is the same as putc(c, stdout). The third
predefined stream is stderr. Like stdout, stderr is typically connected to the
screen by default. The difference is that stderr is not redirected when the
standard output is redirected. For example, under Unix or MS-DOS, when
we invoke
program > filename
clearerr clears the error and EOF indicators for the stream.
feof returns non-zero if the stream's EOF indicator is set, zero otherwise.
ferror returns non-zero if the stream's error indicator is set, zero otherwise.
perror prints a single-line error message on the program's standard output,
prefixed by the string pointed to by s, with a colon and a space appended.
The error message is determined by the value of errno and is intended to
give some explanation of the condition causing the error. For example, this
program produces the error message shown:
#include <stdio.h>
#include <stdlib.h>
main(){
fclose(stdout);
if(fgetc(stdout) >= 0){
fprintf(stderr, "What - no error!\n");
exit(EXIT_FAILURE);
}
perror("fgetc");
exit(EXIT_SUCCESS);
}
/* Result */
fgetc: Bad file number
desired position in a file before data can be read from or written to it. The
Random Access functions allow control over the implied read/write position
in the file. The file position indicator is moved without the need for a read or
a write, and indicates the byte to be the subject of the next operation on the
file.
In C, three types of function exist which allow the file position indicator to be
examined or changed. Their declarations and descriptions follow.
#include <stdio.h>
ftell returns the current value (measured in characters) of the file position
indicator if stream refers to a binary file. For a text file, a ‘magic’ number is
returned, which may only be used on a subsequent call to fseek to
reposition to the current file position indicator. On failure, -1L is returned and
errno is set.
rewind sets the current file position indicator to the start of the file indicated
by stream. The file's error indicator is reset by a call of rewind. No value is
returned.
fseek allows the file position indicator for stream to be set to an arbitrary
value (for binary files), or for text files, only to a position obtained from ftell,
as follows:
In the general case, the file position indicator is set to offset bytes
(characters) from a point in the file determined by the value of ptrname.
Offset may be negative. The values of ptrname may be SEEK_SET,
which sets the file position indicator relative to the beginning of the file,
SEEK_CUR, which sets the file position indicator relative to its current
value, and SEEK_END, which sets the file position indicator relative to
the end of the file. The latter is not necessarily guaranteed to work
properly on binary streams.
For text files, offset must either be zero or a value returned from a
previous call to ftell for the same stream, and the value of ptrname must
be SEEK_SET.
fseek clears the end of file indicator for the given stream and erases the
memory of any ungetc. It works for both input and output.
Zero is returned for success, non-zero for a forbidden request.
Note that for ftell and fseek it must be possible to encode the value of the
file position indicator into a long. This may not work for very long files, so the
Standard introduces fgetpos and fsetpos which have been specified in a
way that it removes the problem.
fgetpos stores the current file position indicator for stream in the object
pointed to by pos. The value stored is ‘magic’ and only used to return to the
specified position for the same stream using fsetpos.
fsetpos works as described above, also clearing the stream's end-of-file
indicator and forgetting the effects of any ungetc operations.
For both functions, on success, zero is returned; on failure, non-zero is
returned and errno is set.
Self Assessment Questions
10. ____________ function returns the current value (measured in
characters) of the file position indicator if stream refers to a binary file.
11. fseek allows the file position indicator for stream to be set to an
arbitrary value. (True/False)
12. __________ stores the current file position indicator for stream in the
object pointed to by pos.
printf("Access Permitted");
else
{
printf("Access denied");
exit(1);
}
program code here ......
}
This program only allows access to its code if the correct password is
entered as a command-line argument. There are many uses for command-
line arguments and they can be a powerful tool.
As another example, here is a program which searches character from the
input file and if the character is available in the file, displays the message
found and comes out from the loop.
Program 14.5: Program to search the specified file, looking for the
character
/*Search specified file for specified character. */
#include <stdio.h>
#include <stdlib.h>
void main(int argc, char *argv[])
{
FILE *fp; /* file pointer */
char ch;
14.8 Summary
Let us recapitulate important points discussed in this unit:
In C, a file can refer to a disk file, a terminal, a printer, or a tape drive.
A stream is a series of ordered bytes. Unlike a file, a stream is device
independent. There are two stream formats: text stream and binary
stream.
The file position indicator in the FILE structure points to the position in a
file where data will next be read from or written to.
The fopen() function is used to open a file and associate a stream to the
opened file. We can specify different modes for opening a file.
The fclose() function is responsible for closing an opened file and
disassociating a stream with the file.
The fgetc() and fputc() functions read or write one character at a time.
The fgets() and fputs() functions read or write one line at a time.
The fprintf() and fscanf() functions for formatted I/O file operation.
The feof() function can determine when the end of a file has been
reached.
“Standard input'' and “standard output'' are two predefined I/O streams
which are implicitly available to us.
Sikkim Manipal University B2074 Page No.: 316
Principles of C Programming Unit 14
The Random Access functions allow control over the implied read/write
position in the file.
The command line argument is a parameter supplied to a program when
the program is invoked.
14.10 Answers
Self Assessment Questions
1. stdio.h
2. null pointer
3. File pointer
4. True
5. false
6. stdin
7. True
8. clearerr
9. ferror
10. ftell
11. true
12. fgetpos
13. true
14. char
15. Command line argument
14.11 Exercises
1. Distinguish between the following functions:
a) getc and getchar
b) printf and fprintf
c) feof and ferror
2. Write a program to copy the contents of one file to another.
3. Two data files DATA1 and DATA2 contains sorted list of integers. Write
a program to produce a third file DATA which holds the single sorted,
merged list of these two lists. Use command line arguments to specify
the file names.
4. The skeletal outline of an C program is shown below.
#include <stdio.h>
main()
{
FILE *pt1, *pt2;
int a;
float b;
char c;
pt1 = fopen(“sample.old”, “r”);
pt2= fopen (“sample.new”,”w”);
……..
fclose(pt1);
fclose(pt2);
}
Identify and Write file function required to perform following:
a) Read the values of a, b and c from the data file sample.old.
b) Display each value on the screen and enter an updated value.
c) Write the new values to the data file sample.new. Format the floating-
point value so that not more than two decimals are written to
sample.new.
__________________