To execute the file-copy programs that we saw in Chapter 12 we are required to first type the program, compile it, and then execute it. This program can be improved in two ways:
(a) There should be no need to compile the program every time to use the file-copy utility. It means the program must be executable at command prompt (A> or C> if you are using MS-DOS, Start | Run dialog if you are using Windows and $ prompt if you are using Unix).
(a) There should be no need to compile the program every time to use the file-copy utility. It means the program must be executable at command prompt (A> or C> if you are using MS-DOS, Start | Run dialog if you are using Windows and $ prompt if you are using Unix).
(b)Instead of the program prompting us to enter the source and target filenames, we must be able to supply them at command prompt, in the form:
filecopy PR1.C PR2.C
where, PR1.C is the source filename and PR2.C is the target filename.
The first improvement is simple. In MS-DOS, the executable file (the one which can be executed at command prompt and has an extension .EXE) can be created in Turbo C/C++ by using the key F9 to compile the program. In VC++ compiler under Windows same can be done by using F7 to compile the program. Under Unix this is not required since in Unix every time we compile a program we always get an executable file.
The second improvement is possible by passing the source filename and target filename to the function main( ). This is illustrated below:
#include "stdio.h"
main ( int argc, char *argv[ ] )
{
FILE *fs, *ft ;
char ch ;
if ( argc != 3 )
{
puts ( "Improper number of arguments" ) ;
exit( ) ;
}
fs = fopen ( argv[1], "r" ) ;
if ( fs == NULL )
{
puts ( "Cannot open source file" ) ;
exit( ) ;
}
ft = fopen ( argv[2], "w" ) ;
if ( ft == NULL )
{
puts ( "Cannot open target file" ) ;
fclose ( fs ) ;
exit( ) ;
}
while ( 1 )
{
ch = fgetc ( fs ) ;
if ( ch == EOF )
break ;
else
fputc ( ch, ft ) ;
}
main ( int argc, char *argv[ ] )
{
FILE *fs, *ft ;
char ch ;
if ( argc != 3 )
{
puts ( "Improper number of arguments" ) ;
exit( ) ;
}
fs = fopen ( argv[1], "r" ) ;
if ( fs == NULL )
{
puts ( "Cannot open source file" ) ;
exit( ) ;
}
ft = fopen ( argv[2], "w" ) ;
if ( ft == NULL )
{
puts ( "Cannot open target file" ) ;
fclose ( fs ) ;
exit( ) ;
}
while ( 1 )
{
ch = fgetc ( fs ) ;
if ( ch == EOF )
break ;
else
fputc ( ch, ft ) ;
}
fclose ( fs ) ;
fclose ( ft ) ;
}
fclose ( ft ) ;
}
The arguments that we pass on to main( ) at the command prompt are called command line arguments. The function main( ) can have two arguments, traditionally named as argc and argv. Out of these, argv is an array of pointers to strings and argc is an int whose value is equal to the number of strings to which argv points. When the program is executed, the strings on the command line are passed to main( ). More precisely, the strings at the command line are stored in memory and address of the first string is stored in argv[0], address of the second string is stored in argv[1] and so on. The argument argc is set to the number of strings given on the command line. For example, in our sample program, if at the command prompt we give,
filecopy PR1.C PR2.C
then,
argc would contain 3
argv[0] would contain base address of the string “filecopy”
argv[1] would contain base address of the string “PR1.C”
argv[2] would contain base address of the string “PR2.C”
Whenever we pass arguments to main( ), it is a good habit to check whether the correct number of arguments have been passed on to main( ) or not. In our program this has been done through,
if ( argc != 3 )
{
printf ( "Improper number of arguments" ) ;
exit( ) ;
}
Rest of the program is same as the earlier file-copy program. This program is better than the earlier file-copy program on two counts:
(a) There is no need to recompile the program every time we want to use this utility. It can be executed at command prompt.
(a) There is no need to recompile the program every time we want to use this utility. It can be executed at command prompt.
(b) We are able to pass source file name and target file name to main( ), and utilize them in main( ).
One final comment... the while loop that we have used in our program can be written in a more compact form, as shown below:
while ( ( ch = fgetc ( fs ) ) != EOF )
fputc ( ch, ft ) ;
This avoids the usage of an indefinite loop and a break statement to come out of this loop. Here, first fgetc ( fs ) gets the character from the file, assigns it to the variable ch, and then ch is compared against EOF. Remember that it is necessary to put the expression
ch = fgetc ( fs )
within a pair of parentheses, so that first the character read is assigned to variable ch and then it is compared with EOF.
There is one more way of writing the while loop. It is shown below:
while ( !feof ( fs ) )
{
ch = fgetc ( fs ) ;
fputc ( ch, ft ) ;
}
Here, feof( ) is a macro which returns a 0 if end of file is not reached. Hence we use the ! operator to negate this 0 to the truth value. When the end of file is reached feof( ) returns a non-zero
value, ! makes it 0 and since now the condition evaluates to false the while loop gets terminated.
Note that in each one of them the following three methods for opening a file are same, since in each one of them, essentially a base address of the string (pointer to a string) is being passed to fopen( ).
fs = fopen ( "PR1.C" , "r" ) ;
fs = fopen ( filename, "r" ) ;
fs = fopen ( argv[1] , "r" ) ;
Note that in each one of them the following three methods for opening a file are same, since in each one of them, essentially a base address of the string (pointer to a string) is being passed to fopen( ).
fs = fopen ( "PR1.C" , "r" ) ;
fs = fopen ( filename, "r" ) ;
fs = fopen ( argv[1] , "r" ) ;
No comments:
Post a Comment