Programming Language & Its Applications — Pointers, Structure and Data Files in C, NEC licence examination syllabus (Nepal Engineering Council).
One record is a struct; a table of records is an array of structs — and that is a database in miniature.
Almost every real program manages a collection of records: students in a class, items in an inventory, employees on a payroll. In C that is an array of structs, laid out contiguously with each element the full struct size. Understanding the memory arithmetic lets you compute addresses, and understanding the alternative layout (arrays of separate fields) explains a performance idea that turns up in graphics and data engineering.
SELECT * FROM students ORDER BY marks DESC, PostgreSQL does what qsort with by_marks_desc does here, with more machinery around it. The AoS-vs-SoA section at the end is why analytics engines like DuckDB and ClickHouse beat row-stores by orders of magnitude on aggregate queries. Search "columnar storage vs row storage".#include <stdio.h>
#include <string.h>
typedef struct {
int roll;
char name[20];
float marks;
} Student;
int main(void) {
Student cls[5] = {
{101, "Ram Bahadur", 87.5f},
{102, "Sita Devi", 91.0f},
{103, "Hari Prasad", 76.5f},
{104, "Gita Kumari", 68.0f},
{105, "Bikash Thapa", 94.5f}
};
int n = sizeof cls / sizeof cls[0];
printf("sizeof(Student)=%zu array=%zu n=%d\n",
sizeof(Student), sizeof cls, n);
printf("\n%-6s %-16s %7s\n", "Roll", "Name", "Marks");
printf("-------------------------------\n");
float total = 0;
for (int i = 0; i < n; i++) {
printf("%-6d %-16s %7.1f\n",
cls[i].roll, cls[i].name, cls[i].marks);
total += cls[i].marks;
}
printf("-------------------------------\n");
printf("%-23s %7.2f\n", "Class average", total/n);
/* addresses show the stride */
printf("\n&cls[0]=%p\n&cls[1]=%p (stride %ld bytes)\n",
(void*)&cls[0], (void*)&cls[1],
(char*)&cls[1] - (char*)&cls[0]);
return 0;
}
Output:
sizeof(Student)=28 array=140 n=5
Roll Name Marks
-------------------------------
101 Ram Bahadur 87.5
102 Sita Devi 91.0
103 Hari Prasad 76.5
104 Gita Kumari 68.0
105 Bikash Thapa 94.5
-------------------------------
Class average 83.50
&cls[0]=0x7ffd1a2b3400
&cls[1]=0x7ffd1a2b341c (stride 28 bytes)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct { int roll; char name[20]; float marks; } Student;
/* linear search by roll: O(n) */
int find_by_roll(const Student *a, int n, int roll) {
for (int i = 0; i < n; i++) if (a[i].roll == roll) return i;
return -1;
}
/* binary search needs the array SORTED by roll: O(log n) */
int bsearch_roll(const Student *a, int n, int roll) {
int lo = 0, hi = n - 1;
while (lo <= hi) {
int mid = lo + (hi - lo)/2; /* no overflow */
if (a[mid].roll == roll) return mid;
if (a[mid].roll < roll) lo = mid + 1;
else hi = mid - 1;
}
return -1;
}
/* comparators for qsort */
int by_marks_desc(const void *x, const void *y) {
float d = ((const Student*)y)->marks
- ((const Student*)x)->marks;
return (d > 0) - (d < 0); /* safe float compare */
}
int by_name(const void *x, const void *y) {
return strcmp(((const Student*)x)->name,
((const Student*)y)->name);
}
int main(void) {
Student cls[5] = {
{103,"Hari",76.5f}, {101,"Ram",87.5f},
{105,"Bikash",94.5f},{102,"Sita",91.0f},
{104,"Gita",68.0f}
};
int n = 5;
int i = find_by_roll(cls, n, 104);
printf("linear: roll 104 -> %s\n",
i >= 0 ? cls[i].name : "not found");
qsort(cls, n, sizeof cls[0], by_marks_desc);
printf("\nRank by marks:\n");
for (int k = 0; k < n; k++)
printf(" %d. %-8s %.1f\n", k+1, cls[k].name,
cls[k].marks);
qsort(cls, n, sizeof cls[0], by_name);
printf("\nAlphabetical: ");
for (int k = 0; k < n; k++) printf("%s ", cls[k].name);
printf("\n");
return 0;
}
Output:
linear: roll 104 -> Gita
Rank by marks:
1. Bikash 94.5
2. Sita 91.0
3. Ram 87.5
4. Hari 76.5
5. Gita 68.0
Alphabetical: Bikash Gita Hari Ram Sita
#include <stdio.h>
typedef struct { int dd, mm, yyyy; } Date;
typedef struct {
int id;
char name[24];
Date joined; /* a struct INSIDE a struct */
float salary;
} Employee;
void print_emp(const Employee *e) {
printf("%-4d %-14s %02d/%02d/%4d Rs %9.2f\n",
e->id, e->name,
e->joined.dd, e->joined.mm, e->joined.yyyy,
e->salary);
}
int main(void) {
Employee staff[3] = {
{1, "Ram Shrestha", {15, 3, 2019}, 68000.0f},
{2, "Sita Adhikari", { 1, 7, 2021}, 54500.0f},
{3, "Hari Magar", {22,11, 2017}, 81250.0f}
};
printf("%-4s %-14s %-12s %12s\n",
"ID","Name","Joined","Salary");
float payroll = 0;
for (int i = 0; i < 3; i++) {
print_emp(&staff[i]);
payroll += staff[i].salary;
}
printf("\nMonthly payroll: Rs %.2f\n", payroll);
printf("Annual payroll : Rs %.2f\n", payroll * 12);
/* nested access chains the dot operator */
printf("staff[2] joined in year %d\n",
staff[2].joined.yyyy);
return 0;
}
Output:
ID Name Joined Salary
1 Ram Shrestha 15/03/2019 Rs 68000.00
2 Sita Adhikari 01/07/2021 Rs 54500.00
3 Hari Magar 22/11/2017 Rs 81250.00
Monthly payroll: Rs 203750.00
Annual payroll : Rs 2445000.00
staff[2] joined in year 2017
&arr[i].member = base + i×sizeof(struct) + offsetof(member) is a standard numerical — practise it with padding included. Expect a full program question: read n student records, compute totals and averages, sort by marks, print a table. Know that qsort needs sizeof of one element and a comparator, and why comparing floats by casting the difference to int is wrong.Create a free account to tick topics off, take notes as you read, watch the video lessons and get a day-by-day study plan built around your exam date.
Loading…