CSC 161 | Grinnell College | Fall, 2013 |
Imperative Problem Solving and Data Structures | ||
A common text-based interface asks a user to enter one or more commands. As a relatively simple case, each command might be a single letter followed by a number. This reading considers how to interpret these letter/number combinations — either individually or in a sequence.
The simplest type of command involves a single letter followed by a single digit, such as
char * comm1 = "r5"; char * comm2 = "h3";
In this context, each variable (comm1 and comm2) references a string — that is an array of characters. Each character in the array resides in an array element:
Typically, the initial letter provides information about a command or action and can be used directly. However, processing in the program likely needs a number: the int 5 rather than the character code for char '5'. If the program used a cast:
int value = (int) comm2[1];
the value would have the value of the character code for 5 rather than the integer value 5 itself. To resolve this difficulty, we examine the character codes for the digits '0', '1', ..., '9'. It turns out that the character codes start at the code for '0' and increase by one for each digit. That is, '1' is coded as 1 more than the code for '0', '2' is coded as 2 more than the code for '0', etc.
With this coding, we observe that we can obtain the int value of a character by subtracting '0' from the character code of a digit:
int 1 == '1' - '0' int 2 == '2' = '0' etc.
Using this approach, program command-deciphering-1.c decodes and prints the two commands identified above:
If a user is to enter several letter/digit commands, one way to store these commands might be in an array of strings:
char * commArray [4] = {"r5", "h3", "b7", "q4"};
In this sequence, commArray[0] is the first string, commArray[1] is the second string, etc. Accessing specific action or numeric value information involves first specifying the appropriate array element and then working with individual characters within that string. Program command-deciphering-2.c illustrates the same decoding process within this array of letter/digit commands:
In many command settings, users specify an action and a multi-digit integer or floating-point number, such as the following:
char * comm3 = "c100"; char * comm4 = "p3.141592";
In these cases extraction of the character for the action proceeds as before:
Determination of the corresponding number, however, is somewhat more challenging. One approach would be to proceed character by character through the digits and decimal points, working with comm3[1], comm3[2], comm3[3], .... While this approach could work, C provide two standard functions in the stdlib.h library that handle the conversion details:
For example,
With the availability of these standard C functions, the challenge of extracting a multi-digit number from a command reduces to removing the action character from the original command string to obtain a string of digits (perhaps with a decimal point). There are at least three workable approaches for deciphering a commandString:
We could create a new string array, copy the desired digits to a new string array, and then apply atoi or atof.
/* create temporary string */ char * temp = malloc (strlen(commandString)* sizeof(char)); /* copy characters, omitting the first */ int i; for (i = 1; i <= strlen(commandString); i++) temp[i-1] = command[i]; /* convert to a number */ int value = atoi (temp); /* with temp having served its purpose, its space can be deallocated */ free (temp);
We can take advantage of the definition of a string in C. A string is a sequence of characters, starting at a specified address and continuing until a null character is reached. In this case, we are given a commandString, in which the first character is commandString[0] and the number starts with character commandString[1]. That is, the address of the first number character in the command string is &CommandString[1]. With this observation, obtaining the multi-digit number in our command involves the string with initial address &CommandString[1]. Thus, we can apply atoi or atof to this string to obtain the desired number.
In a variation of the previous approach, the base address of the full command string is commandString. Hence the address of the string starting with the next character is CommandString+1.
Program command-deciphering-3.c illustrates each of these approaches for decoding a letter command following by a multi-character number.
As with letter/digit commands, we can consider processing a sequence of commands, each of which begins with a single letter, followed by a number of one or more digits. The following array illustrates such a sequence, in which the numbers are all digits:
char * anotherCommandArray[7] = {"I1", "V5", "X10", "L50", "C100", "D500", "M1000"};
As with the array of letter/digit commands, each array element contains one command, and we can access actions and numbers by working with individual characters within a command string. Such work is illustrated in program command-deciphering-4.c. The first part of the program converts all numbers to integers, while the second part converts all numbers to doubles.