Therefore, there is a need for a data structure that can contain components with different types (which means an array cannot be directly used).
In C, a structure can be defined by specifying its components by type and name.
For example, a planet can be described by its five attributes: name, diameter, number of moons, orbit time, and rotation time. To organize these data together, the following structure type planet_t can be defined:
#define STRSIZ 10 typedef struct { char name[STRSIZ]; double diameter; int moons; double orbit_time, rotation_time; } planet_t;When a variable is declared as of a structure type, the variable will get the memory for storing values for its components. For example,
planet_t current_planet, previous_planet, blank_planet = {"", 0, 0, 0, 0};The last declaration comes with an initialization of the components, according to their defining order in the structure.
A component in a structure type can be a (previously defined) structure type or array, so as to form a hierarchical structure.
In general, a structure type is defined in the following format:
typedef struct { type_1 name_list_1; type_2 name_list_2; ... ... type_n name_list_n; } type_name;where a name list consists of component names separated by comma (",").
Please note the similarity and difference between this definition and the definition of an enumerated type, as well as an array.
After a structured variable is declared as belonging to a structure type, a component in it can be accessed using the variable name followed by the direct component selection operator, which is a period ("."). A component used in this way is just like a variable of the corresponding type, as in FIGURE 10.1:
Then, the following statement
printf("%s's equatorial diameter is %.1f km.\n", current_planet.name, current_planet.diameter);displays the sentence
Jupiter's equatorial diameter is 142800.0 km.The direct component selection operator has the highest precedence (when used with other operators) and is left associative (when occurring more than once). See Table 10.1 (page 572), or this webpage, for a review of precedence and associativity of operators.
When the name of a structure type variable is used with no component selection operator, it refers to the entire structure. A new copy of a structure's value can be made by an assignment, as the following:
previous_planet = current_planet;
For example, see the programs in FIGURE 10.2, FIGURE 10.3, and FIGURE 10.4.
Please note that in the last example, "&(*plnp).diameter" actually means "&((*plnp).diameter)", and it cannot be further simplified into "&*plnp.diameter" — here "." has higher precedence than "&" and "*", and the other two are right associative.
FIGURE 10.5 shows the data areas of functions main and scan_planet during execution of the following statement in main:
status = scan_planet(& current_planet);
C also provides an indirect component selection operator, "->", as a combination of a direct component selection operator and a pointer reference, that is, when structp is a pointer to a structure, the following two expressions are equivalent:
(*structp).component // referencing, then direct component selection structp->component // indirect component selectionConsequently, the assignment in FIGURE 10.4 can be rewritten as
result = scanf("%s%lf%d%lf%lf", plnp->name, &plnp->diameter, &plnp->moons, &plnp->orbit_time, &plnp->rotation_time;Here "->" has a higher precedence than "&".
Example: FIGURE 10.6 and FIGURE 10.7, and in the latter the following structure is used:
typedef struct { int hour, minute, second; } time_t;The following statement uses the function to update a time record:
time_now = new_time(time_now, secs);as shown by FIGURE 10.8:
ADT provides a higher-level description about the data and the operations.
We use the following structure type for complex numbers:
typedef struct { double real, imag; } complex_t;The operations defined on complex numbers are specified by the following function prototypes:
int scan_complex(complex_t *c); void print_complex(complex_t c); complex_t add_complex(complex_t c1, complex_t c2); complex_t subtract_complex(complex_t c1, complex_t c2); complex_t multiply_complex(complex_t c1, complex_t c2); complex_t divide_complex(complex_t c1, complex_t c2); complex_t abs_complex(complex_t c);A partial implementation of these functions, as well as a demo driver, are in FIGURE 10.10.
For example, if each student record consists of an ID number and a GPA value, then a list of students can be represented as an array of structure:
typedef struct { int id; double gpa; } student_t; student_t stulist[50];and the array is shown in FIGURE 10.11:
The same data can be stored as two arrays that "parallel" to each other, in the sense that the same index in them indicate data for the same student:
int id_list[50]; double gpa_list[50];Usually the first way is more natural and convenient.
typedef struct { /* unit of measurement type */ char name[NAME_LEN]; /* character string such as "milligrams" */ char abbrev[ABBREV_LEN];/* shorter character string such as "mg" */ char class[CLASS_LEN]; /* character string such as "pressure", "distance", "mass" */ double standard; /* number of standard units equivalent to this unit */ } unit_t;All the units are put into an array of unit_t. Each time the user is asked to input a measurement value, the old (source) unit, and the new (destination) unit. The result is the same measurement in the new unit.
The complete program is in FIGURE 10.12. The data file and sample run are shown in FIGURE 10.13: