C programming with command-line arguments

This is a brief introduction suitable for this class. In real life, writing real software, any fiddling with arrays (and C programming in general) requires considerable care.

Command-line arguments

Suppose we want to create a C program that will accept arguments from the Unix or DOS command line. Consider for instance the unix command wc:


% wc myfile.txt
47 131 1373 myfile.txt

wc stands for "word count." It counts the number of lines, words, and characters in a file. Here, it accepted the argument "myfile.txt" from the command line. This is what we want: a program that can access the words typed by the user, on the command line.

Accessing the command line from a C program

To access command-line arguments, simply add two arguments to your C program's main() function. Try typing in the following code:

#include <stdio.h>

int main( int argc, char ** argv ) {

	int i;

	printf( "You typed in %d arguments\n\n", argc );

	for( i=0; i<argc; i++ ) {  /* For each argument */

		printf( "Argument %2d:  ", i );
		printf( "%s\n", argv[i] );
	}
	return 0;
}

If you put this in a file and compile it on bingsuns, for example, you'll see the following:

bingsun2% gcc -o foo.exe foo.c

bingsun2% foo.exe blah blah blah yak yak yak
You typed in 7 arguments

Argument  0:  foo.exe
Argument  1:  blah
Argument  2:  blah
Argument  3:  blah
Argument  4:  yak
Argument  5:  yak
Argument  6:  yak

So, the first parameter (int argc) is the number of words on the command line. The second parameter (char ** argv) is an array of the strings. These are conveniently divided into words for you. The first word, argv[0], is the name of the command.

Getting the data out

In your assignment, you want a command line option with a hyphen, e.g. "myshift -5" to shift 5 letters.
The string argv[1] will then be "-5", but the user could specify any number. To get it out, we can just use the C function
sscanf(). Also, we will punish the user for misusing the command:

#include <stdio.h>

int main( int argc, char ** argv ) {

	int i, shift;

        if( argc != 2 ) /* only one extra argument allowed */
        { 
	      printf( "BAD BAD BAD BAD USER.\n" );
	      printf( "BAD, AWFUL, NAUGHTY USER.\n" );
	      printf( "Usage:  %s -[shift].\n", argv[0] );
	} 
        else {
            if( argv[1][0] == '-' ) /* Look for a hyphen */
            {
                sscanf( argv[1]+1, "%d", &shift );
                printf( "You want a shift of %d\n", shift );
            }
            else
		printf( "%s is an invalid argument.\n", argv[1] );
	}
	return 0;
}

It's starting to look complicated, but this code snippet does pretty much all we need. In fact, you might want to copy it as the template for your program 0, if you are new to command line arguments.

Try compiling this code and feeding it various arguments.

What it does in more detail:

Here are the important bits of the program. First, checking that the right number of arguments has been entered:

        if( argc != 2 ) /* only one extra argument allowed */
        { 
	      printf( "BAD BAD BAD BAD USER.\n" );
	      printf( "BAD, AWFUL, NAUGHTY USER.\n" );
	      printf( "Usage:  %s -[shift].\n", argv[0] );
	} 

This code enforces the rule that only 2 arguments are allowed. "foo -3" is okay, and so is "foo BLAH". "foo" or "foo -3 -6 -9" will both trigger the rude warning.

            if( argv[1][0] == '-' ) /* Look for a hyphen */
            {
                sscanf( argv[1]+1, "%d", &shift );
                printf( "You want a shift of %d\n", shift );
            }

The first line makes sure the argument starts with a hyphen. The first character of argv[1] is argv[1][0].

Next, we sscanf() the value out of the string. This function is just like the C function scanf(), except you add an extra argument at the beginning. Note that extra +1 in there:

                sscanf( argv[1]+1, "%d", &shift );

I just add 1, because the first character is a hyphen. The string argv[1]+1 is an array starting with the next character.

That's it. If you have any questions, send me an email.