1
📐 Array Basics — Declare, Initialise, Iterate
1-D array of ints — indexing, loops, finding min/max/sum
Basics
An array is a contiguous block of memory holding elements of the same type. Elements are accessed by zero-based index:
arr[0] is the first, arr[n-1] is the last. The array name itself is a pointer to the first element. Here we declare an int array, initialise it with a brace list, and compute the sum, minimum, and maximum in a single pass — the most common array pattern in any C program.
#include <stdio.h> int main() { int marks[] = { 85, 92, 78, 95, 60, 88, 74 }; int n = sizeof(marks) / sizeof(marks[0]); /* 7 */ int sum = 0, mn = marks[0], mx = marks[0]; for (int i = 0; i < n; i++) { sum += marks[i]; if (marks[i] < mn) mn = marks[i]; if (marks[i] > mx) mx = marks[i]; } printf("Marks : "); for (int i = 0; i < n; i++) printf("%d ", marks[i]); printf("\n"); printf("Count : %d\n", n); printf("Sum : %d\n", sum); printf("Average: %.2f\n", (double)sum / n); printf("Min : %d\n", mn); printf("Max : %d\n", mx); /* sizeof trick — always use it, never hard-code n */ printf("\nsizeof(marks) = %zu bytes\n", sizeof(marks)); printf("sizeof(int) = %zu bytes\n", sizeof(int)); return 0; }
Marks : 85 92 78 95 60 88 74 Count : 7 Sum : 572 Average: 81.71 Min : 60 Max : 95 sizeof(marks) = 28 bytes sizeof(int) = 4 bytes
memory layout — 7 ints, contiguous, zero-indexed
marks[0..6]
85
92
78
95
60
88
74
← 7 × 4 = 28 bytes
index
[0]
[1]
[2]
[3]
[4]
[5]
[6]
← base address + i×4
sizeof trick:
int n = sizeof(arr) / sizeof(arr[0]) always gives the correct element count — even if you add or remove values from the initialiser list. Never hard-code n = 7; let the compiler count for you.example 2
2
🧱 Struct Basics — Group Related Fields
Define a struct, create instances, access members with the dot operator
Struct
A struct bundles variables of different types under one name. Unlike an array — which holds elements of the same type — a struct lets you group a name, an age, a GPA, and a boolean together as a single logical unit. Members are accessed with the dot operator (
.) for a variable, or the arrow operator (->) for a pointer. Here we build a simple Student struct and display its fields.
#include <stdio.h> #include <string.h> typedef struct { char name[30]; int roll; float gpa; int active; /* 1 = enrolled, 0 = alumni */ } Student; void printStudent(const Student *s) { printf("Roll %-4d | %-20s | GPA %.2f | %s\n", s->roll, s->name, s->gpa, s->active ? "Enrolled" : "Alumni"); } int main() { /* Initialise with brace list */ Student s1 = { "Ananya Sharma", 101, 8.9f, 1 }; /* Initialise by field name (designated initialiser) */ Student s2 = { .name = "Rohan Verma", .roll = 102, .gpa = 7.6f, .active = 1 }; /* Assign fields one by one */ Student s3; strcpy(s3.name, "Priya Singh"); s3.roll = 103; s3.gpa = 9.1f; s3.active = 0; printf("%-8s %-20s %s %s\n", "Roll", "Name", "GPA", "Status"); printf("%s\n", "------------------------------------------------------"); printStudent(&s1); printStudent(&s2); printStudent(&s3); printf("\nsizeof(Student) = %zu bytes\n", sizeof(Student)); return 0; }
Roll Name GPA Status ------------------------------------------------------ Roll 101 | Ananya Sharma | GPA 8.90 | Enrolled Roll 102 | Rohan Verma | GPA 7.60 | Enrolled Roll 103 | Priya Singh | GPA 9.10 | Alumni sizeof(Student) = 40 bytes
Three ways to initialise a struct: brace list (order matters), designated initialisers (C99, order-independent, self-documenting), or field-by-field assignment. Prefer designated initialisers for structs with more than 3 fields — they're immune to field reordering bugs.
example 3
3
📋 Array of Structs — Classlist
Put multiple Student structs in an array — sort, search, and display
Array of Structs
The most common real-world pattern: an array of structs. Each element is a complete struct; you access individual fields with
arr[i].field. Here we store five students, find the topper (highest GPA), count enrolled vs alumni, and print a formatted table — exactly the kind of record-processing loop that appears in every database, game engine, or server.
#include <stdio.h> typedef struct { char name[20]; int roll; float gpa; int active; } Student; int main() { Student cls[] = { { "Ananya", 101, 8.9f, 1 }, { "Rohan", 102, 7.6f, 1 }, { "Priya", 103, 9.1f, 0 }, { "Karan", 104, 8.3f, 1 }, { "Sunita", 105, 6.8f, 0 }, }; int n = sizeof(cls) / sizeof(cls[0]); printf("%-6s %-12s %5s %s\n", "Roll", "Name", "GPA", "Status"); printf("%s\n", "--------------------------------------"); int topIdx = 0, enrolled = 0; for (int i = 0; i < n; i++) { printf("%-6d %-12s %5.2f %s\n", cls[i].roll, cls[i].name, cls[i].gpa, cls[i].active ? "Enrolled" : "Alumni"); if (cls[i].gpa > cls[topIdx].gpa) topIdx = i; if (cls[i].active) enrolled++; } printf("%s\n", "--------------------------------------"); printf("Topper : %s (GPA %.2f)\n", cls[topIdx].name, cls[topIdx].gpa); printf("Enrolled : %d / %d\n", enrolled, n); return 0; }
Roll Name GPA Status -------------------------------------- 101 Ananya 8.90 Enrolled 102 Rohan 7.60 Enrolled 103 Priya 9.10 Alumni 104 Karan 8.30 Enrolled 105 Sunita 6.80 Alumni -------------------------------------- Topper : Priya (GPA 9.10) Enrolled : 3 / 5
Access pattern:
cls[i].gpa — array index first, then dot-member. This scales to thousands of records. The same loop pattern (find max, count matching) is used in every data-processing task: leaderboards, inventory reports, log analysis, and more.example 4
4
🏠 Nested Structs — Address Inside Student
A struct whose field is itself another struct — two levels of nesting
Nested Struct
Structs can contain other structs as fields — nested structs. An
Address struct (city, state, pin) is embedded directly inside Student. You navigate with chained dots: s.addr.city. This keeps related data logically grouped and avoids a flat list of twenty loosely related fields. It is also how C libraries represent complex entities — a sockaddr contains a nested in_addr, for example.
#include <stdio.h> #include <string.h> typedef struct { char city[20]; char state[20]; int pin; } Address; typedef struct { char name[25]; int roll; Address addr; /* nested struct */ float gpa; } Student; void printStudent(const Student *s) { printf("Name : %s (Roll %d)\n", s->name, s->roll); printf("GPA : %.2f\n", s->gpa); printf("Addr : %s, %s — %d\n\n", s->addr.city, s->addr.state, s->addr.pin); } int main() { Student s1 = { .name = "Ananya Sharma", .roll = 101, .gpa = 8.9f, .addr = { .city = "Haridwar", .state = "Uttarakhand", .pin = 249401 } }; Student s2; strcpy(s2.name, "Rohan Verma"); s2.roll = 102; s2.gpa = 7.6f; strcpy(s2.addr.city, "Dehradun"); /* chained dot access */ strcpy(s2.addr.state, "Uttarakhand"); s2.addr.pin = 248001; printf("--- Student Records ---\n\n"); printStudent(&s1); printStudent(&s2); printf("sizeof(Address) = %zu\n", sizeof(Address)); printf("sizeof(Student) = %zu\n", sizeof(Student)); return 0; }
--- Student Records --- Name : Ananya Sharma (Roll 101) GPA : 8.90 Addr : Haridwar, Uttarakhand — 249401 Name : Rohan Verma (Roll 102) GPA : 7.60 Addr : Dehradun, Uttarakhand — 248001 sizeof(Address) = 44 sizeof(Student) = 76
Chained dot access:
s.addr.city — as many levels deep as needed. With pointers: p->addr.city (arrow for the outermost pointer, dot for everything nested inside). This pattern is used in OS structs like struct stat, struct tm, and all network address types.example 5
5
🔀 Struct + Union — Sensor Reading
A sensor can be temperature, humidity, or pressure — one struct covers all three
Struct + Union
This is where all three concepts lock together. A
Sensor struct has a type tag (an enum), a name (array of char), and a union holding the actual reading. Temperature is a float. Humidity is a float percentage. Pressure is a double in Pascals. The union means we never waste memory on unused fields — each sensor object is exactly as big as its largest possible reading.
#include <stdio.h> typedef enum { TEMP, HUMIDITY, PRESSURE } SensorType; typedef struct { char label[16]; SensorType type; union { float celsius; /* for TEMP */ float percent; /* for HUMIDITY */ double pascals; /* for PRESSURE */ } reading; } Sensor; void printSensor(const Sensor *s) { printf("%-14s", s->label); switch (s->type) { case TEMP: printf("Temperature : %.1f °C\n", s->reading.celsius); break; case HUMIDITY: printf("Humidity : %.1f %%\n", s->reading.percent); break; case PRESSURE: printf("Pressure : %.0f Pa\n", s->reading.pascals); break; } } int main() { Sensor sensors[] = { { "Roof", TEMP, { .celsius = 38.5f } }, { "Lab", HUMIDITY, { .percent = 64.2f } }, { "Basement",PRESSURE, { .pascals = 101325.0 } }, { "Outdoor", TEMP, { .celsius = 42.0f } }, { "Kitchen", HUMIDITY, { .percent = 75.0f } }, }; int n = sizeof(sensors) / sizeof(sensors[0]); printf("--- Sensor Dashboard ---\n"); for (int i = 0; i < n; i++) printSensor(&sensors[i]); printf("\nsizeof(Sensor) = %zu bytes\n", sizeof(Sensor)); return 0; }
--- Sensor Dashboard --- Roof Temperature : 38.5 °C Lab Humidity : 64.2 % Basement Pressure : 101325 Pa Outdoor Temperature : 42.0 °C Kitchen Humidity : 75.0 % sizeof(Sensor) = 32 bytes
Sensor memory layout — tag + label array + union share one struct
label[16]
char[16]
← 16 bytes
type (enum)
int
← 4 bytes
reading (union)
double (8B)
← largest member wins
Always match the tag to the union member you read. If
type == TEMP, read reading.celsius. Reading reading.pascals when the tag says TEMP gives garbage — the raw bytes are reinterpreted as a double. The tag is your contract.example 6
6
📬 Passing Structs to Functions
Pass by value vs pass by pointer — see the difference with a swap example
Functions
Structs can be passed to functions by value (a full copy is made — changes don't affect the original) or by pointer (only the address is passed — changes affect the original). For large structs, always prefer pointer: it avoids copying dozens of bytes on every call. Here we demonstrate both — a
display function takes a const pointer (read-only), and a swap function takes two pointers to exchange two struct variables.
#include <stdio.h> typedef struct { char name[20]; int score; } Player; /* Pass by const pointer — no copy, read-only */ void display(const Player *p) { printf(" %-15s %d\n", p->name, p->score); } /* Pass by value — gets its own copy, original unchanged */ void addBonus(Player p, int bonus) { p.score += bonus; /* only modifies the local copy */ printf(" Inside addBonus: %s -> %d\n", p.name, p.score); } /* Pass by pointer — modifies the original */ void swap(Player *a, Player *b) { Player tmp = *a; *a = *b; *b = tmp; } int main() { Player p1 = { "Karan", 850 }; Player p2 = { "Sunita", 920 }; printf("Before:\n"); display(&p1); display(&p2); printf("\naddBonus (pass by value):\n"); addBonus(p1, 100); printf(" After call: p1.score still = %d\n", p1.score); printf("\nswap (pass by pointer):\n"); swap(&p1, &p2); printf("After swap:\n"); display(&p1); display(&p2); return 0; }
Before: Karan 850 Sunita 920 addBonus (pass by value): Inside addBonus: Karan -> 950 After call: p1.score still = 850 swap (pass by pointer): After swap: Sunita 920 Karan 850
Rule of thumb: read-only access →
const Struct *p. Modifying the struct → Struct *p. Returning a new struct from a function → return by value (compilers optimise this with RVO). Never pass large structs by value in a loop — you copy the entire struct on every iteration.example 7
7
🎓 Student Records System — Sort by GPA
Array of structs + bubble sort + linear search — a complete mini DBMS
Mini App
Everything so far combined into a mini student records system. We store ten students in an array of structs, sort them by GPA using bubble sort (swapping entire struct objects), search by roll number using linear search, and print a grade letter for each. This is the archetype for small file-less databases in C — the same logic powers embedded systems, exam results processors, and small admin tools.
#include <stdio.h> #include <string.h> typedef struct { int roll; char name[20]; float gpa; } Student; char grade(float g) { if (g >= 9.0f) return 'A'; if (g >= 8.0f) return 'B'; if (g >= 7.0f) return 'C'; if (g >= 6.0f) return 'D'; return 'F'; } /* Bubble sort — descending GPA */ void sortByGPA(Student *arr, int n) { for (int i = 0; i < n-1; i++) for (int j = 0; j < n-i-1; j++) if (arr[j].gpa < arr[j+1].gpa) { Student tmp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = tmp; } } /* Linear search by roll */ Student* findByRoll(Student *arr, int n, int roll) { for (int i = 0; i < n; i++) if (arr[i].roll == roll) return &arr[i]; return NULL; } int main() { Student cls[] = { {101,"Ananya",8.9f},{102,"Rohan",7.6f}, {103,"Priya",9.4f},{104,"Karan",6.2f}, {105,"Sunita",8.1f},{106,"Amit",5.7f}, {107,"Divya",9.0f},{108,"Vijay",7.3f}, {109,"Meena",8.5f},{110,"Arjun",6.8f}, }; int n = sizeof(cls)/sizeof(cls[0]); sortByGPA(cls, n); printf("Rank %-6s %-12s GPA Grade\n","Roll","Name"); printf("%s\n","------------------------------------------"); for (int i = 0; i < n; i++) printf(" %2d %-6d %-12s %.1f %c\n", i+1, cls[i].roll, cls[i].name, cls[i].gpa, grade(cls[i].gpa)); printf("\nSearch roll 106: "); Student *found = findByRoll(cls, n, 106); if (found) printf("%s GPA %.1f Grade %c\n", found->name, found->gpa, grade(found->gpa)); return 0; }
Rank Roll Name GPA Grade ------------------------------------------ 1 103 Priya 9.4 A 2 107 Divya 9.0 A 3 101 Ananya 8.9 B 4 109 Meena 8.5 B 5 105 Sunita 8.1 B 6 102 Rohan 7.6 C 7 108 Vijay 7.3 C 8 110 Arjun 6.8 D 9 104 Karan 6.2 D 10 106 Amit 5.7 F Search roll 106: Amit GPA 5.7 Grade F
Swapping structs is just
tmp = a; a = b; b = tmp; The compiler copies the entire struct in each assignment. For large structs (>100 bytes), swap indices or use an array of pointers to structs instead — you then swap only the 8-byte pointer, not the whole struct.example 8
8
🛒 Inventory System — Struct + Union + Array
Products can be weighed, counted, or sold by volume — one array covers all
Real World
A practical inventory: products come in three sale types — by weight (kg), by count (units), or by volume (litres). Each needs different data. A tagged union inside the
Product struct holds exactly the right field for each type. An array of Product covers all three types in one list. A single totalValue() function computes stock value for any product regardless of type.
#include <stdio.h> typedef enum { BY_WEIGHT, BY_COUNT, BY_VOLUME } SaleType; typedef struct { char name[20]; float pricePerUnit; /* per kg, per unit, per litre */ SaleType saleType; union { float kg; /* BY_WEIGHT */ int units; /* BY_COUNT */ float litres; /* BY_VOLUME */ } stock; } Product; float totalValue(const Product *p) { switch (p->saleType) { case BY_WEIGHT: return p->pricePerUnit * p->stock.kg; case BY_COUNT: return p->pricePerUnit * p->stock.units; case BY_VOLUME: return p->pricePerUnit * p->stock.litres; } return 0; } void printProduct(const Product *p) { const char *units[] = { "kg", "units", "litres" }; float qty; switch(p->saleType){ case BY_WEIGHT: qty=p->stock.kg; break; case BY_COUNT: qty=p->stock.units; break; case BY_VOLUME: qty=p->stock.litres; break; default: qty=0; } printf("%-14s Rs%6.2f/%-6s stock:%6.1f value: Rs%.2f\n", p->name, p->pricePerUnit, units[p->saleType], qty, totalValue(p)); } int main() { Product inv[] = { { "Rice", 55.0f, BY_WEIGHT, { .kg = 200.5f } }, { "Pen", 12.0f, BY_COUNT, { .units = 500 } }, { "Cooking Oil", 130.0f, BY_VOLUME, { .litres = 80.0f } }, { "Sugar", 44.0f, BY_WEIGHT, { .kg = 150.0f } }, { "Notebook", 60.0f, BY_COUNT, { .units = 300 } }, }; int n = sizeof(inv)/sizeof(inv[0]); printf("%-14s %-18s %-12s %s\n","Product","Price/Unit","Stock","Value"); printf("%s\n","--------------------------------------------------------------"); float grandTotal = 0; for (int i = 0; i < n; i++) { printProduct(&inv[i]); grandTotal += totalValue(&inv[i]); } printf("%s\n","--------------------------------------------------------------"); printf("%-44s TOTAL: Rs%.2f\n", "", grandTotal); return 0; }
Product Price/Unit Stock Value
--------------------------------------------------------------
Rice Rs 55.00/kg stock: 200.5 value: Rs11027.50
Pen Rs 12.00/units stock: 500.0 value: Rs6000.00
Cooking Oil Rs130.00/litres stock: 80.0 value: Rs10400.00
Sugar Rs 44.00/kg stock: 150.0 value: Rs6600.00
Notebook Rs 60.00/units stock: 300.0 value: Rs18000.00
--------------------------------------------------------------
TOTAL: Rs52027.50The union saves memory here because each product only ever stores one quantity type. Without a union, the struct would need
float kg, int units, float litres — all three fields, all the time — wasting 8 bytes per product. With a union, only the largest field is allocated, and the right one is always in use.example 9
9
🗺️ 2D Array of Structs — Seating Chart
A 2-D grid of seat structs — row/col access, search by name, count empty seats
2D Arrays
A 2-D array of structs — each element is a
Seat struct; the whole grid represents a cinema hall. Access a seat with hall[row][col].field. The grid makes it natural to print a visual layout, search across all seats for a name, and count vacant seats — the exact same operations a real booking system performs.
#include <stdio.h> #include <string.h> #define ROWS 4 #define COLS 6 typedef struct { int booked; char guest[15]; } Seat; void book(Seat hall[ROWS][COLS], int r, int c, const char *name) { if (!hall[r][c].booked) { hall[r][c].booked = 1; strncpy(hall[r][c].guest, name, 14); } else { printf("R%dC%d already booked!\n", r, c); } } void printHall(Seat hall[ROWS][COLS]) { printf(" "); for (int c = 0; c < COLS; c++) printf(" C%d ", c+1); printf("\n"); for (int r = 0; r < ROWS; r++) { printf("R%d ", r+1); for (int c = 0; c < COLS; c++) printf("[%s] ", hall[r][c].booked ? "XX" : " "); printf("\n"); } } int main() { Seat hall[ROWS][COLS]; /* zero-init all seats */ for (int r = 0; r < ROWS; r++) for (int c = 0; c < COLS; c++) hall[r][c].booked = 0; book(hall, 0, 0, "Ananya"); book(hall, 0, 1, "Rohan"); book(hall, 1, 3, "Priya"); book(hall, 2, 5, "Karan"); book(hall, 3, 2, "Sunita"); book(hall, 0, 0, "Duplicate"); /* conflict */ printf("--- Seating Chart ---\n"); printHall(hall); int empty = 0; for (int r = 0; r < ROWS; r++) for (int c = 0; c < COLS; c++) if (!hall[r][c].booked) empty++; printf("\nBooked: %d | Empty: %d | Total: %d\n", ROWS*COLS - empty, empty, ROWS*COLS); printf("\n--- Guest list ---\n"); for (int r = 0; r < ROWS; r++) for (int c = 0; c < COLS; c++) if (hall[r][c].booked) printf(" R%d-C%d : %s\n", r+1, c+1, hall[r][c].guest); return 0; }
R0C0 already booked!
--- Seating Chart ---
C1 C2 C3 C4 C5 C6
R1 [XX] [XX] [ ] [ ] [ ] [ ]
R2 [ ] [ ] [ ] [XX] [ ] [ ]
R3 [ ] [ ] [ ] [ ] [ ] [XX]
R4 [ ] [ ] [XX] [ ] [ ] [ ]
Booked: 5 | Empty: 19 | Total: 24
--- Guest list ---
R1-C1 : Ananya
R1-C2 : Rohan
R2-C4 : Priya
R3-C6 : Karan
R4-C3 : Sunita2-D array access pattern:
hall[row][col].field — two indices, then the dot. In memory it is still a flat contiguous block — element [r][c] lives at offset (r * COLS + c) * sizeof(Seat). Pass a 2-D array to a function as Seat arr[][COLS] — the column count must be known at compile time.example 10
10
🏗️ Full App — Hospital Patient Registry
Arrays + nested structs + tagged union + sort + search — one complete C program
Complete App
Every concept from Examples 1–9 in one real application. A hospital patient registry stores patients with nested struct contact info, a tagged union for diagnosis data (inpatient needs a bed number and ward; outpatient needs a clinic slot string), an array to hold all records, and functions to sort by name and search by ID. The design is extensible: add a new patient type by touching exactly four places.
#include <stdio.h> #include <string.h> typedef enum { INPATIENT, OUTPATIENT } PatientType; typedef struct { char phone[12]; char city[20]; } Contact; /* nested struct */ typedef struct { int id; char name[25]; int age; Contact contact; /* nested struct */ PatientType type; union { /* tagged union */ struct { int bedNo; char ward[15]; } inp; struct { char slot[20]; } outp; } care; } Patient; void printPatient(const Patient *p) { printf("ID:%04d %-20s Age:%3d Ph:%-12s City:%-12s\n", p->id, p->name, p->age, p->contact.phone, p->contact.city); if (p->type == INPATIENT) printf(" [INPATIENT] Bed:%d Ward:%s\n", p->care.inp.bedNo, p->care.inp.ward); else printf(" [OUTPATIENT] Slot:%s\n", p->care.outp.slot); } /* Sort by name (bubble sort) */ void sortByName(Patient *arr, int n) { for (int i = 0; i < n-1; i++) for (int j = 0; j < n-i-1; j++) if (strcmp(arr[j].name, arr[j+1].name) > 0) { Patient t = arr[j]; arr[j] = arr[j+1]; arr[j+1] = t; } } /* Search by ID */ Patient* findByID(Patient *arr, int n, int id) { for (int i = 0; i < n; i++) if (arr[i].id == id) return &arr[i]; return NULL; } int main() { Patient reg[] = { { 1003, "Meena Gupta", 45, { "9876543210", "Haridwar" }, INPATIENT, { .inp = { 12, "Cardiology" } } }, { 1001, "Arjun Rawat", 32, { "9123456789", "Dehradun" }, OUTPATIENT, { .outp = { "Mon 10:00am" } } }, { 1004, "Sunita Devi", 60, { "9988776655", "Rishikesh" }, INPATIENT, { .inp = { 7, "Ortho" } } }, { 1002, "Aditya Kumar", 28, { "9001122334", "Roorkee" }, OUTPATIENT, { .outp = { "Wed 3:30pm" } } }, { 1005, "Priya Negi", 37, { "9765432100", "Mussoorie" }, INPATIENT, { .inp = { 22, "Neurology" } } }, }; int n = sizeof(reg) / sizeof(reg[0]); printf("=== Hospital Registry (sorted by name) ===\n\n"); sortByName(reg, n); for (int i = 0; i < n; i++) { printPatient(®[i]); printf("\n"); } printf("--- Search ID 1004 ---\n"); Patient *f = findByID(reg, n, 1004); if (f) printPatient(f); int inp=0, outp=0; for (int i=0; i<n; i++) (reg[i].type==INPATIENT ? inp : outp)++; printf("\nInpatients: %d Outpatients: %d\n", inp, outp); return 0; }
=== Hospital Registry (sorted by name) ===
ID:1002 Aditya Kumar Age: 28 Ph:9001122334 City:Roorkee
[OUTPATIENT] Slot:Wed 3:30pm
ID:1001 Arjun Rawat Age: 32 Ph:9123456789 City:Dehradun
[OUTPATIENT] Slot:Mon 10:00am
ID:1003 Meena Gupta Age: 45 Ph:9876543210 City:Haridwar
[INPATIENT] Bed:12 Ward:Cardiology
ID:1005 Priya Negi Age: 37 Ph:9765432100 City:Mussoorie
[INPATIENT] Bed:22 Ward:Neurology
ID:1004 Sunita Devi Age: 60 Ph:9988776655 City:Rishikesh
[INPATIENT] Bed:7 Ward:Ortho
--- Search ID 1004 ---
ID:1004 Sunita Devi Age: 60 Ph:9988776655 City:Rishikesh
[INPATIENT] Bed:7 Ward:Ortho
Inpatients: 3 Outpatients: 2All 5 patterns in one program:
Contact as nested struct · PatientType enum as tag · union care with two inner structs · Patient reg[] as array of structs · sortByName and findByID as the canonical data-processing functions. Add a new patient type (e.g. EMERGENCY) by adding one enum value, one struct in the union, and one branch in printPatient — nothing else changes.checklist
- Ex 1 —
sizeof(arr) / sizeof(arr[0])gives the element count. Arrays are zero-indexed, contiguous, same type. - Ex 2 — Struct groups different types. Dot operator for variables, arrow for pointers. Three init styles: brace list, designated, field-by-field.
- Ex 3 — Array of structs:
arr[i].field. One loop can sort, search, count, and aggregate over all records. - Ex 4 — Nested struct:
s.outer.innerchained dots. With pointer:p->outer.inner. sizeof(outer) includes sizeof(inner). - Ex 5 — Struct + union: tag enum tells you which union member is valid. Read only the member matching the tag.
- Ex 6 — Pass struct by
const *for reading (no copy). Pass by*to modify. Pass by value for a safe local copy. - Ex 7 — Bubble sort swaps entire struct objects. For big structs, swap pointers or indices instead to avoid copying.
- Ex 8 — Tagged union inside struct for inventory variants.
totalValue()dispatches on tag — one function handles all product types. - Ex 9 — 2-D array of structs:
arr[row][col].field. Pass to functions asSeat arr[][COLS]— column count required. - Ex 10 — Full app: nested struct + enum tag + tagged union + array + sort + search. Add a new variant in 4 places only.