Part 1: Defining a Structure (A Quick Review)
As we saw in the "Structures" note, "defining" a structure means creating the blueprint for a new, custom data type. This definition doesn't create any variables or use any memory; it just tells the compiler what your new type looks like.
Method 1: The Basic Way
This method uses the struct keyword every time you create a variable.
// This is the blueprint
struct Student {
char name[50];
int roll;
float gpa;
};
int main() {
// You must use 'struct Student' to create a variable
struct Student s1;
return 0;
}
Method 2: The typedef Way (Preferred)
This method uses typedef to create a simple, one-word alias (like Student) for your new type. This is much cleaner and is the standard way to define structures.
// This blueprint also creates a nickname 'Student'
typedef struct {
char name[50];
int roll;
float gpa;
} Student; // 'Student' is now an alias for the struct
int main() {
// Now you can just use 'Student' like a built-in type
Student s1;
return 0;
}
For the rest of this note, we will use the clean typedef method.
Part 2: Array of Structures
The Core Idea: A Collection of Structs
You already know what an array of ints is:
int grades[60];
This creates 60 "slots" in memory, where each slot is just big enough to hold one int.
An array of structures is the exact same concept, but each "slot" is big enough to hold one *entire structure*.
Student class_roll[60];
This creates 60 "slots" in memory. Each slot (class_roll[0], class_roll[1], etc.) is a complete Student variable, containing its *own* name, roll, and gpa.
Analogy: Filing Cabinet
Think of an array of ints as a row of 60 small mailboxes. Each mailbox (element) can hold only one thing (a number).
Think of an array of structs as a row of 60 large filing cabinets. Each filing cabinet (element) contains *multiple drawers* (members) labeled "name", "roll", and "gpa".
Declaration and Memory
When you declare an array of
structures, the computer allocates a single, continuous block of memory large
enough to hold *all* of them.
If one Student struct takes 60 bytes (e.g., 50
for name + 4 for roll + 4 for gpa + 2 padding), then `Student class_roll[3];`
would allocate `3 * 60 = 180` bytes.
Accessing Elements and Members
This is the most important part. You combine array syntax ([]) with struct syntax (.).
The Golden Rule for Accessing:
array_name[index].member_name
First, you use the [index] to select *which filing cabinet* (which element) you want from the array. Then, you use the .member_name to select *which drawer* (which member) you want from *that specific cabinet*.
Example:
// Create an array to hold 3 Student structs
Student class_roll[3];
// --- Accessing the FIRST student (index 0) ---
// Set the 'roll' member of the element at index 0
class_roll[0].roll = 101;
// Set the 'gpa' member of the element at index 0
class_roll[0].gpa = 3.8;
// Set the 'name' member of the element at index 0
strcpy(class_roll[0].name, "Alice");
// --- Accessing the SECOND student (index 1) ---
class_roll[1].roll = 102;
strcpy(class_roll[1].name, "Bob");
// --- Printing the data ---
printf("Student 1's Name: %s\n", class_roll[0].name);
printf("Student 2's Name: %s\n", class_roll[1].name);
Initialization
You can initialize an array of structures using nested curly braces. Each inner set of braces {...} initializes one element (one struct) in the array.
// Initialize an array of 2 students
Student class_roll[2] = {
{ "Alice", 101, 3.8 }, // Element 0: {name, roll, gpa}
{ "Bob", 102, 3.5 } // Element 1: {name, roll, gpa}
};
Complete Example: Student Database using a Loop
The most common use of an array of structures is to loop through it to read or write data. This program creates a small database for 3 students.
#include <stdio.h>
#include <string.h>
// 1. Define the 'Student' type using typedef
typedef struct {
char name[50];
int roll;
float gpa;
} Student;
int main() {
int num_students = 3;
// 2. Declare an array capable of holding 3 Student structs
Student classDB[num_students];
int i;
// --- PART A: Loop to get input ---
printf("--- Enter Student Details ---\n");
for (i = 0; i < num_students; i++) {
printf("Student %d\n", i + 1);
printf(" Enter Name: ");
// Access the 'name' member of the i-th element
scanf("%s", classDB[i].name);
printf(" Enter Roll: ");
// Access the 'roll' member of the i-th element
scanf("%d", &classDB[i].roll);
printf(" Enter GPA: ");
// Access the 'gpa' member of the i-th element
scanf("%f", &classDB[i].gpa);
}
// --- PART B: Loop to print output ---
printf("\n--- Student Records ---\n");
for (i = 0; i < num_students; i++) {
printf("Record %d:\n", i + 1);
printf(" Name: %s\n", classDB[i].name);
printf(" Roll: %d\n", classDB[i].roll);
printf(" GPA: %.2f\n", classDB[i].gpa);
}
return 0;
}
Note on scanf("%s", ...): Using scanf("%s", classDB[i].name) is simple but can only read single words (it stops at a space). For real programs, you would use fgets() to read full names, but this example is kept simple.