Author : Christopher Sawtell
Page : << Previous 7 Next >>
/* generated format
string */
printf( "\n" );
}
/* ----------------------------------------- */
If you cheated and looked at my example before even attempting
to have a go, you must pay the penalty and explain fully why
there are THREE "%" signs in the line which starts with a call
to the sprintf function. It's a good idea to do this anyway!
So much for printf(). Lets examine it's functional opposite - scanf(),
Scanf is the family of functions used to input from the outside world
and to perform internal format conversions from character strings to
binary numbers. Refer to the entry scanf(3S) in the Programmer
Reference Manual. ( Just a few pages further on from printf. )
The "Important Point to Note" for the scanf family is that the
arguments to the function are all POINTERS. The format string has to
be passed in to the function using a pointer, simply because this
is the way 'C' passes strings, and as the function itself has to store
its results into your program it ( the scanf function ) has to "know"
where you want it to put them.
You can allocate space for an array of elements at compile time with fixed
dimension sizes of any data type, even functions and structs.
So these are legal array definitions:
char name[30]; /* An array of 30 signed
characters. */
char *strings[50]; /* 50 pointers to strings. */
unsigned long int *(*func)()[20];/* An array of pointers to functions which
*/
/* return pointers to unsigned long ints.
*/
You can declare a pointer to point at any type of data element, and as in
the array situation above functions and structs are included.
struct ship
{
char name[30];
double displacement; /* in grammes */
float length_of_water_line; /* in meters */
unsigned short int number_of_passengers;
unsigned short int number_of_crew;
};
So using the ship concept from Lesson 2 you can declare a pointer to point
at one of the ship structs in an array.
struct ship *vessel_p;
Note the use of the suffix "_p".
This is my way of reminding myself that the variable is a pointer.
struct ship fleet[5]; /* This allocates enough storage for
5 ships' info.
*/
Now lets set the pointer to point at the first vessel in the fleet.
vessel_p = fleet;
This pointer can be made to point at other ships in the fleet by
incrementing it or doing additive arithmetic on it:
vessel_p++; /* point a the next ship in the fleet array. */
vessel_p = fleet + 3;
Also we can find out the index of the ship in the fleet at which we are
pointing:
i = vessel_p - fleet;
It is also legal to find out the separation of two pointers pointing at
elements in an array:
d = vessel_p - another_vessel_p; /* This gives the separation
in elements. */
So summarising, pointers may be, incremented, decremented, and subtracted
one from another or have a constant subtracted from them. Any other
mathematical operation is meaningless and not allowed.
Assembler programmers should note that while the pointer variables contain a
byte machine address, when the arithmetic is done using pointers the
compiler
also issues either a multiply or a divide as well as the add or subtract
instruction so that the result is ALWAYS expressed in elements rather than
bytes. Have a go and write yourself a trivial little program, and have a
look at the compiler ouput code. Lesson 1 told you how!
When using a pointer to reference a structure we have to use a "pointer
offset" operator in order to access the member of the struct we require:
vessel_p = fleet;
vessel_p->name = "Queen Mary";
vessel_p->displacement = 97500000000.0;
vessel_p->length_of_water_line = 750.0
vessel_p->number_of_passengers = 3575;
vessel_p->number_of_crew = 4592;
Remember:
It's a "." when accessing a struct which is in storage declared in
the program.
It's a "->" when accessing a struct at which a pointer is pointing.
Initialisation of arrays.
'C' has the facility to initialise variables in a program script.
Some examples:
char *qbf = "The quick brown fox jumped over the lazy dogs back";
int tic_tac_toe[3][3] =
{
{ 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 }
};
struct ship fleet[2] =
{
{ "Queen Elizabeth", 97500000000.0, 750.0, 3575, 4592 },
{ "Queen Mary", 115000000000.0, 875.0, 4500, 5500 }
};
Take a careful note of where the commas and semi-colons go ( and don't go )!
Initialised Tables of Indeterminate Length.
One nice feature 'C' offers is that it is able to calculate
the amount of storage required for a table by 'looking' at the number
of initialisers.
char *verse[] =
{
"On top of the Crumpetty Tree",
"The Quangle Wangle sat,",
"But his face you could not see,",
"On account of his Beaver Hat.",
"For his Hat was a hundred and two feet wide.",
"With ribbons and bibbons on every side,",
"And bells, and buttons, and loops, and lace,",
"So that nobody ever could see the face",
"Of the Quangle Wangle Quee."
NULL
};
Note the * character in the definition line. This means that we are going
to make an array of pointers to variables of type char. As there is no
number between the [ ] characters the compiler calculates it for us.
With this kind of set-up it is nice and easy to add extra information
to the table as program development proceeds. The compiler will calculate
the new dimension for you. The point to remember is that the program has to
know - from the contents of the table - that it has come to the end of the
table! So you have to make a special entry which CANNOT under any
circumstances be a real data element. We usually use NULL for this.
The other way is to calculate the size of the table by using the sizeof
operator - Note that although use of sizeof looks like a function call
it is in fact an intrinsic operator of the language. The result is
available at compile time. So one can say:-
#define SIZE_OF_VERSE sizeof verse
There is one final initialised data type, the enum. It is a fairly recent
addition
Page : << Previous 7 Next >>