The C language allows an array to be used as a structure member. This enables us to group related structure members and is also useful for declaring character strings as structure members. This section explains how we can effectively use such structures. This includes
I. Declaration of structures containing arrays
2. Initialization of structures containing arrays
3. Accessing member arrays and passing them to functions
4. Accessing individual elements of member arrays
5. Using structure that contain arrays as function parameter and return value
We’ll be covering the following topics in this tutorial:
Declaring Structures Containing Arrays
A structure may contain one or more array members, each of a different type and size. The array members are declared using the usual syntax. We can declare ordinary (scalar) members and array members in any order. However, remember that the names of the members of a structure must be distinct.
Example of Declaring structures containing arrays
a) Structure declaration for a person’s data
Consider the declaration of structure person given below that uses a character array name as a member to store a person’s full name, and two other members to store the person’s gender and age.
struct person { char name[60]; /* person's name */ char gender; /* M: male, F: female */ int age; } ;
We often expect a person’s name to be displayed in some specific order, e. g., last name followed by first name and middle name. This cannot be ensured if we use a single character array to store the person’s name. Hence, we can use three arrays, say, lname, fname and mname, to store these components. We can also store the salutation (such as Mr., Ms., Mrs., Dr., Shri, Smt., etc.) in another array named salut. Thus, the structure person is modified as shown below.
struct person { char salut[5]; /* salutation */ char lname[20]; /* last name */ char fname[20]; /* first name */ char mname[20]; /* middle name */ char gender; /* M: male, F: female */ int age; } ;
Although one character position is required to store the null terminator for the string data, the sizes of the member arrays (salut, lname, fname and mname) are adequate for most, if not all, persons. We can increase these array sizes, but it leads to large memory wastage, particularly when we declare an array of this structure to store the data of several persons. As multiple members can be declared in a single declaration, we can rewrite the above declaration as shown below.
struct person { char salut[5]; /* salutation ·•/ char lname[20], fname[20], mname[20]; /* person's name */ char gender; /* M: male, F: female */ int age; } ;
Now we can declare variables of this structure as shown below:
struct person boss, secretary, client;
b) Structure declaration for HSC examination details of a student
Consider the declaration of structure hsc_stud given below that can be used to store the HSC examination details of a student.
struct hsc_stud { int seat no; /* exam seat number */ char salut[5]; /* salutation */ char lname[20], fname[20], /*student's name*/ int marks[6]; /* marks in six subjects */ int tot_marks; /* total marks */ float perce_marks; /* percentage marks */ char result[5], class[25]; /* exam result and class obtained */ mname[20]; };
The arrays used in this structure are as follows: character array salute for salutation, character arrays lname, fname and mname to store student’s name, integer array marks to store the marks in six subjects and character arrays result and class to store the examination result and class obtained, respectively. Other members are used to store the exam seat number, total marks and percentage marks. Note that the order of declaration of these members is quite logical.
c) Structure representing size-aware vector and matrix
As we know, built-in arrays in C language do not store information about the number of elements in it. Hence, a programmer has to be very careful while processing arrays, particularly during operations like insert and delete. This example overcomes this problem by declaring structures to represent a vector and a matrix that store the size information along with the array data.
First consider the declaration of structure vector that contains two data members: len to store array length (i. e., number of elements in it) and an integer array named data having 20 elements to store the elements of the vector.
struct vector { int len; int data[20]; }
Next, consider the declaration of structure matrix given below that contains three members: rows,cols and data. The rows and cols members represent the number of rows and columns in the matrix and a two-dimensional array named data is used to store the matrix elements. Note that the maximum matrix size is specified using symbolic constants Rows and COLS.
#define ROWS 10 #define COLS 10 struct matrix { int rows, cols; int data[ROWS] [COLS]; };
Initializing Structures Containing Arrays
To initialize a structure containing arrays, we combine the syntax for the initialization of a structure and an array. Thus, in the format for initialization of a structure given below
struct tag var= { expr1, expr2,… } ;
we replace the initialization expression corresponding to the array member with an array initializer list enclosed in curly braces. Also remember that an array of characters can be initialized using a string constant.
Consider the declaration of structure special_nos used to store a list of special numbers and the initialization of variable prime_nos given below.
struct special_nos { int n; char name[20); int data[20]; } ; struct special_nos prime_nos = { 10, "Prime numbers", {2, 3, 5, 7, 11, 13, 17, 19, 23, 29) };
Observe that name is initialized using a character string, whereas data is initialized using array initializer that contains the first ten prime numbers.
Example of Initializing Structures Containing Arrays
a) Initialize the information of an employee
struct employee { int emp_id; /* employee id */ char name[60]; /* person's name */ char dept[20]; /* work department */ char desg[20]; /* designation */ int leaves[l3]; /* number of leaves in each month */ el = {127, "D. K. Thakur", "Comp Engg", "Lecturer", {0, 1, 0, 3}}; struct employee me = {102, "S. Thakur", "M.C.A", "Professor", {0, 1, 2, 0) } ;
This example declares a structure employee to store information about an employee of an organization and initializes two variables named el and me. Observe that the three character arrays, name,dept and desg, are initialized using character strings. Also observe that since leaves[0] will be unused, the leaves array has 13 elements and the leave data is initialized for the first three months only.
b) Initialization of a size-aware unit matrix
Observe that the matrix size is stored in the structure variable followed by the array data. The uninitialized elements of array data will have zero value.
struct matrix unit3 = { 3, 3, /* rows, cols */ {{1, 0, 0}, /*data*/ {0, 1, 0}' {0, 0, 1} } } ;
Accessing Member Arrays
We can access the entire array member of a structure variable using the usual construct to access a structure member as shown below:
struct-var.arr-member
We can pass this array to a function. As an array is passed by address, we can use this array as an input-output parameter, i. e., to pass information to a function and to return the processed results back to the calling function.
Example of passing array members of a structure to a function
a) HSC result processing
Consider the following definition of a function that accepts an array of marks in six subjects and returns an integer value indicating the result: 1 if the result is pass and 0 otherwise.
/* determine HSC result */ int hsc_result(int marks[]) { int i; for(i = 0; i < 6; i++) { if (marks[i] < 35) return 0; /* fail */ } return 1; /* pass */ }
Let us declare a structure variable studl of type structure hsc_stud declared in Example as shown below.
struct hsc_stud stud1;
Now we can call the hsc_result function and set the result in the stud1.result array member as shown below.
if (hsc_result(studl.marks)) strcpy(studl.result, "Pass"); else strcpy(studl.result, "Fail");
Note that we can simplify this code using the conditional operator (?:) as follows:
strcpy(studl.result, hsc_result(studl.marks)? "Pass": "Fail");
Alternatively, we can define function hsc_result with one more parameter, a character array result,in which the result string can be returned to the calling function as shown below.
/* determine HSC result */ void hsc_result(int marks[], char result[]) { int i; for(i = 0; i < 6; i++) { if (marks[i] < 35) { strcpy(result, "Fail"); return; } } strcpy (result, "Pass"); }
This function can be called as
hsc_result(studl.marks, studl.result);
b) Using the mat_print function to print a size-aware matrix
Consider the initialization of a size-aware unit matrix named unit3 from Example declared using structure matrix. Also consider the prototype of function mat_print defined to print an integer matrix of specified size:
void mat_print(int a[] [10], int m, int n);
Note that the dimensions of the arrays (member data in struct matrix and parameter a in function mat_print) have the same number of columns (10). Thus, we can use the function mat_print to print matrix unit3 as shown below:
mat_print(unit3.data, unit3.rows, unit3.cols);
Accessing Elements of Member Arrays
An individual element of the member array of a structure variable can be accessed by writing array indexes after the construct used to access the member array. Thus, the elements of a one-dimensional array member can be accessed as shown below:
struct_var.arr_member [ expr ]
where expr is an expression that specifies the index of the array element being accessed. Similarly, the elements of a two-dimensional array member can be accessed using the expression given below.
struct_var.arr_member[expr1][expr2]
We can perform all operations on such an array element that we can perform on a scalar variable. Thus, we can use it in an expression, assign a value to it, pass it to a function and so on. When we use it in an expression, no additional parentheses are required as the dot operator and the array index operator have higher precedence that most other operators. For example, the prefix increment, postfix decrement, address-of operator and negation operators can be used with the elements of a one-dimensional array member of a structure as follows:
++ struct _var.arr_member [ expr ] struct_var.arr_member [ expr ] - - &struct_var.arr_member [ expr ] -struct_var.arr_member [ expr]
Example of accessing the elements of member array of a structure
a) Determine the total marks in the HSC examination
Assume that a structure variable named stud is defined using structure hsc_stud to represent the HSC examination data of a student as shown below.
struct hsc_stud stud;
The program segment given below illustrates how the elements of marks member array can be Accessed to determine the total marks in member stud.tot marks.
int i; stud.tot_marks = 0; for (i = 0; i < 6; i++) stud.tot_marks += stud.marks[i];
b) Read and print a size-aware matrix
Consider the program segment given below used to read and print a matrix m declared using structure matrix. Observe how the elements of array member data are accessed.
int main() { struct matrix m; int i, j; printf("Enter matrix size: "); scanf("%d %d", &m.rows, &m.cols); printf("Enter matrix elements:\n"); for(i = 0; i < m.rows; i++) { for(j = 0; j < m.cols; j++) scanf("%d", &m.data[i][j]); printf("\n"); } for(i = 0; i< m.rows; i++) { for(j = 0; j< m.cols; j++) printf("%4d ", m.data[i] [j]); printf("\n"); } }
Using Structure Containing Arrays as Function Parameter and Return Value
We can use an entire structure containing arrays as a function parameter. However, modifications to the structure parameter including the member arrays will not be reflected in the corresponding arguments in the called function. This might be confusing, particularly for a beginner, since arrays are passed by reference. However, understand that we are passing an entire structure (that contains arrays) and not an array. In addition, we can also return a structure containing arrays from a function.
As we already know, passing or returning a structure containing arrays will of course be very inefficient due to the involved structure copy operation.’ We should instead use the efficient pointer-to-structure mechanism. Finally, note that if we pass only the contained array member to a function, it will be passed by reference.
Example of Structure containing arrays as function parameter and return value
Consider the definition of function vector_print given below used to print a size-aware vector Declared using structure vector.
void vector_print(struct vector v) int i; for (i = 0; i < v.len; i++) printf("%d ", v.data[i]); printf ("\n");
Observe how the vector length (len)and the individual elements of the data array are accessed Within the function using the dot operator. This function can be called as shown below.
struct vector v = {5, {l, 3, 5, 7, 9}); vector_print(v);