A Little C Primer/C Command Line Arguments

C allows a program to obtain the command line arguments provided when the executable is called, using two optional parameters of "main()" named "argc (argument count)" and "argv (argument vector)".

The "argc" variable gives the count of the number of command-line parameters provided to the program. This count includes the name of the program itself, so it will always have a value of at least one. The "argv" variable is a pointer to the first element of an array of strings, with each element containing one of the command-line arguments.

The following example program demonstrates:

   /* cmdline.c */

   #include <stdio.h>

   void main( int argc, char *argv[] )
   {
     int ctr;
     for( ctr=0; ctr < argc; ctr++ )
     {
       puts( argv[ctr] );
     }
   }

If this program is run from the command line as follows:

   stooges moe larry curley

—the output is:

   stooges
   moe
   larry
   curley

In practice, the command line will probably take a number of arguments, some of which will indicate options or switches, designated by a leading "-" or "/". Some of the switches may be specified separately or together, and some may accept an associated parameter. Other arguments will be text strings, giving numbers, file names, or other data.

The following example program demonstrates parsing the command-line arguments for an arbitrary program. It assumes that the legal option characters are "A", "B", "C", and "S", in either upper- or lower-case. The "S" option must be followed by some string representing a parameter.

   /* cparse.c */
   
   #include <stdio.h>
   #include <stdlib.h>
   #include <string.h>
   
   main( int argc, char *argv[] )
   {
     int m, n,                              /* Loop counters. */
         l,                                 /* String length. */
         x,                                 /* Exit code. */
         ch;                                /* Character buffer. */
     char s[256];                           /* String buffer. */
   
     for( n = 1; n < argc; n++ )            /* Scan through args. */
     {
       switch( (int)argv[n][0] )            /* Check for option character. */
       {
       case '-':
       case '/': x = 0;                   /* Bail out if 1. */
                 l = strlen( argv[n] );
                 for( m = 1; m < l; ++m ) /* Scan through options. */
                 {
                   ch = (int)argv[n][m];
                   switch( ch )
                   {
                   case 'a':              /* Legal options. */
                   case 'A':
                   case 'b':
                   case 'B':
                   case 'c':
                   case 'C':
                   case 'd':
                   case 'D': printf( "Option code = %c\n", ch );
                             break;
                   case 's':              /* String parameter. */
                   case 'S': if( m + 1 >= l )
                             {
                               puts( "Illegal syntax -- no string!" );
                               exit( 1 );
                             }
                             else
                             {
                               strcpy( s, &argv[n][m+1] );
                               printf( "String = %s\n", s );
                             }
                             x = 1;
                             break;
                   default:  printf( "Illegal option code = %c\n", ch );
                             x = 1;      /* Not legal option. */
                             exit( 1 );
                             break;
                   }
                   if( x == 1 )
                   {
                     break;
                   }
                 }
                 break;
       default:  printf( "Text = %s\n", argv[n] ); /* Not option -- text. */
                 break;
       }
     }
     puts( "DONE!" );
   }

For a more practical example, here's a simple program, based on an example from the previous chapter, that attempts to read the names of an input and output file from the command line. If no files are present, it uses standard input and standard output instead. If one file is present, it is assumed to be the input file and opens up standard output. This is a useful template for simple file-processing programs.

   /* cpfile.c */

   #include <stdio.h>
   #include <stdlib.h>
   #define MAX 256

   void main( unsigned int argc, unsigned char *argv[] )
   {
   
     FILE *src, *dst;
     char b[MAX];
   
     /* Try to open source and destination files. */
   
     switch (argc)
     {
     case 1:          /* No parameters, use stdin-stdout. */
       src = stdin;
       dst = stdout;
       break;

     case 2:          /* One parameter -- use input file & stdout. */
       if ( ( src = fopen( argv[1], "r" )) == NULL )
       {
          puts( "Can't open input file.\n" );
          exit( 0 );
       }
       dst = stdout;
       break;

     case 3:         /* Two parameters -- use input and output files. */
       if ( ( src = fopen( argv[1], "r" )) == NULL )
       {
          puts( "Can't open input file.\n" );
          exit( 0 );
       }
       if ( ( dst = fopen( argv[2], "w" )) == NULL )
       {
          puts( "Can't open output file.\n" );
          exit( 0 );
       }
       break;

     default:        /* Too many parameters. */
       puts( "Wrong parameters.\n" );
       exit( 0 );

     }
   
     /* Copy one file to the next. */
   
     while( ( fgets( b, MAX, src ) ) != NULL )
     {
        fputs( b, dst );
     }
   
     /* All done, close up shop. */
   
     fclose( src );
     fclose( dst );
   }