09 Beginner's Lesson 4: Arrays, Qualifiers, and Reading Numbers

Greetings!

In Lesson 3 we learned how to declare a variable and assign a value
to it. We also learned about forming expressions with arithmetic
operators. In this lesson we'll learn about arrays, strings, reading
strings, multiple dimension arrays, reading numbers, initializing
variables, types of integer and floats, hexadecimal and octal constants,
and operators for performing shortcuts. Since this is a long lesson,
I'm going to split it up into two parts (A & B). This is part A. We'll
be able to input data into our programs once we've learned this stuff!
Exciting times...

A variable holds one value. An ARRAY is a set of consecutive memory
locations that are all the same type. Each item in an array is called
an ELEMENT. The number of elements in the array is called the DIMENSION
of the array. The first element of an array is numbered zero. Here is
how to declare an array:

array_type array_name[ number_of_array_elements ];

Therefore, float data[5]; declares "data" to be an array of five
elements, numbered 0 to 4. To use this array we use one of those
numbers, called an INDEX. You can reference data[0] (the first
element), data[1] (the second element), and so forth, up to data[4]
(the fifth element). data[5] is illegal because the index `5' is
the sixth element, and we only declared the array to have five elements.

Here is a sample program to illustrate the above concepts:

/* exmpl4-1.c -- computes the total and average of five numbers */
/* -- program shows use of a single dimension array */
#include <stdio.h>
int main(void)
{
float data[5]; /* array holds data to average and total */
float total; /* the total of the data items */
float average; /* average of the items */

data[0] = 34.0;
data[1] = 27.0;
data[2] = 45.0;
data[3] = 82.0;
data[4] = 22.0;

total = data[0] + data[1] + data[2] + data[3] + data[4];
average = total /5.0;
printf("Total %f Average %f\n", total, average);

return 0;
}

Strings are arrays of characters. The special character `\0' (NUL)
indicates the end of a string. We need to remember to allocate
enough room in our string arrays for the NUL character.

int main(void)
{
char name[4];

name[0] = 'K';
name[1] = 'a';
name[2] = 't';
name[3] = '\0';

return 0;
}

Note that one element of the array was allocated for NUL.

String constants are enclosed in double quotes (" "). C does not
allow one array to be assigned to another, we can't do this kind
of assignment:

name = "Kat"; /* NOT correct! */

We can use the standard library function strcpy() to copy the
string into the variable:

#include <string.h>
int main(void)
{
char name[4];
strcpy(name, "Kat"); /* correct */
return 0;
}

We can also make variable-length strings:

#include <string.h>
int main(void)
{
char string[50];
strcpy(string, "Kat");
return 0;
}

Note that the size of the array is 50 characters (we can store
49 characters plus a NUL), but the length of the string is 3.
Remember that NUL indicates the end of the string.

Note that string and character constants are very different:
"X" is a one character string. 'Z' is a single character.

Here are some string functions.
Make sure to #include <string.h> when using any of these:

Function Description
-------------------+--------------------------------------
strcpy(s1, s2) | Copy s1 into s2.
strcat(s1, s2) | Concatenate s1 onto end of s2.
length = strlen(s) | Get the length of string "s".
strcmp(s1, s2) | 0 if s1 equals s2, otherwise nonzero.
-------------------+--------------------------------------

The printf() function uses the character conversion symbol %s
to print strings. Study this example:

#include <string.h>
#include <stdio.h>
int main(void)
{
char name[20];
strcpy(name, "Kat"); /* initialize name */
printf("The name is %s\n", name);
return 0;
}

Now lets look at a program that will use strcat() to combine
two strings together:

#include <string.h>
#include <stdio.h>
int main(void)
{
char first[20];
char last[20];
char full_name[40];

strcpy(first, "Robin");
strcpy(last, "Williams");

strcpy(full_name, first); /* full_name = "Robin" */
strcat(full_name, " "); /* note strcat NOT strcpy */
/* full_name = "Robin " */
strcat(full_name, last); /* full_name = "Robin Williams" */
printf("%s is very handsome.\n", full_name);
return 0;
}

Debugging exercise. What is wrong with the following program?

#include <string.h>
#include <stdio.h>
int main(void)
{
char first[100];
char last[100];
char full[200];

strcpy(first, "John");
strcpy(last, "Doe");

strcpy(full, first);
strcat(full, ' ');
strcat(full, last);
printf("The name is %s\n", full);
return 0;
}

Okay, now it looks like things are going to get interesting!
So far, we've been supplying all the data to our programs.
Now it looks like we're going to learn a way to enter some
data from the keyboard! !@#$%&*8^)

The standard library function fgets() can be used to read a
string from the keyboard. The general form of fgets() is:

fgets( array_name, sizeof(array_name), stdin);

where array_name is the name of a character array; sizeof(array_name)
is used to indicate the maximum characters to read, minus one for NUL;
and stdin is the file to read. In this case stdin is the standard
input, or keyboard. This program reads a line entered by the user
and reports the length of the line. Since fgets() includes the
end-of-line character, your string length will include a newline
('\n').

#include <string.h>
#include <stdio.h>
int main(void)
{
char line[80];

printf("Enter a line: ");
fgets(line, sizeof(line), stdin);
printf("The length of the line is: %d\n", strlen(line));
return 0;
}

Why don't we change the name program listed above to ask for the
user's first and last name? Here is one way to do it:


#include <string.h>
#include <stdio.h>
int main(void)
{
char first[20];
char last[20];
char full_name[40];

printf("Enter first name: ");
fgets(first, sizeof(first), stdin);
first[strlen(first) -1] = '\0'; /* trim off last character */
printf("Enter last name: ");
fgets(last, sizeof(last), stdin);
last[strlen(last) -1] = '\0'; /* trim off last character */

strcpy(full, first);
strcat(full, " ");
strcat(full, last);

printf("The name is %s.\n", full);
return 0;
}

Running the program gives the following output:

Enter first name: Jane
Enter last name: Doe
The name is Jane Doe.

So what's the deal with having to trim off the last character?
Since fgets() includes the newline and since there is a NUL
at the end of the string, if you don't trim off the last
character, the output would look like this:

The name is Jane
Doe.

Here is what the array last[] looks like after "Doe" is entered:

last[0] = 'D'
last[1] = 'o'
last[2] = 'e'
last[3] = '\n'
last[4] = '\0' /* end of string */

The line last[strlen(last) - 1] = '\0'; overwrites the newline
with a NUL so the name will all come out on the same line. Cool.

Multiple dimensional arrays have more than one dimension. We can
declare a two dimensional array like this:

/* comment stating what the array is for */
type array_name[size1][size2];

Note that each dimension is in square brackets. matrix[5][5] is
a two dimensional array that is 5 elements by 5 elements. We might
access an element like this: matrix[2][4] = 10;
We can add as many dimensions to an array as we have memory for it:

four_dimension[100][150][175][200];

Initialize a multi-dimensional array by enclosing each element in
curly braces {}. char tictac[3][3]; declares a tic-tac-toe board
and initializes its contents to blanks:

char tictac[3][3] =
{
{' ', ' ', ' ',},
{' ', ' ', ' ',},
{' ', ' ', ' ',},
};

To put an 'X' in the middle of the board: tictac[1][1] = 'X';

Look at it like this:
0 1 2
0 | |
---+---+---
1 | X |
---+---+---
2 | |

We're ready to start reading numbers now. Just about every other
textbook out there uses the scanf() function to do this, but Steve
Oualline has a better idea. He says that scanf() is notorious for
its poor end-of-line handling. But he knows how to get around that:
we won't use scanf() at all! Hooray! Instead, we'll use fgets()
to read a line of input, and use sscanf() to convert the text into
numbers. This sounds like fun.

We'll use the character variable `line' to read from the keyboard:

char line[100]; /* Line of keyboard input */

when we want to process input, we use:

fgets(line, sizeof(line), stdin);
sscanf(line, _format_, &variable1, &variable2, ...);

Note the ampersand in front of variable1. Don't forget it!
The _format_ is a string similar to the printf() format string.

In this program we use sscanf() to get a number and double it.

#include <stdio.h>
int main(void)
{
char line[100];
int value;

printf("Enter a number: ");

fgets(line, sizeof(line), stdin);
sscanf(line, "%d", &value);

printf("Twice %d is %d\n", value, value * 2);
return 0;
}

I'm going to stop here. I'll finish this later.

Happy Programming!
--
K