While single struct variables can be useful, there are many applications that require a collection of records. An array of structs or records is ideal for these applications. For example, suppose we need store a collection of addresses. We could create an array of Address structs the same as we would do when working with a collection of integer or floating-point values.
Defining the Array
To illustrate an array of records, suppose we want to represent a triangle, which consists of three vertices. We can define an array of Point structs with 3 elements to represent the triangle
Figure 9.5.1. An array of Point structs.
struct Point triangle[3];
which can be visualized as shown in Figure 9.5.1. Here, each element of the array contains a Point struct variable. If we need to access an entire struct variable within an element of the array, we can do so by specifying the appropriate subscript. For example,
struct Point vertex = triangle[0];
creates a new Point struct named vertex and initializes it with the contents of the struct variable in the first element of the array.
Accessing Struct Fields
To access an individual field within a struct stored in an array element, we use the expression:
which will assign 0 to the x field of the Point struct in the second element. Suppose we want to initialize all of the vertices to 0, we can use a for loop as shown below
for(int i = 0; i < 3; i++) {
triangle[i].x = 0;
triangle[i].y = 0;
}
which results in the following
As an alternative, we could initialize a Point struct with both fields set to 0 and then assign the struct to each element of the array
struct Point init = {.x = 0, .y = 0};
for(int i = 0; i < 3; i++) {
triangle[i] = init;
}
Struct Pointers
If you need to get the address of a struct variable stored in an array, you simply take the address of the specific array element:
struct Point *pt = &triangle[2];
which results in the following
Given the pointer, pt, we can access the fields of the struct in the last element through the pointer instead of the array subscript. For example, we can change the x- and y-coordinates of that point:
which updates the array with the following:
The triangles.cc sample program below provides a real-world example of using an array of Point structs to represent a triangle.
Testing for Right Triangles |
/* triangles.cc
*
* Reads three discrete vertices from the user that represent a triangle and
* determines if the triangle is a right triangle.
*/
#include <stdio.h>
#include <math.h>
// Define a 2-D discrete point.
struct Point {
int x;
int y;
};
void readVertices(struct Point triangle[]);
bool isRightTriangle(struct Point triangle[]);
float distance(struct Point vertex1, struct Point vertex2);
float equalFloats(float value1, float value2);
int main()
{
struct Point triangle[3];
/* Read the vertices from the user. */
readVertices(triangle);
/* Test if the triangle is a right triangle. */
if(isRightTriangle(triangle))
printf("The triangle is a right triangle.\n");
else
printf("The triangle is not a right triangle.\n");
}
/* Prompts for and reads the coordinates for three vertices from standard
* input and stores them in an array of Points. */
void readVertices(struct Point triangle[])
{
int x, y;
for(int i = 0; i < 3; i++) {
printf("Enter the coordinates of vertex %d\n", i);
printf(" x: ");
scanf("%d", &x);
printf(" y: ");
scanf("%d", &y);
triangle[i].x = x;
triangle[i].y = y;
}
}
/* Computes and returns the distance between two points. */
float distance(struct Point vertex1, struct Point vertex2)
{
int xDiff = triangle[0].x - triangle[1].x;
int yDiff = triangle[0].y - triangle[1].y;
return = sqrt(xDiff * xDiff + yDiff * yDiff);
}
/* Determine if the two floating-point values are equal. */
float equalFloats(float value1, float value2)
{
// A small threshold used for comparing if two floats are equal.
const float delta = 1e-9;
/* It can be difficult to compare real values (s == r).
The most efficient way to do this is to:
(1) take the difference between the two values (s - r)
(2) compare it against a very small delta value (1e-9)
If (s - r) < 1e-9, then the values are approximately equal.
*/
if(value1 - value < delta)
return true;
else
return false;
}
/* Determines if the triangle is a right triangle. */
bool isRightTriangle(struct Point triangle[])
{
// Compute the lengths of each side of the triangle.
float distAB = distance(triangle[0], triangle[1]);
float distBC = distance(triangle[1], triangle[2]);
float distCA = distance(triangle[2], triangle[0]);
// Identify the longest side of the triangle and the other two sides.
float c, a, b;
if(distAB > distBC && distAB > distCA) {
c = distAB;
a = distBC;
b = distCA;
}
else if(distBC > distAB && distBC > distCA) {
c = distBC;
a = distAB;
b = distCA;
}
else {
c = distCA;
a = distAB;
b = distBC;
}
// If the c^2 == a^2 + b^2, it's a right triangle.
return equalFloats(c * c, (a * a + b * b));
}
|