#include <stdio.h> //for printf
#include <string.h> //for strcpy
//------------------------------------------
// ARRAYS: What really goes on
//------------------------------------------
//------------------------------------------
// Example #1: Storing text in an array
//------------------------------------------
void Example1()
{
/*
First, lets look at arrays in a common use. In this scenario,
many new programmers dont realise that they are using an array,
or what exactly it is thats happening behind the scenes.
*/
char String[13];
strcpy(String, "Hello World!");
printf("Array Contains: %s\n", String);
/*
So what happened there?
Well, on the first line we declared our variable. Its an array
of type char with 13 elements. Each element of the array is going
to hold one character of the string we want to print. The next line
copies our string into that variable. Visualizing the array:
-----------------------------------------------------
Element# | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10| 11| 12|
-----------------------------------------------------
Value | H | e | l | l | o | | W | o | r | l | d | ! | |
-----------------------------------------------------
Notice that the first element is _not_ number 1, its 0. Thats
because an array is always mapped from 0 to n-1. This means that
the thirteenth element of our array is #12.
Another question you're probably asking in this situation is:
Whats that blank space at the end? Well, since we're using this
array for text, and we want to be able to perform actions like
strcmp, strcpy, and the like, we need to have some way to tell
those functions where the end of the text is. Without any marker,
the function would keep reading the array long past its last
element, which could cause all sorts of unpredictable behavior,
but would most likely crash your program.
Thats where the NULL Terminating Character comes into the picture.
Though we cant see it happening, the text "Hello World!" contains
this magical NULL character at the end. Our compiler automcatically
does this for us when it reaches the "Hello World!" string. Then,
when its copied with strcpy into the String array, there has to be
room for it. If we try to strcpy to an array that isnt big enough
to hold it, strcpy tells us this: "No overflow checking is
performed when strings are copied or appended." Thats bad. We must
make sure that we never ever use memory that doesnt belong to us.
*/
}
//------------------------------------------
// Example #2: Using an array as a lookup table
//------------------------------------------
void Example2()
{
/*
Now, lets look at using arrays for simple data storage. This is a
very important and helpful use of arrays.
*/
int AgeOfFamily[4] = {0,0,0,0};
int i; //for the for loop counter
AgeOfFamily[0] = 35;
AgeOfFamily[1] = 33;
AgeOfFamily[2] = 6;
AgeOfFamily[3] = 4;
for(i = 0; i < 4; i ++)
{
printf("Age of family member %i is: %i\n", i, AgeOfFamily[i]);
}
/*
So what happened there?
Well, on the first line we declared our variable. Its an array of
type int, with 4 elements. Each element is going to hold the age
of one of the members of a family. Notice I initialise all values
to 0. Thats this part: "= {0,0,0,0}". Even though we're setting all
4 values of AgeOfFamily directly afterwards, its a good idea to
have a default initialisation. In larger programs its easy to get
confused and wind up using a variable that has never been set. This
can lead to all kinds of confusing results and is often very hard
to debug.
Next we're going to set each element of the array:
AgeOfFamily[0] = 35;
Whats happening here is fairly obvious. 0 is the first element, and
we're assigning it a value of 35. Simple. Just like any normal
variable. We do the same thing for the rest of the elements, and
assign different values for each. Visualising:
-----------------
Element# | 0 | 1 | 2 | 3 |
-----------------
Value |35 |33 | 6 | 4 |
-----------------
NOTE: We have to be careful that we never do something like this:
AgeOfFamily[4] = 2;
That could be catastrophic. Since arrays are indexed from 0 to n-1,
saying [4] is actually accessing the fifth element, or more
specifically, the section of memory after the fourth element. Since
there is no fifth element (barring the movie starring Bruce Willis,
which I enjoyed quite a bit, and actually _does_ exist), we're
accessing memory that we dont own. As I've said many times before,
and will continue to say: This is something that should never be
done. Bad things will happen. The worst part being that bad things
will not _always_ happen every time. That means that your program
might run fine when you test it, but crash later on. That makes it
really hard to debug, since you may already have moved on long ago.
Next up: We use a "for" loop to cycle through each element of the
array and display its contents. This demonstrates how useful it
is to use arrays in this instance (and so many others). Without the
array, we would need a variable for each family member, and we would
need to deal with each one separatly. Thats not too horrible with 4
family members... but imagine you were cataloging all the childrens
ages in an elementary school!
*/
}
//------------------------------------------
// Example #3: Multi-Dimensional Arrays
//------------------------------------------
void Example3()
{
/*
Getting more complicated... and more useful. We now look at 2D
arrays and their uses.
*/
int Grid[3][3] = {16,32,64,
10,11,12,
99,98,97};
int x, y; //for the for loop counters
for(y = 0; y < 3; y ++)
{
for(x = 0; x < 3; x ++)
{
printf("x%i y%i: %i ", x, y, Grid[y][x]);
}
//Every time we reach the end of a row, move down one space
printf("\n");
}
/*
So what happened there?
Well, on the first line we declared our variable. Its an array of
type int, with a total of 9 elements; 3 rows x 3 coloumns = 9
elements in all. This array works just like the previous example
except that we now how two dimensions to work in. This is a little
more complicated to visualise, but lets try:
----------------
|x0y0|x1y0|x2y0|
----------------
|x0y1|x1y1|x2y1|
----------------
|x0y2|x1y2|x2y2|
----------------
Just like always, we still have to be careful not to access either
dimension of the array outside its bounds. "Grid[2][3] = 0;" is
_not_ an okay thing to do. Remember: arrays index from 0 to n-1, so
our 3x3 arrays third (and last) element in both directions is 2.
And then, just like in our previous example, we loop through the
array and display its contents. Since this array has two dimensions,
we have to loop through both of them. First we loop through each
coloum in the first row. When a row is done, we move to the next
row and repeat.
*/
}
//------------------------------------------
// MAIN
//------------------------------------------
int main(void)
{
printf("*** Example # 1 ***\n\n");
Example1();
printf("\n\n*** Example # 2 ***\n\n");
Example2();
printf("\n\n*** Example # 3 ***\n\n");
Example3();
/*
ARRAYS: Technical Overview (for the ambitious)
An array is simply a continuous section of memory equal to the
size of the variable type times the number of elements in the
array. i.e. a char array with 5 elements is 40 bits long. a char
is 8 bits x 5 elements = 40 bits. You will find that in certain
circumstances, a sizeof operation on the array will tell you that
it is larger than you expected. This has to do with variable
padding and is specific to the OS. You shouldnt worry about this
_right now_, as it all goes on well behind the scenes.
This doesnt specifically relate to arrays, but to any variable.
I'm convering here to clear up possible misunderstandings in the
future. Though the first example shows the use of a char array to
hold text, there is no actual letters or characters stored. What
happens instead is that there is a _value_ assigned to each
character on your keyboard (as well as many others). These are
refered to as ASCII values. The array actually contains a number
whos value corresponds with the letter/symbol/number in your
string. If we actually looked in the array we'd see these values:
-----------------------------------------------------
Element# | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10| 11| 12|
-----------------------------------------------------
Value | 72|101|108|108|111| 32| 87|111|114|108|100| 33| 0|
-----------------------------------------------------
Those numbers are the ASCII values of the characters they
correspond to. Notice that the apparent space between "Hello" and
"World" is not actually a space at all? 32 is the ASCII value for
a space. Notice the 0 at the end? Thats our NULL terminating
character.
You see, even though we thought of char String[13] as a string, it
really isnt. Its just an array of values, the same as the rest.
If we said "printf("%i\n", String[0]);" after the strcpy, our output
would be "72".
*/
return 0;
}