Command-Line Arguments
Introduction
Command-line arguments are a great way to give a program input right
as the program begins executing. The convention to do this is to give
your main function two arguments, argc
and argv. argc is an integer related to the
number of arguments passed in to the program, and argv
is an array of strings related to those arguments, and thus is
declared as char* argv[].
Textbook Reading
The necessary background details on processing command-line arguments in C first comes from the textbook. Read
- King: Section 13.7, pp. 300-304
String Processing
Because arguments are given as strings, we introduce or review several important string-processing mechanisms in C.
- Characters and Substrings
- Conversion to numbers
- Command-string processing
All examples that follow may be found in the C-program,
string-processing.c
Characters and Substrings
Extraction of a character
In C, a string is an array of characters, and each character can be accessed directly through in index within the array.
char myArray[17] = "computer science";
int length = strlen (myArray);
for (int i = 0; i < length; i++)
printf ("\tmyArray[%d] = %c\n", i, myArray[i]);
Extraction of a substring
Given a string, a common task is to extract a substring from a string. For example, in Scheme, one might use the substring function:
(substring str start end)
According to the
Scheme
R5 documentation, Substring
returns a newly allocated
string formed from the characters of string beginning with
index start (inclusive) and ending with index end
(exclusive).
In C, there is not a function with the name substring,
but the function strncpy accomplishes the same result;
one copies end - start characters from str,
starting with the offset start. If the extracted string
does not go to the end of str, then one must remember to
add a null character at the end of the extracted string.
The function header of strncpy reads:
char * strncpy(char * dest, const char * src, int n);
In addition to copying the specified number of characters from src
to dest, the function returns a pointer
to dest.
Several examples follow. Note that string functions are often written to recover gracefully from possible errors, such as in the line
strncpy (subArray, myArray+3, strlen(myArray));
in which strncpy will pad subArray with three extra '\0' characters rather than let the extra 3 spaces be filled with undefined characters.
/* extracting substrings from a string */
/* the example uses myArray from above as the starting point */
printf ("extracting substrings from a string\n");
char subArray[20]; /* for a string copy, remember to have allocated space! */
strncpy (subArray, myArray, 8);
subArray[8] = 0; /* null terminate the array */
printf ("\t extract the first 8 characters (plus the null): %s\n", subArray);
/* extra bytes past end of myArray pads subArray with nulls*/
strncpy (subArray, myArray+3, strlen(myArray));
printf ("\t extract all characters after the first 3: %s\n", subArray);
int start = strlen(myArray) - 8;
strncpy (subArray, myArray+start, 8);
subArray[strlen(myArray)-8] = 0; /* null terminate array */
printf ("\t extract the last 8 characters (plus the null): %s\n", subArray);
Breaking a string into pieces
Some applications require a string to be separated into pieces. For example, consider the string
"January,February,March,April,May,June,July,August,September,October,November,December"
We might want to break it into a sequence of substrings, separated by a given separator or delimiter. This task is accomplished by the following function, which breaks a string into pieces called "tokens" (hence the abbreviation strtok):
char * strtok(char * strptr, const char * delimiter);
Using strtok is done in two stages. The first call to strtok returns the first string before
the given delimiter. For subsequent calls, a null string is used for
the strptr parameter, and these calls return the next
elements in the sequence. When no more elements are
present, strtok returns NULL.
Warnings:
-
Calls to
strtokcan change the first parameter. -
Because
strtokchanges the parameter, standard practice is to copy the original string first and use the copy when callingstrtok -
The function
strsepis now preferred overstrtok, although the new function may not be included in all compilers.
The following example places the months given above into an array of 12 string pointers:
char year[] = "January,February,March,April,May,June,July,"
"August,September,October,November,December" ;
/* copy original array */
char* yearCopy = malloc (sizeof(char)*(strlen(year) + 1));
strcpy (yearCopy, year);
/* array to receive the string pieces, including space for NULL strtok at end */
char* months[13];
/* loop puts strings into successive elements of months array */
months[0] = strtok(yearCopy, ",");
i = 1;
while ((months[i] = strtok(NULL, ","))) /* continue as long as token != NULL */
i++;
printf ("result of using strtok to break up a string of months\n");
for (i = 0; i < 12; i++)
printf ("\t month %d: %s\n", i, months[i]);
printf ("original year array: %s\n", year);
Conversion to numbers
Input from a command line (and input from scanf
using %s format) is a string. It can be a challenge to convert a string of digits to a number; so the stdlib.h
library contains several functions to convert strings to numbers:
-
convert a character string to an
intint atoi (const char * strptr); /* converts a string to an int */ -
convert a character string to a
doubledouble atof (const char * strptr); /* converts a string to a double */
| Function call | Result | Comments | |
|---|---|---|---|
atoi("1234") |
1234 | int type returned
| |
atoi("3.14") |
3 |
int type returned; digits after the decimal point
ignored
|
|
atof("1234") |
1234.0 | double type returned |
|
atof("3.14") |
3.14 | double type returned |
Note that more recent (C99) library functions strtol
and strtod feature more robust error checking and are to be
preferred over atoi and atof.