Dr. Brown's 3rd period class spent the catch up period
building a program called "go", that takes a filename as a
command-line argument and produces a new file, whose name is
the input file name with a .mod stuck on the end,
that is the original file with all the lower-case letters
changed to capitals. It handles missing and invalid filenames
properly too!
/**********************************************
* go: a captital program!
*
* "go foo" produces a file foo.mod that is
* identical to foo, except that all letters
* are capitals.
**********************************************/
#include <stdio.h>
#include <ctype.h>
int main(int argc, char **argv)
{
/** Check number of arguments ***************/
if (argc < 2)
{
fprintf(stderr,"usage: go <file>\n");
exit(1);
}
/** Open specified input file ***************/
FILE* fin = fopen(argv[1],"r");
if (fin == 0)
{
fprintf(stderr,"Error in go: File \"%s\" not found!\n",argv[1]);
exit(2);
}
/** Create output file name string **********/
char *ofname = (char*)malloc((strlen(argv[1]) + 5)*sizeof(char));
strcpy(ofname,argv[1]);
strcat(ofname,".mod");
/** Create & open output file ***************/
FILE* fout = fopen(ofname,"w");
if (fout == 0)
{
fprintf(stderr,"Error in go: File \"%s\" could not be created!\n",ofname);
exit(3);
}
/** Read and write capitalized **************/
char c;
while(fscanf(fin,"%c",&c) == 1)
{
fprintf(fout,"%c",toupper(c));
}
return 0;
}
Consider this run of the original "go" program:
BASH$ ./go /etc/passwd
Error in go: File "/etc/passwd.mod" could not be created!
What happened? Well, we tried to create a new file
in /etc, which we do not have permission to do!
So this is correct behavior. Let's modify the program,
though, to change what it is supposed to do. Let's change it
so that the output file is always created in the current
directory, and its name is the input file name (stripped from
the path) with .mod at the end. That way the
above example will work, creating a
file passwd.mod in the current directory.
#include <stdio.h>
#include <ctype.h>
#include <strings.h>
int main(int argc, char** argv)
{
/* check for commandline arguments */
if (argc < 2)
{
fprintf(stderr,"usage: go <file>\n");
exit(1);
}
/* Open input file. */
FILE* fin = fopen(argv[1],"r");
if (fin == 0)
{
fprintf(stderr,"Error in go: File \"%s\" could not be opened!\n",argv[1]);
exit(2);
}
/* Set p to point to char after the last / in argv[1] */
char *p = argv[1];
int i;
for(i = 0; argv[1][i] != '\0'; ++i)
{
if (argv[1][i] == '/')
p = &(argv[1][i+1]);
}
/* Create output file name */
int h = strlen(p);
char *ofname = (char*)malloc((h + 5)*sizeof(char));
strcpy(ofname,p);
strcat(ofname,".mod");
/* Open output file. */
FILE* fout = fopen(ofname,"w");
if (fout == 0)
{
fprintf(stderr,"Error in go: File \"%s\" could not be created!\n",ofname);
exit(3);
}
/* Capitalize! */
char c;
while(fscanf(fin,"%c",&c) == 1)
{
fprintf(fout,"%c",toupper(c));
}
return 0;
}