Using Arrays of Structures

Structures, just like integers, floats, and characters, can be used in arrays. The syntax for creating one is just like you'd expect:

struct students {
   char name[30];
   float gpa;
};
struct students class[20];

To refer to an individual array element, you would of course refer to the array's index, like class[19]. To refer to an individual structural member of an individual array element, the syntax is

					array_name[index].field_name
class[10].gpa = 2.78;

In our next example, we create a list of student names and grades by taking input from the user and storing it in an array of structures.

To use arrays of structures

1.
Create a new file or project in your text editor or IDE.

2.
Type the standard beginning lines of code (Script 13.3).

/* grades.c - Script 13.3 */
#include <stdio.h>

Script 13.3. An array of structures is used to represent an entire class of students. Each array element stores the student's first name, last name, and grade.


3.
Include the string.h library file:

#include <string.h>

In order to use the strncpy() function, the string.h file must be included.

4.
Define two macro constants:

#define STR_LEN 20
#define NUM_STUDENTS 10

The first value represents the maximum string length (for a person's first and last names). The second will be the number of elements in the array.

5.
Begin the main function:

int main (void) {

6.
Define the structure:

struct student_grade {
     char first_name[STR_LEN];
     char last_name[STR_LEN];
     float grade;
};

The structure has two character arrays and one float.

7.
Use typedef to rename the structure syntax, then create an array of structures:

typedef struct student_grade sg;
sg class[NUM_STUDENTS];

Again, the typedef simplifies the process of referring to a structure. Then an array of structures called class is created.

8.
Create the other variables:

int i, num;
int count = 0;
float g;
char classname[12], fn[STR_LEN],
 ln[STR_LEN];

Several standard variables are required to handle the user input. Three integers are declared: i, a loop counter; num, which will be used to validate the input; and, count, which will count the number of entered records. One float is required to store the grade point average (which will then be stored in the array of structures). Finally there are three character arrays. Two match up with the first_name and last_name structure members and the third is for storing a class name.

9.
Prompt the user and read in the class name:

printf ("Enter the classname (without
 spaces): ");
scanf ("%11s", classname);

The application begins by taking the name of the class for which student records will be entered (Figure 13.7). The assumption is that this will be something like Algebra, English, or EN302.

Figure 13.7. The user is first prompted to enter the name of a class.


10.
Begin a loop:

for (i = 0; i < NUM_STUDENTS; ++i) {

The user will be prompted to enter several student records. This process takes place within a loop, which goes from 0 to 1 less than NUM_STUDENTS (the size of the array).

11.
Prompt the user and read in the input:

printf ("Enter the student's name
 and their grade. Enter 0 0 0 to
 quit.
(First Last ##.#): ");
num = scanf ("%11s %11s %f", fn, ln,
 &g);

First the user is prompted so that they know what information is requested and in what format (Figure 13.8). Then the scanf() function is called, assigning the input to the fn, ln, and g variables.

Figure 13.8. Reading in one student record at a time.


12.
Check if the user has finished entering records:

 if (fn[0] == '0') {
     break;
 }

As you can tell from the prompt (see Figure 13.8), if the first character entered is a 0, the user has no more records to enter. This conditional checks for that contingency and exits the for loop (via the break statement) if it is true.

13.
Check if the proper input was entered:

if (num == 3) {

The num variable is assigned a value from the scanf() function. If that function read in three items and assigned them to the three variables, we can assume that the data was entered correctly.

14.
Assign the input to the structure:

strncpy(class[i].first_name, fn,
 STR_LEN-1);
class[i].first_name[STR_LEN-1]
 = ''; 
strncpy(class[i].last_name, ln,
 STR_LEN-1);
class[i].last_name[STR_LEN-1] =
 ''; 
class[i].grade = g;
++count;

Assigning values to an array of structures is easier than you might think. Begin by identifying the specific array element: class[i]. Then refer to each member number using the .member syntax.

The strncpy() function is used to assign values to the two character arrays and the grade value is assigned using the assignment operator. After each name value is assigned, their final character (STR_LEN - 1) is assigned a terminating character. This is a safety precaution, as each string may not have been properly terminated during the copy.

Structures and Pointers

You can, naturally, create a pointer to a structure. As with any pointer, the type of pointer must match the type of variable it points to. So

struct student {
   char name[30];
   float gpa;
};
struct student timmy, * struct_ptr;
struct_ptr = &timmy;

Once you've done this, you can do all the wonderful things with the pointer that you've now (possibly) grown accustomed to. For example, you can pass the structure's pointer to a function.

To refer to a structure's member by using a pointer, there are two options:

(*struct_ptr).member

or

struct_ptr->member

The first, more complex example requires the parentheses, since the dot has a higher precedence than the dereferencing operator (*). The second option is syntactically easier and means the same thing.

Finally it should be said that when working with pointers to structures, the programmer must clearly understand how memory is being allocated. If it's dynamically allocated using malloc(), as in the next example, you must be certain to free any used memory. If the memory is statically allocated, you do not need to worry about freeing it.


15.
Complete the num conditional and the loop:

      } else {
             printf ("The data was
 not in the proper format.
");
             break; 
      }
}

If the value returned by scanf()num—is not equal to 3, the data wasn't entered properly and the loop should be exited.

16.
Print all of the records:

printf ("Students and grades for the
 class '%s':
", classname);
for (i = 0; i < count; ++i) {
     printf("%s %s %0.1f
",
 class[i].first_name,
 class[i].last_name,
 class[i].grade);
}

Printing the records requires another for loop. Instead of counting up to NUM_STUDENTS, it goes to count, which is the actual number of records entered.

Within the loop itself, each array element and structure member is fed to the print statement.

17.
Complete the main function:

      getchar();
      getchar();
      return 0;
}

18.
Save the file as grades.c, compile, and debug as necessary.

19.
Run the application, varying the number of entries (Figure 13.9).

Figure 13.9. Several records are entered and then redisplayed by the application.


✓ Tips

  • Arrays of structures can be initialized during declaration, but the syntax can be very complicated.

  • Structures can also be nested, where the definition of one structure includes a field of a structure type.

  • In a way, understanding structures is a good first step toward understanding object-oriented programming (OOP). OOP involves the definition of classes, composed of both variables and functions.

  • You could improve upon this application in many ways—such as storing the records in a binary file, putting more thorough validation routines in place, or using the discard_input() function—but, as it stands, it's a good representation of how to use an array of structures.


..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset