Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Advanced C 1992

.pdf
Скачиваний:
92
Добавлен:
17.08.2013
Размер:
4.28 Mб
Скачать

Part II • Managing Data in C

Listing 7.2. continued

Chicken Little has to be right only once.”, 0, “”, 0, “”, 0,

“Manly’s Maxim:”, 0,

Logic is a systematic method of coming to”, 0,

the wrong conclusion with confidence.”, 0,

“”,

0,

“”,

0,

“Moer’s truism:”, 0,

The trouble with most jobs is the job holder’s”, 0,

resemblance to being one of a sled dog team. No one”, 0,

gets a change of scenery except the lead dog.”, 0, “”, 0, “”, 0,

“Cannon’s Comment:”, 0,

If you tell the boss you were late for work because you”, 0,

had a flat tire, the next morning you will have a flat tire.”,

0,

};

for (i = 0;

i < (sizeof(MySaying) / sizeof(MySaying[0])); i++)

{

MySaying[i].nLength = strlen(MySaying[i].szSaying);

}

printf(“sizeof(MySaying) = %d\n”, sizeof(MySaying));

printf(“Number of elements = %d\n”, (sizeof(MySaying) / sizeof(MySaying[0])));

for (i = 0;

i < (sizeof(MySaying) / sizeof(MySaying[0])); i++)

{

printf(“MySaying[%2d] %p %3d ‘%s’\n”, i,

&MySaying[i].szSaying,

MySaying[i].nLength,

196

C Structures

C C C

 

C7C

 

C C C

 

C

MySaying[i].szSaying);

}

printf(“\n\n”);

return (0);

}

Let’s look at how the structure is declared. In the first few lines, the structure members and the structure’s name are established:

struct

{

char

szSaying[129];

int

nLength;

} MySaying[] = {

In the last line of this code fragment, brackets indicate that an array is being defined. (A nonstructure array is declared in this way also.) Following are the array brackets, which do not have a size. This tells the compiler to compute the number of elements in MySaying from the initializers.

I have not specified the number of elements; instead, the compiler computes this number. While the program is executing, it calculates the number of members using a simple formula:

nNumberOfMembers = (sizeof(MySaying) / sizeof(MySaying[0]))

The total size of the structure is divided by the size of the first member. (Remember that all members must be the same size.) This gives us the number of elements in the structure array. Computing the number of elements in this way is handy. If you want to change the initializers to add a new saying, for example, you won’t have to change the program.

You can write a macro to compute the number of elements as follows:

#define NUMBER_ELEMENTS(array) (sizeof(array) / sizeof(array[0]))

If you give this macro the name of an array (of any type), it returns the number of elements in the array. An example is shown in Listing 7.3, the STRUCTA program. The macro makes it easy to use loops to index an array whose number of elements has been determined by the initializers (or by any other means).

197

Part II • Managing Data in C

Listing 7.3. STRUCTA.C.

/* STRUCTA, written 1992 by Peter D. Hipson

*A program showing a macro to determine the

*number of elements in an array.

*/

#include <stdio.h> // Make includes first part of file #include <string.h> // For string functions

/* The NUMBER_ELEMENTS(array) macro returns the number of

*elements found in array. Array can be any array, including

*an array of type struct.

*/

#define NUMBER_ELEMENTS(array) (sizeof(array) / sizeof(array[0]))

int main(void); // define main(), and the fact that this program doesn’t // use any passed parameters.

int main()

{

int i;

struct

{

char

szSaying[129];

int

nLength;

} MySaying[] = {

“Firestone’s Law of Forecasting:”, 0,

Chicken Little has to be right only once.”, 0, “”, 0, “”, 0,

“Manly’s Maxim:”, 0,

Logic is a systematic method of coming to”, 0,

the wrong conclusion with confidence.”, 0,

“”,

0,

“”,

0,

“Moer’s truism:”, 0,

198

C Structures

C C C

 

C7C

 

C C C

 

C

The trouble with most jobs is the job holder’s”, 0,

resemblance to being one of a sled dog team. No one”, 0,

gets a change of scenery except the lead dog.”, 0, “”, 0, “”, 0,

“Cannon’s Comment:”, 0,

If you tell the boss you were late for work because you”, 0,

had a flat tire, the next morning you will have a flat tire.”,

0,

};

for (i = 0; i < NUMBER_ELEMENTS(MySaying); i++)

{

MySaying[i].nLength = strlen(MySaying[i].szSaying);

}

printf( /* String literal concatenation makes formatting lists easy */

“sizeof(MySaying) = %d\n” “Number of MySaying elements = %d\n” “sizeof(MySaying[0].szSaying) = %d\n”, sizeof(MySaying), NUMBER_ELEMENTS(MySaying), NUMBER_ELEMENTS(MySaying[0].szSaying));

for (i = 0;

i < NUMBER_ELEMENTS(MySaying); i++)

{

printf(“MySaying[%2d] %p %3d ‘%s’\n”, i,

&MySaying[i].szSaying,

MySaying[i].nLength,

MySaying[i].szSaying);

}

printf(“\n\n”);

return (0);

}

199

Part II • Managing Data in C

As Listing 7.3 shows, creating arrays of structures is simple and straightforward. Under ANSI C, you can initialize an auto structure as both a singular entity and an array, which makes it easier to use structures.

Listing 7.3 has some problems, however. Note the size of the structure when you run the program. It is huge! Because the size of the largest initializing string cannot be determined easily, I made the szString member large enough for all (or almost all) strings, 129 characters. The compiler adds a byte to pad this length to a wordboundary, making the length 130. The total length of the structure—including the integer length member, nLength—is 132 bytes. There are 18 members in the array of structures. When I compiled and executed the program, the total length was 2376 bytes. Perhaps there is a better way.

Structures of Arrays

If you can make an array from a structure, can a structure contain an array? Of course! The process of defining an array in a structure was demonstrated in Listing 7.3, in which the szString variable is a string variable, and string variables are made up of arrays of type char.

An advanced version of STRUCTA is shown in STRUCT3.C, Listing 7.4. This program stores pointers to a ragged-right array of character initializers. Because the program does not allocate additional space, this version is useful when the saved strings will not be modified. If you have to modify the saved strings, STRUCTA is a better choice.

Listing 7.4. STRUCT3.C.

/*

STRUCT3, written 1992 by Peter D. Hipson

*

A structure containing an array (or two).

*/

 

#include <stdio.h> // Make includes first part of file #include <string.h> // For string functions

#define NUMBER_ELEMENTS 35

int main(void); // define main(), and the fact that this program doesn’t // use any passed parameters.

200

C Structures

C C C

 

C7C

 

C C C

 

C

int main()

{

int i;

struct

{

char

*szSaying[NUMBER_ELEMENTS];

int

nLength[NUMBER_ELEMENTS];

} OurSaying = {

“Firestone’s Law of Forecasting:”,

Chicken Little has to be right only once.”, “”, “”,

“Manly’s Maxim:”,

Logic is a systematic method of coming to”,

the wrong conclusion with confidence.”,

“”,

“”,

“Moer’s truism:”,

The trouble with most jobs is the job holder’s”,

resemblance to being one of a sled dog team. No one”,

gets a change of scenery except the lead dog.”, “”, “”,

“Cannon’s Comment:”,

If you tell the boss you were late for work because you”,

had a flat tire, the next morning you will have a flat tire.”, NULL /* Flag to mark the last saying */

};

for (i = 0; OurSaying.szSaying[i]; i++)

{

OurSaying.nLength[i] = strlen(OurSaying.szSaying[i]);

}

printf(“sizeof(OurSaying) = %d\n”, sizeof(OurSaying));

for (i = 0; OurSaying.szSaying[i]; i++)

continues

201

Part II • Managing Data in C

Listing 7.4. continued

{

printf(“OurSaying %p %3d ‘%s’\n”, &OurSaying.szSaying[i], OurSaying.nLength[i], OurSaying.szSaying[i]);

}

printf(“\n\n”);

return (0);

}

Because I do not want to count by hand how many strings will be used to initialize the structure and cannot (in this context) let the compiler compute the number, I have a problem. I must specify the number explicitly. I chose a value of 35 (the identifier is called NUMBER_ELEMENTS) because I knew that there would not be more than 35 lines of sayings.

Although the number of elements is fixed at 35, all of them are not initialized. Therefore, the program needs a way to know when the end of the list has been reached. This is accomplished by adding a pointer with the NULL value as the last initializer. The program can test for the end of the array using a conditional test, such as

for (i = 0; OurSaying.szSaying[i]; i++)

Because ANSI C has defined NULL as a pointer that is never used, and because the value of NULL is usually zero when programming under DOS, this test always works.

If you are unwilling to assume that NULL is always defined as a zero value, the test could be rewritten as

for (i = 0; OurSaying.szSaying[i] != NULL; i++)

This conditional comparison of the pointer and NULL makes the test more explicit. I did not test for a zero-length string because the blank lines between sayings have a length of zero.

202

C Structures

C C C

 

C7C

 

C C C

 

C

Structures of Structures

It is common to have members of a structure be structures themselves. The maximum level of nesting is 15 according to the ANSI C standard. (You are unlikely to reach this limit.)

Listing 7.5, STRUCT4, has nested structure definitions. This program (built from STRUCT) has Murphy’s sayings and a few others I have collected over the years.

Listing 7.5. STRUCT4.C.

/*

STRUCT4, written 1992 by Peter D. Hipson

*

A program with nested structures.

*/

 

#include <stdio.h> // Make includes first part of file #include <string.h> // For string functions

int main(void); // Define main(), and the fact that this program doesn’t // use any passed parameters.

int main()

 

 

{

 

 

 

int

i;

 

 

struct SAYING

 

 

 

{

 

 

 

char

*szSaying[35];

 

int

nLength[35];

 

};

 

 

struct

 

 

 

{

 

 

 

struct SAYING

Murphy;

 

struct SAYING

Peter;

 

} OurSaying = {{

 

“Firestone’s Law of Forecasting:”,

continues

203

Part II • Managing Data in C

Listing 7.5. continued

Chicken Little has to be right only once.”, “”, “”,

“Manly’s Maxim:”,

Logic is a systematic method of coming to”,

the wrong conclusion with confidence.”,

“”,

“”,

“Moer’s truism:”,

The trouble with most jobs is the job holder’s”,

resemblance to being one of a sled dog team. No one”,

gets a change of scenery except the lead dog.”, “”, “”,

“Cannon’s Comment:”,

If you tell the boss you were late for work because you”,

had a flat tire, the next morning you will have a flat tire.”, NULL /* Flag to mark the last saying */

}, {

“David’s rule:”,

Software should be as easy to use as a Coke machine.”,

“”,

“”,

“Peter’s Maxim:”,

To be successful, you must work hard, but”,

Hard work doesn’t guarantee success.”,

“”,

“”,

“Teacher’s truism:”,

Successful people learn.”, “”, “”,

“Player’s Comment:”,

If you don’t play to win,”,

you don’t win.”,

NULL /* Flag to mark the last saying */ }};

for (i = 0; OurSaying.Murphy.szSaying[i]; i++)

{

204

C Structures

C C C

 

C7C

 

C C C

 

C

OurSaying.Murphy.nLength[i] = strlen(OurSaying.Murphy.szSaying[i]);

}

printf(“sizeof(OurSaying.Murphy) = %d\n”, sizeof(OurSaying.Murphy));

for (i = 0; OurSaying.Murphy.szSaying[i]; i++)

{

printf(“OurSaying.Murphy %p %3d ‘%s’\n”, &OurSaying.Murphy.szSaying[i], OurSaying.Murphy.nLength[i], OurSaying.Murphy.szSaying[i]);

}

printf(“\n\n”);

for (i = 0; OurSaying.Peter.szSaying[i]; i++)

{

OurSaying.Peter.nLength[i] = strlen(OurSaying.Peter.szSaying[i]);

}

printf(“sizeof(OurSaying.Peter) = %d\n”, sizeof(OurSaying.Peter));

for (i = 0; OurSaying.Peter.szSaying[i]; i++)

{

printf(“OurSaying.Peter %p %3d ‘%s’\n”, &OurSaying.Peter.szSaying[i], OurSaying.Peter.nLength[i], OurSaying.Peter.szSaying[i]);

}

printf(“\n\n”);

return (0);

}

STRUCT4 is the first program in this book that has used the structure tag. The definition of the structure is

struct SAYING

{

205