10 - Files and Command Line Arguments
10 - Files and Command Line Arguments
10 - Files and Command Line Arguments
12.1 Files
So far, we have seen taking input from the user through keyboard or outputting the results
to the screen. This works fine if the frequency of I/O (input-output) operations is low. As
the volume of data to be processed increases, the I/O operations become tedious. Moreover, if
you want to repeatedly execute a program, you need to enter the input, each time you execute
it. In such situations, it becomes necessary to store the data in a manner so that they can be
easily retrieved later. One of the simplest ways for programs to organize their data is to use
data files. A file is a collection of bytes stored on a permanent medium like a hard drive, flash
memory, or CD-ROM.
Files are of two types : data files and program files. Data files store data to be processed
by a program. Program files on the other hand contain instructions or code to be executed.
Data files are further classified as text files and binary files.
A text file (also called ASCII file) stores information as ASCII characters. A text file
contains human-readable characters. A user can read the contents of a text file or edit it using
a text editor. In text files, each line of text is terminated (delimited) with a special character
known as EOL (End of Line) character. Text documents like word documents are a good example
of text files.
A binary file is a file that contains information in the binary form. Thus, such files are not
human readable but provide a better security than text files. In binary file, there is no delimiter
for a line. Binary files are faster and easier for a program to read and write than the text files.
Image files are an example of binary files. The discussion here is restricted to that of text files.
1
12.1.1.1 Opening and closing files
Before you can read from or write to a file, you have to open it using the fopen() function.
The syntax of fopen() is:
fp=fopen(fileName,accessMode)
where fileName specifies the name of the file you want to open and accessMode specifies the
purpose of opening the file. For example, the following code opens a file named myfile.txt for
writing:
fp=fopen("myfile.txt",’w’)
The various access modes and their description are tabulated in Table 12.1.
While trying to open a file, the fopen() function returns a file pointer if successful. If an
error occurs, it returns a null pointer NULL.
Once you have performed the operations (read or write) on the file, you need to close it.
For this you use the fclose() function. The statement
fclose(fp);
closes a file whose associated file pointer is fp.
2
Writing characters to file
The putc() function writes characters to a file opened for writing. The syntax is
putc(ch,fp);
where fp is the pointer associated with the file to which the character ch is to be written. If a
putc() operation is successful, it returns the character written. Otherwise, it returns a special
value called EOF (End Of File).
Example 12.1. The program below writes a collection of characters one by one to a file.
#include<stdio.h>
main()
{
FILE *fp;
int count,i;char c;
fp=fopen("sample.txt","w");
if(fp==NULL)
printf("Sorry! Error in opening file\n");
else
{
printf("How many characters you want to enter?\n");
scanf("%d",&count);
for(i=0;i<count;i++)
{
printf("Enter a character\n");
scanf(" %c",&c);
putc(c,fp);
}
fclose(fp);
}
}
Example 12.2. This code reads all characters in a file one by one and prints them until the
end of the file is reached.
#include<stdio.h>
main()
{
FILE *fp;
int ch;
fp=fopen("sample.txt","r");
if(fp==NULL)
3
printf("Sorry! Error in opening file\n");
else
{
while ((ch = getc(fp))!= EOF)
{
putchar(ch);
//ch = getc(fp);
}
fclose(fp);
}
}
Using feof()
getc() returns EOF when it reaches the end of the file. When an error occurs during read
operation, then also getc() returns EOF. Thus, using only the return value of getc(), it is
impossible to know which occurred. To solve this problem, C includes the function feof(),
which determines when the end of the file has been encountered. feof() returns 1 if the end
of the file has been reached; otherwise, it returns zero. Therefore, to read the characters from
a file to its end, you can use the code:
while(feof(fp)!=0)
ch = getc(fp);
Example 12.3. This example illustrates the use of fputs() function to write a string to a file.
#include<stdio.h>
main()
{
FILE *fp;
int count,i;char str[15];
fp=fopen("sampleStrP.txt","w");
if(fp==NULL)
printf("Sorry! Error in opening file\n");
else
{
printf("Enter a string\n");
scanf(" %s",str);
fputs(str,fp);
fclose(fp);
}
4
}
■
Example 12.4. Here is how you read strings from a file using fgets().
#include<stdio.h>
main()
{
FILE *fp;
char str[50];
fp=fopen("sample.txt","r");
if(fp==NULL)
printf("Sorry! Error in opening file\n");
else
{
while ((fgets(str,50,fp))!=NULL)
printf("%s",str);
fclose(fp);
}
}
Example 12.5. The program below inputs numbers from the user and writes them to a file.
Later the numbers are printed by reading from the file.
#include<stdio.h>
main()
{
FILE *fp;
int num,count,i;
5
printf("How many numbers?");
scanf("%d",&count);
fp=fopen("file.txt","w");
if(fp==NULL)
printf("Sorry! Error in opening file\n");
else
{
for(i=0;i<count;i++)
{
printf("Enter any number:\n");
scanf("%d",&num);
putw(num,fp);
}
fclose(fp);
}
fp=fopen("file.txt","r");
if(fp==NULL)
printf("Sorry! Error in opening file\n");
else
{
num=getw(fp);
while(num!=EOF)
{
printf("%d ",num);
num=getw(fp);
}
fclose(fp);
}
}
• addr denotes the address of the data block (structure variable) whose contents are to be
written to file.
• count denotes the number of data blocks (number of structure variables) that you need
to write.
6
• fptr represents the file pointer associated with the file to which you are going to write
data.
Similarly fread() is used to read blocks of data from a file. The syntax of fread() is same as
that of fwrite():
fread(addr,size,count,fptr)
where
• addr denotes the address of the data block (structure variable) to which data from the
file will be written.
• count denotes the number of data blocks (number of structure variables) whose contents
you are reading.
• fptr represents the file pointer associated with the file from which you are reading data.
Example 12.6. This example inputs the details of a bank customer and writes to the file.
Later, the contents are being read from the file and printed out.
#include<stdio.h>
typedef struct
{
char name[15];
int accNo;
float balance;
}account;
main()
{
account acc;
FILE *fp;
fp=fopen("struct.txt","w");
if(fp==NULL)
printf("Sorry! Error in opening file\n");
else
{
printf("Enter customer name\n");
scanf(" %s",acc.name);
printf("Enter account number\n");
scanf("%d",&acc.accNo);
printf("Enter balance\n");
scanf("%f",&acc.balance);
fwrite (&acc, sizeof(account), 1, fp); /*count is 1 because you are
writing the contents of only 1 struct variable*/
fclose(fp);
}
fp=fopen("struct.txt","r");
if(fp==NULL)
printf("Sorry! Error in opening file\n");
else
7
{
fread(&acc, sizeof(account), 1, fp);
printf("Customer name: %s\n",acc.name);
printf("Account number: %d\n",acc.accNo);
printf("Balance: %f\n",acc.balance);
fclose(fp);
}
}
Formatted functions
If you need to handle multiple data items and that too of mixed types (char, int, float etc.),
you should use fprintf() and fscanf(). The fprintf() function is used to write mixed type
data items into a file. Its syntax is
fprintf(fp,format-string,var-list);
where fp is the file pointer, format-string is the list of format specifiers and var-list is the
list of variables whose values are to be written to file. Thus fprintf() function is similar to
printf() function except the first argument which is a file pointer.
The fscanf() function is used to read mixed type data from the file. The syntax is similar to
that of fprintf():
fscanf(fp,format-string,addr-list);
where fp and format-string have same meanings as with fprintf(); addr-list denotes the
lists of addresses of variables which will hold the values that are read from the file.
Example 12.7. The code below inputs the details of a student and writes them to a file. The
details are then printed by reading from the file.
#include<stdio.h>
main()
{
int m1,m2,roll,n,i;
char name[15];
FILE *fp;
fp=fopen("marks.txt","w");
if(fp==NULL)
printf("Sorry! Error in opening file\n");
else
{
printf("Number of students please\n");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("Enter the details of student %d\n",i+1);
scanf(" %s %d %d %d",name,&roll,&m1,&m2);
fprintf(fp,"%s %d %d %d",name,roll,m1,m2);
}
fclose(fp);
8
}
fp=fopen("marks.txt","r");
if(fp==NULL)
printf("Sorry! Error in opening file\n");
else
{
for(i=0;i<n;i++)
{
printf("Details of student %d\n",i+1);
fscanf(fp,"%s %d %d %d",name,&roll,&m1,&m2);
printf("Name: %s\n",name);
printf("Roll: %d\n",roll);
printf("Marks: %d and %d\n",m1,m2);
}
fclose(fp);
}
}
12.1.2.1 ftell()
This function tells the current position of the file pointer in the file. It takes a file pointer as
argument and returns the byte location of current position of the pointer. The statement
len = ftell(fp);
means that the file pointer is currently at byte numbered len. i.e., bytes 0 to len - 1 are to
the left of the current pointer position.
12.1.2.2 rewind()
The rewind() function resets the file pointer to the beginning of the file with the pointer
specified as its argument. That is, it “rewinds” the file. Its syntax is:
rewind(fp);
where fp is a file pointer. Thus, after executing the statements,
rewind(fp);
n=ftell(fp);
the value of n will be zero (indicating the beginning of file).
12.1.2.3 fseek()
fseek() is used to move the file pointer to a desired location in the file. Its syntax is:
fseek(fp,offset,position);
9
where
• fp is the file pointer.
• offset is the number of bytes fp is to be moved.
• position denotes the position from which the file pointer is moved.
position can take three values:
• 0 – beginning of file
• 1 – current position
• 2 – end of the file
position can also be specified in terms of constants rather than in terms of integers as follows:
• SEEK SET – beginning of file
• SEEK CUR – current position
• SEEK END – end of the file
offset can be positive or negative. If it is positive, the file pointer is moved in forward direction.
If it is negative, file pointer is moved backwards.
Example 12.8. This example shows some usages of fseek() function and their interpretations.
fseek(fp,0,0) − Moves fp zero bytes from the beginning of the file. In other
words, it moves the file pointer to start of the file.
fseek(fp,0,SEEK CUR) − Moves fp zero bytes from current position. In other words,
the pointer stays in its current position.
fseek(fp,0,SEEK END) − Moves fp to the file end.
fseek(fp,m,SEEK SET) − Moves fp m bytes from the beginning – sets the pointer at
(m + 1)th byte in the file.
fseek(fp,m,1) − Moves fp forward by m bytes from current position.
fseek(fp,-m,1) − Moves fp backward by m bytes from current position.
fseek(fp,-m,2) − Moves fp backward by m bytes from end of the file.
■
10
Example 12.9. Here is a simple example that uses a command line argument. It prints Hello
and your name on the screen, if you specify your name as a command line argument.
#include<stdio.h>
main(int argc,char *argv[])
{
printf("Hello %s",argv[1]);
}
If you run the above code as follows:
./a.out Narasimhan
the output will be
Hello Narasimhan
■
Example 12.10. This program receives command line arguments when the program is executed
and then displays the number of arguments entered and their values.
#include<stdio.h>
#include<stdlib.h>
main(int argc,char *argv[])
{
int i;
printf("argc is %d\n",argc);
for(i=0;i<argc;i++)
printf("argv[%d] is %s\n",i,argv[i]);
}
If you run the above code as:
./a.out CSE IT
the output is
argc is 3
argv[0] is ./a.out
argv[1] is CSE
argv[2] is IT
11
printf("Insufficient number of arguments\n");
else
{
printf("Name:%s\n",argv[1]);
printf("Roll:%s\n",argv[2]);
printf("Age:%s\n",argv[3]);
}
}
Recall every command line argument is a string. Thus roll number and age are interpreted as
string constants and hence %s is used while printing them.
Program 12.2. To add two numbers received as command line arguments.
#include<stdio.h>
#include<stdlib.h>
main(int argc,char *argv[])
{
int a,b;
a=atoi(argv[1]);
b=atoi(argv[2]);
printf("The sum is %d",a+b);
}
Since the numbers are received as command line arguments, they will be string constants. To
convert them to integers, the function atoi() is used. For this, the stdlib header file is
required.
Program 12.3. Input integers to a file “numbers.txt”. Read from this file and write the
even numbers to another file “even.txt” and odd numbers to a third file “odd.txt”. Finally
print the odd and even numbers separately by reading from corresponding files.
#include<stdio.h>
main()
{
FILE *fpn,*fpe,*fpo;
int num,count,i;
fpn=fopen("numbers.txt","w");
fpe=fopen("even.txt","w");
fpo=fopen("odd.txt","w");
if(fpn==NULL||fpe==NULL||fpo==NULL)
printf("Sorry!Error in opening file\n");
else
{
printf("How many integers you want to enter?\n");
scanf("%d",&count);
printf("Enter the integers\n");
for(i=0;i<count;i++)
{
scanf("%d",&num);
putw(num,fpn);
}
12
fclose(fpn);
fpn=fopen("numbers.txt","r");
num=getw(fpn);
while(num!=EOF)
{
if(num%2==0)
putw(num,fpe);
else
putw(num,fpo);
num=getw(fpn);
}
fclose(fpo);
fclose(fpe);
fpe=fopen("even.txt","r");
fpo=fopen("odd.txt","r");
printf("Contents of file with even numbers\n");
num=getw(fpe);
while(num!=EOF)
{
printf("%d ",num);
num=getw(fpe);
}
printf("\nContents of file with odd numbers\n");
num=getw(fpo);
while(num!=EOF)
{
printf("%d ",num);
num=getw(fpo);
}
fclose(fpo);
fclose(fpe);
fclose(fpn);
}
}
13