Menu

Class 7: catch up examples


A simple program that pulls a lot of stuff together
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;
}
A twist ... requiring more string manipulation
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;
}