The answers from last time's puzzles are again too long to list here, so they are both on the cover disc again this month. As before though, an SAE with a floppy will get you them from myself or Archive.
You will have guessed that n is for a new line to be printed and t tabs along the text. There are still more of these, and they are listed below.
Letter | Meaning |
\\ | backslash |
\' | single quote |
\" | double quote |
\? | question mark |
\a | bell |
\b | backspace |
\f | formfeed |
\n | newline |
\0 | NULL |
\r | carriage return |
\t | tab |
\v | vertical tab |
\xhhh | insert ASCII code hhh |
One addition to the % list given in the second article is %0. This causes all the leading zeros to be printed out.
That's all I need to add on the printf command, so on with arrays.
There is no DIM statement in C; arrays are defined by using the variable type, variable name and the number of components held within square brackets [].
char string[30]; int fred[35]; double big[10];
These define a character array of 30 elements, an integer of 35 and a double of 10.
An important fact to remember about arrays is that they go from 0 to n-1 (that is, if the array is [10], the array goes from 0 to 9).
If in Basic, you wanted to define a DIM statement to contain some fixed data or other (say, birth dates), you would use something like this
DIM birthdays(8) FOR a%=1 TO 8 READ birthdays(a%) NEXT DATA ........
In C, this is done away with. To define a set of data elements for an array, you simply encase the data within a set of curly brackets.
int birthdays [8] = { date1, date2, date3 .... };
A two-dimensional array works slightly differently as it has to be thought of as a block of x rows.
The above diagram should make it clearer. A 3 × 3 array contains nine elements all told. The addressing of this array is as follows.
Say you want the second element of the third row assigned to variable x, you would use
x = array [2] [1];
And remember, arrays go from 0, not from 1.
Defining a 2D array is the same as a 1D array, except that the second element needs to be held in another set of brackets. So,
int two_d [10] [10];
defines the int array two_d 10 elements by 10 elements (giving a total of 100 elements).
As before, the contents can be initialised by the use of curly brackets.
The 3D array is the same as a 2D, but with another set of numbers in square brackets.
int three_d [5] [10] [4];
This would give 5 down, by 10 across by 4 'diagonally', giving a total of 5 × 10 × 4 = 200 elements.
Accessing a 3D array into a different variable (say you want point 3 - 6 - 2 - remembering that the array goes from 0 first though!)
var = array [2] [5] [1];
There are a couple of nice little tricks when dealing with arrays under C.
The first is when defining a 1D array and using a set of curly brackets, you don't need to define the number of elements within the square brackets - the compiler does this for you. This is known as an unsized array and is useful as you can always resize it should you need to. This can also be applied to a multi-dimension array. You don't need to define the first element, but do need to define the rest.
Strings need to be handled slightly differently. So, say we had
char names [3] [6] [80];
This would mean we have three lists of strings (say names, birthdays and religion) of six elements of strings, each of a maximum of 80 characters.
Accessing something from this array would be done by saying which list and which element
printf("%s",names[2] [2]);
would display the contents of the third person's religion.
Data can be entered into the array using the standard gets() function, thus:
gets (name [list][element]);
A far simpler method (and much faster) of passing an array across multiple functions is to use a pointer.
This is defined in the same way as you would any other pointer:
int *array [x][y][z]; int array [x][y][z]; int *pointer; pointer=array;
These would define (a) a pointer array of int values, (b) a normal array, (c) a pointer and (d) then makes the pointer equal to the base of the array in memory.
Now, instead of passing over a huge array, you're simply passing over a pointer containing the base of the array in memory. Far quicker!
There are a couple of drawbacks to using pointers with arrays. Firstly, look at the following snippet
int x [10] = { 10 values }; int *pointer; pointer=x; printf("%d %d %d\n",*pointer,*(pointer+1),*(pointer+2)); printf("%d %d %d\n",x[0],x[1],x[2]);
You'll see that pointer+1 is held within brackets. This is because the pointer is a higher priority than the +. The brackets are a higher priority than the pointer, so this is processed first. Other than that, the two printf lines do exactly the same.
The second drawback is when accessing a multi-dimensioned array.
Say we've defined
float numbers [5][6];
Normally, we would access this by saying
x = numbers [3][4];
However, we're using a pointer, so the fragment would look like this:
float *pointer; pointer = (float *) numbers; printf ("value at x [3][4] = %d\n",*(pointer + (3 * 6) + 4));
In other words, to access point [3][4], you first have to multiply the number of rows by the number of elements in that row (in this case, row 3 × 6 elements) then add the actual element you're after.
It is a lot of messing around and, unless you're going to be passing this across a function, you're going to be better off with the normal x = array [3][4]; command.
The (float*) is known as a cast and was needed in this example, as the array had to be indexed manually, so the pointer arithmetic had to be kept relative to a float pointer.
Character and numeric arrays can also be treated the same as normal numbers and arrays within an if else or switch case condition.
That's enough for this time. Next time I'll be revisiting functions and looking at prototypes and recursion within a function. Until then, here's this time's teasers...
1. Adjust the functions written in the simple maths program you should have done for this time so that the numbers can be floating point or integer and also that the sum and average function(s) use a dimension to store the numbers in (to a maximum of 10).
2. Write a phone directory program which stores the name, phone number (with the STD code separate), four lines for the address and one line for the postcode. Make sure this program has a lookup and display function so that you can find a name and number. The name and phone number arrays should be pointers. Make the program able to store 100 names.
This second program is far more important than the first and should be done as it will be built on later. I would also suggest upgrading your Archive subscription now to include the monthly disc (that's a subtle hint as to how much code there will be soon!).
Source: | Archive Magazine 13.6 |
Publication: | Archive Magazine |
Contributor: | Paul Johnson |