Working with Arrays in C: Character Arrays

The purpose of Program 7.6 is to simply illustrate how a character array can be used. However, one point is worthy of discussion. Can you spot it?

Program 7.6   Introducing  Character Arrays

#include <stdio.h>

int main (void)

{

char word[] = { ‘H’, ‘e’, ‘l’, ‘l’, ‘o’, ‘!’ };

int  i;

for ( i = 0; i < 6; ++i )

printf (“%c”, word[i]);

printf (“\n”);

return 0;

}

Program 7.6   Output

Hello!

The most notable point in the preceding program is the declaration of the character array word. There is no mention of the number of elements in the array. The C language allows you to define an array without specifying the number of elements. If this is done, the size of the array is determined automatically based on the number of initialization elements. Because Program 7.6 has six initial values listed for the array word, the C lan- guage implicitly dimensions the array to six elements.

This approach works fine so long as you initialize every element in the array at the point that the array is defined. If this is not to be the case, you must explicitly dimension the array.

In the case of using index numbers in the initialization  list, as in

float sample_data[] = { [0] = 1.0, [49] = 100.0, [99] = 200.0 };

the largest index number specified sets the size of the array. In this case, sample_data is set to contain 100 elements, based on the largest index value of 99 that is specified.

1. Base Conversion  Using Arrays

The next program further illustrates the use of integer and character arrays. The task is to develop a program that converts a positive integer from its base 10 representation into its equivalent representation in another base up to base 16. As inputs to the program, you specify the number to be converted and also the base to which you want the number converted. The program then converts the keyed-in number to the appropriate base and displays the result.

The first step in developing such a program is to devise an algorithm to convert a number from base 10 to another base. An algorithm to generate the digits of the con- verted number can be informally stated as follows: A digit of the converted number is obtained by taking the modulo of the number by the base. The number is then divided by the base, with any fractional remainder discarded, and the process is repeated until the number reaches zero.

The outlined procedure generates the digits of the converted number starting from the rightmost digit. See how this works in the following example. Suppose you want to convert the number 10 into base 2. Table 7.1 shows the steps that would be followed to arrive at the result.

Table 7.1   Converting  an Integer from Base 10 to Base 2

The result of converting 10 to base 2 is, therefore, seen to be 1010, reading the digits of the “Number Modulo 2” column from the bottom to the top.

To write a program that performs the preceding conversion process, you must take a couple of things into account. First, the fact that the algorithm generates the digits of the converted number in reverse order is not very nice.You certainly can’t expect the user to read the result from right to left, or from the bottom of the page upward. Therefore, you must correct this problem. Rather than simply displaying each digit as it is generated,

you can have the program store each digit inside an array. Then, when you’ve finished converting the number, you can display the contents of the array in the correct order.

Second, you must realize that you specified for the program to handle conversion of numbers into bases up to 16. This means that any digits of the converted number that are between 10 and 15 must be displayed using the corresponding letters, A through F. This is where our character array enters the picture.

Examine Program 7.7 to see how these two issues are handled. This program also introduces the type qualifier const, which is used for variables whose value does not change in a program.

Program 7.7   Converting  a Positive  Integer to Another Base

// Program to convert a positive integer to another base

#include <stdio.h>

int main (void)

{

const char baseDigits[16] = {

‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’,

‘8’, ‘9’, ‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’ };

int    convertedNumber[64];

long int numberToConvert;

int    nextDigit, base, index = 0;

// get the number and the base

printf (“Number to be converted? “);

scanf (“%ld”, &numberToConvert);

printf (“Base? “);

scanf (“%i”, &base);

// convert to the indicated base

do {

convertedNumber[index] = numberToConvert % base;

++index;

numberToConvert = numberToConvert / base;

}

while ( numberToConvert != 0 );

// display the results in reverse order printf (“Converted number = “);

for (–index; index >= 0; –index ) {

nextDigit = convertedNumber[index];

printf (“%c”, baseDigits[nextDigit]);

}

printf (“\n”);

return 0;

}

Program 7.7   Output

Number to be converted? 10

Base? 2

Converted number = 1010

Program 7.7   Output (Rerun)

Number to be converted? 128362

Base? 16

Converted number = 1F56A

2. The const Qualifier

The compiler allows you to associate the const qualifier with variables whose values will not be changed by the program. That is, you can tell the compiler that the specified variables have a constant value throughout the program’s execution. If you try to assign a value to a const variable after initializing it, or try to increment or decrement it, the compiler might issue an error message, although it is not required to do so. One of the motivations for the const attribute in the language is that it allows the compiler to place your const variables into read-only memory. (Normally, the instructions of your pro- gram are also placed into read-only memory.)

As an example of the const attribute, the line

const double pi = 3.141592654;

declares the const variable pi. This tells the compiler that this variable will not be modi- fied by the program. If you subsequently wrote a line like this in your program:

pi = pi / 2;

the gcc compiler would give you a warning message similar to this:

foo.c:16: warning: assignment of read-only variable ‘pi’

Returning to Program 7.7, the character array baseDigits is set up to contain the 16 possible digits that will be displayed for the converted number. It is declared as a const array because its contents will not be changed after it is initialized. Note that this fact also aids in the program’s readability.

The array convertedNumber is defined to contain a maximum of 64 digits, which holds the results of converting the largest possible long integer to the smallest possible base (base 2) on just about all machines. The variable numberToConvert is defined to be of type long int so that relatively large numbers can be converted if desired. Finally, the variables base (to contain the desired conversion base) and index (to index into the convertedNumber array) are both defined to be of type int.

After the user keys in the values of the number to be converted and the base—note that the scanf call to read in a long integer value takes the format characters %ld—the program then enters a do loop to perform the conversion. The do was chosen so that at least one digit appears in the convertedNumber array even if the user keys in the num- ber zero to be converted.

Inside the loop, the numberToConvert modulo the base is computed to determine the next digit. This digit is stored inside the convertedNumber array, and the index in the array is incremented by 1. After dividing the numberToConvert by the base, the con- ditions of the do loop are checked. If the value of numberToConvert is 0, the loop ter- minates; otherwise, the loop is repeated to determine the next digit of the converted number.

When the do loop is complete, the value of the variable index is the number of digits in the converted number. Because this variable is incremented one time too many inside the do loop, its value is initially decremented by 1 in the for loop. The purpose of this for loop is to display the converted number at the terminal. The for loop sequences through the convertedNumber array in reverse sequence to display the digits in the cor- rect order.

Each digit from the convertedNumber array is in turn assigned to the variable nextDigit. For the numbers 10 through 15 to be correctly displayed using the letters A through F, a lookup is then made inside the array baseDigits, using the value of nextDigit as the index. For the digits 0 through 9, the corresponding location in the array baseDigits contains nothing more than the characters ‘0’ through ‘9’ (which as you recall are distinct from the integers 0 through 9). Locations 10 through 15 of the array contain the characters ‘A’ through ‘F’. So, if the value of nextDigit is 10, for example, the character contained in baseDigits[10], or ‘A’, is displayed. And if the value of nextDigit is 8, the character ‘8’ as contained in baseDigits[8] is displayed.

When the value of index becomes less than zero, the for loop is finished. At this point, the program displays a newline character, and program execution is terminated.

Incidentally, you might be interested in knowing that you could have easily avoided the intermediate step of assigning the value of convertedNumber[index] to nextDigit by directly specifying this expression  as the subscript of the baseDigits array in the printf call. In other words, the expression

baseDigits[ convertedNumber[index] ]

could have been supplied to the printf routine with the same results achieved. Of course, this expression is a bit more cryptic than the two equivalent expressions used by the program.

It should be pointed out that the preceding program is a bit sloppy. No check was ever made to ensure that the value of base was between 2 and 16. If the user had entered 0 for the value of the base, the division inside the do loop would have been a division by zero.You should never allow this to happen. In addition, if the user had keyed in 1 as the value of the base, the program would enter an infinite loop because the value of numberToConvert would never reach zero. If the user had entered a base value that was greater than 16, you might have exceeded the bounds of the baseDigits array later in the program. That’s another “gotcha” that you must avoid because the C system does not check this condition for us.

In Chapter 8, “Working with Functions,” you rewrite this program and resolve these issues. But now, it’s time to look at an interesting extension to the notion of an array.

Source: Kochan Stephen G. (2004), Programming in C: A Complete Introduction to the C Programming Language, Sams; Subsequent edition.

Leave a Reply

Your email address will not be published. Required fields are marked *