15 experiments, each set out as 1. Question, 2. Aim, 3. Steps, 4. Programme, 5. Execution and Results.
Every program is in labs/course-2-c/ as a
compilable .c file. All fifteen compile under gcc -Wall -Wextra with no
warnings and were run against the sample inputs below. Each was run on a terminal, with its
sample input typed at its prompts, so the output under 5. Execution and Results is what you
would see, the typed values included.
Re-run the whole set:
bash tools/data-science/run_c_labs.sh
Compile and run one:
gcc -Wall -Wextra -o armstrong labs/course-2-c/01_armstrong.c
./armstrong
| # | Experiment | File | Sample input | Key idea |
|---|---|---|---|---|
| 1 | Armstrong number | 01_armstrong.c |
153 |
digit extraction with % 10 and / 10 |
| 2 | Sum of digits | 02_sum_of_digits.c |
12345 |
same peeling loop |
| 3 | Fibonacci series | 03_fibonacci.c |
10 |
iterative, three variables |
| 4 | Largest and smallest | 04_largest_smallest.c |
5 then 23 7 91 4 56 |
seed with a[0], not 0 |
| 5 | Swap by value and address | 05_swap_value_address.c |
10 20 |
the parameter-passing demo |
| 6 | String operations | 06_string_operations.c |
Hello World |
library and hand-written versions |
| 7 | Linear search | 07_linear_search.c |
5, list, 30 |
return index, −1 for absent |
| 8 | Matrix addition | 08_matrix_addition.c |
2 2 then both matrices |
2-D arrays passed to functions |
| 9 | Factorial by recursion | 09_factorial_recursive.c |
5 |
base case and recursive case |
| 10 | Matrix multiplication | 10_matrix_multiplication.c |
2 then both matrices |
three nested loops |
| 11 | Sort ascending | 11_sort_ascending.c |
6 then the list |
bubble sort with early exit |
| 12 | Employee salary | 12_employee_salary.c |
2 then two records |
structures and formatted output |
| 13 | File read/write | 13_file_read_write.c |
none | fopen, fprintf, fgets, fclose |
| 14 | Reverse a file | 14_reverse_file.c |
none | fseek from SEEK_END |
| 15 | Book database | 15_book_file_crud.c |
menu choices | full CRUD on a binary file |
Check whether a number is an Armstrong number (here 153).
Decide whether a number equals the sum of its digits each raised to the number of digits.
% 10 takes the last digit and / 10 drops it.THE METHOD
An n-digit number equals the sum of its digits each raised to the power n. 153 = 1³ + 5³ + 3³. You must count the digits first to know the exponent — that step is what most students miss. 1634 is a four-digit Armstrong number: 1⁴ + 6⁴ + 3⁴ + 4⁴ = 1 + 1296 + 81 + 256 = 1634.
/* Experiment 1: Check whether a given number is an Armstrong number.
*
* An Armstrong number of n digits equals the sum of its own digits each
* raised to the power n. 153 -> 1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153.
*
* Sample input: 153
* Sample output: 153 is an Armstrong number
*/
#include <stdio.h>
/* Step 1: Count the digits */
int count_digits(int n)
{
int digits = 0;
if (n == 0)
return 1;
while (n > 0) {
digits++;
n /= 10;
}
return digits;
}
/* Step 2: Raise a digit to a power */
int power(int base, int exp)
{
int result = 1, i;
for (i = 0; i < exp; i++)
result *= base;
return result;
}
int main(void)
{
int num, temp, digit, sum = 0, n;
/* Step 3: Read the number */
printf("Enter a number: ");
if (scanf("%d", &num) != 1) {
printf("Invalid input\n");
return 1;
}
/* Step 4: Add each digit raised to the number of digits */
n = count_digits(num);
temp = num;
while (temp > 0) {
digit = temp % 10;
sum += power(digit, n);
temp /= 10;
}
/* Step 5: Compare the sum with the number */
if (sum == num)
printf("%d is an Armstrong number\n", num);
else
printf("%d is not an Armstrong number\n", num);
return 0;
}
OUTPUT
Enter a number: 153
153 is an Armstrong number
RESULT
153 = 1³ + 5³ + 3³, so 153 is an Armstrong number.
Find the sum of the digits of a number (here 12345).
Add the digits of a number by peeling them off one at a time.
/* Experiment 2: Find the sum of individual digits of a positive integer.
*
* Sample input: 12345
* Sample output: Sum of digits of 12345 = 15
*/
#include <stdio.h>
int main(void)
{
int num, temp, sum = 0;
/* Step 1: Read the number */
printf("Enter a positive integer: ");
if (scanf("%d", &num) != 1 || num < 0) {
printf("Please enter a positive integer\n");
return 1;
}
/* Step 2: Peel off each digit and add it */
temp = num;
while (temp > 0) {
sum += temp % 10; /* peel off the last digit */
temp /= 10; /* and drop it */
}
/* Step 3: Print the sum */
printf("Sum of digits of %d = %d\n", num, sum);
return 0;
}
OUTPUT
Enter a positive integer: 12345
Sum of digits of 12345 = 15
RESULT
The digits of 12345 add to 15.
Print the first n terms of the Fibonacci series (here 10).
Generate the series iteratively, with three variables.
long long holds more terms before it overflows./* Experiment 3: Generate the first n terms of the Fibonacci sequence.
*
* Sample input: 10
* Sample output: 0 1 1 2 3 5 8 13 21 34
*/
#include <stdio.h>
int main(void)
{
int n, i;
long long first = 0, second = 1, next;
/* Step 1: Read the number of terms */
printf("Enter the number of terms: ");
if (scanf("%d", &n) != 1 || n <= 0) {
printf("Please enter a positive number of terms\n");
return 1;
}
/* Step 2: Print each term and move the pair on */
printf("Fibonacci sequence: ");
for (i = 0; i < n; i++) {
printf("%lld", first);
if (i < n - 1)
printf(" ");
next = first + second;
first = second;
second = next;
}
printf("\n");
return 0;
}
OUTPUT
Enter the number of terms: 10
Fibonacci sequence: 0 1 1 2 3 5 8 13 21 34
RESULT
The first ten terms are 0 1 1 2 3 5 8 13 21 34.
Find both the largest and the smallest number in a list (here 23, 7, 91, 4, 56).
Find the extremes of a list in one pass.
/* Experiment 4: Find both the largest and the smallest number in a list.
*
* Sample input: 5
* 23 7 91 4 56
* Sample output: Largest = 91
* Smallest = 4
*/
#include <stdio.h>
#define MAX 100
int main(void)
{
int list[MAX], n, i, largest, smallest;
/* Step 1: Read the numbers */
printf("How many numbers? ");
if (scanf("%d", &n) != 1 || n <= 0 || n > MAX) {
printf("Please enter a count between 1 and %d\n", MAX);
return 1;
}
printf("Enter %d numbers: ", n);
for (i = 0; i < n; i++) {
if (scanf("%d", &list[i]) != 1) {
printf("Invalid input\n");
return 1;
}
}
/* Step 2: Seed both with the first element */
/* Seed both with the first element -- not with 0, which breaks on
all-negative lists. */
largest = smallest = list[0];
/* Step 3: Compare every other element */
for (i = 1; i < n; i++) {
if (list[i] > largest)
largest = list[i];
if (list[i] < smallest)
smallest = list[i];
}
/* Step 4: Print the two */
printf("Largest = %d\n", largest);
printf("Smallest = %d\n", smallest);
return 0;
}
OUTPUT
How many numbers? 5
Enter 5 numbers: 23 7 91 4 56
Largest = 91
Smallest = 4
RESULT
The largest is 91 and the smallest 4.
Swap two numbers using call by value and call by address (here 10 and 20).
Show that only call by address changes the caller's variables.
THE METHOD
The most examined program in the course. Make sure your output shows all three
states — before, inside the function, after — for both methods. The point
is visible only in the contrast: call by value prints 10 20 after the call,
call by address prints 20 10.
/* Experiment 5: Demonstrate the change in parameter values while swapping two
* integers using Call by Value and Call by Address.
*
* This is the classic exam question on parameter passing. Call by value swaps
* only the function's private copies, so the caller sees nothing change. Call
* by address passes the addresses, so the function reaches the originals.
*
* Sample input: 10 20
*/
#include <stdio.h>
/* Step 1: Swap by value: the function gets copies */
void swap_by_value(int a, int b)
{
int temp = a;
a = b;
b = temp;
printf(" inside swap_by_value : a = %d, b = %d\n", a, b);
}
/* Step 2: Swap by address: the function gets pointers */
void swap_by_address(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
printf(" inside swap_by_address: a = %d, b = %d\n", *a, *b);
}
int main(void)
{
int x, y;
/* Step 3: Read two integers */
printf("Enter two integers: ");
if (scanf("%d %d", &x, &y) != 2) {
printf("Invalid input\n");
return 1;
}
/* Step 4: Call by value: before, inside, after */
printf("\nCALL BY VALUE\n");
printf(" before: x = %d, y = %d\n", x, y);
swap_by_value(x, y);
printf(" after : x = %d, y = %d <- unchanged\n", x, y);
/* Step 5: Call by address: before, inside, after */
printf("\nCALL BY ADDRESS\n");
printf(" before: x = %d, y = %d\n", x, y);
swap_by_address(&x, &y);
printf(" after : x = %d, y = %d <- swapped\n", x, y);
return 0;
}
OUTPUT
Enter two integers: 10 20
CALL BY VALUE
before: x = 10, y = 20
inside swap_by_value : a = 20, b = 10
after : x = 10, y = 20 <- unchanged
CALL BY ADDRESS
before: x = 10, y = 20
inside swap_by_address: a = 20, b = 10
after : x = 20, y = 10 <- swapped
RESULT
Both functions swap their own copies, but only call by address changes x and y: after it they are 20 and 10, while after call by value they are still 10 and 20.
Perform the string operations — length, compare, copy, concatenate, reverse — with the library functions and with functions of your own (here on Hello and World).
Use the string library, and write its functions by hand.
/* Experiment 6: Perform various string operations.
*
* Shows both the library functions from <string.h> and hand-written versions,
* because exams commonly ask you to implement strlen/strcpy/strcmp yourself.
*
* Sample input: Hello
* World
*/
#include <stdio.h>
#include <string.h>
/* Step 1: Hand-written strlen and strcpy */
/* Hand-written equivalents -- the "write it without the library" exam question. */
int my_strlen(const char *s)
{
int len = 0;
while (s[len] != '\0')
len++;
return len;
}
void my_strcpy(char *dest, const char *src)
{
int i = 0;
while (src[i] != '\0') {
dest[i] = src[i];
i++;
}
dest[i] = '\0';
}
/* Step 2: Hand-written strcmp and reverse */
int my_strcmp(const char *a, const char *b)
{
int i = 0;
while (a[i] != '\0' && a[i] == b[i])
i++;
return a[i] - b[i];
}
void my_strrev(char *s)
{
int i = 0, j = my_strlen(s) - 1;
char temp;
while (i < j) {
temp = s[i];
s[i] = s[j];
s[j] = temp;
i++;
j--;
}
}
int main(void)
{
char s1[100], s2[100], copy[200], joined[200];
/* Step 3: Read two strings */
printf("Enter first string : ");
if (scanf("%99s", s1) != 1) return 1;
printf("Enter second string: ");
if (scanf("%99s", s2) != 1) return 1;
/* Step 4: The library functions */
printf("\nLibrary functions\n");
printf(" strlen(s1) = %d\n", (int) strlen(s1));
printf(" strcmp(s1, s2) = %d\n", strcmp(s1, s2));
strcpy(joined, s1);
strcat(joined, s2);
printf(" strcat(s1, s2) = %s\n", joined);
/* Step 5: The hand-written versions */
printf("\nHand-written versions\n");
printf(" my_strlen(s1) = %d\n", my_strlen(s1));
printf(" my_strcmp(s1, s2) = %d\n", my_strcmp(s1, s2));
my_strcpy(copy, s1);
printf(" my_strcpy -> %s\n", copy);
my_strrev(copy);
printf(" my_strrev -> %s\n", copy);
return 0;
}
OUTPUT
Enter first string : Hello
Enter second string: World
Library functions
strlen(s1) = 5
strcmp(s1, s2) = -15
strcat(s1, s2) = HelloWorld
Hand-written versions
my_strlen(s1) = 5
my_strcmp(s1, s2) = -15
my_strcpy -> Hello
my_strrev -> olleH
RESULT
Both versions agree: the length of Hello is 5, and Hello compares below World (−15, the difference of H and W). The copy is Hello, reversed olleH, and the two joined HelloWorld.
Search a list for an element by linear search (here 30 in 10, 20, 30, 40, 50).
Find an element's position, or report that it is absent.
/* Experiment 7: Search for an element in a given list of values.
*
* Linear search: check each element in turn. Worst case O(n).
*
* Sample input: 5
* 10 20 30 40 50
* 30
* Sample output: 30 found at position 3 (index 2)
*/
#include <stdio.h>
#define MAX 100
/* Step 1: Search, returning the index or -1 */
int linear_search(const int list[], int n, int key)
{
int i;
for (i = 0; i < n; i++) {
if (list[i] == key)
return i; /* found -- return the index */
}
return -1; /* the conventional "not found" marker */
}
int main(void)
{
int list[MAX], n, i, key, pos;
/* Step 2: Read the list and the key */
printf("How many elements? ");
if (scanf("%d", &n) != 1 || n <= 0 || n > MAX) return 1;
printf("Enter %d elements: ", n);
for (i = 0; i < n; i++)
if (scanf("%d", &list[i]) != 1) return 1;
printf("Enter the element to search: ");
if (scanf("%d", &key) != 1) return 1;
/* Step 3: Search, and report the position */
pos = linear_search(list, n, key);
if (pos == -1)
printf("%d is not present in the list\n", key);
else
printf("%d found at position %d (index %d)\n", key, pos + 1, pos);
return 0;
}
OUTPUT
How many elements? 5
Enter 5 elements: 10 20 30 40 50
Enter the element to search: 30
30 found at position 3 (index 2)
RESULT
30 is at position 3 (index 2).
Use functions to add two matrices (here two 2 × 2 matrices).
Pass 2-D arrays to functions to read, add and print them.
/* Experiment 8: Use functions to add two matrices.
*
* Sample input: 2 2
* 1 2 3 4
* 5 6 7 8
* Sample output: 6 8
* 10 12
*/
#include <stdio.h>
#define MAX 10
/* Step 1: Read a matrix */
void read_matrix(int m[MAX][MAX], int rows, int cols, const char *name)
{
int i, j;
printf("Enter %d elements of matrix %s: ", rows * cols, name);
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
if (scanf("%d", &m[i][j]) != 1)
return;
}
/* Step 2: Add two matrices */
void add_matrices(int a[MAX][MAX], int b[MAX][MAX], int sum[MAX][MAX],
int rows, int cols)
{
int i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
sum[i][j] = a[i][j] + b[i][j];
}
/* Step 3: Print a matrix */
void print_matrix(int m[MAX][MAX], int rows, int cols)
{
int i, j;
for (i = 0; i < rows; i++) {
for (j = 0; j < cols; j++)
printf("%4d", m[i][j]);
printf("\n");
}
}
int main(void)
{
int a[MAX][MAX], b[MAX][MAX], sum[MAX][MAX];
int rows, cols;
/* Step 4: Read the order and both matrices */
printf("Enter rows and columns: ");
if (scanf("%d %d", &rows, &cols) != 2 ||
rows <= 0 || cols <= 0 || rows > MAX || cols > MAX) {
printf("Dimensions must be between 1 and %d\n", MAX);
return 1;
}
read_matrix(a, rows, cols, "A");
read_matrix(b, rows, cols, "B");
/* Step 5: Add them, and print the sum */
add_matrices(a, b, sum, rows, cols);
printf("\nA + B =\n");
print_matrix(sum, rows, cols);
return 0;
}
OUTPUT
Enter rows and columns: 2 2
Enter 4 elements of matrix A: 1 2 3 4
Enter 4 elements of matrix B: 5 6 7 8
A + B =
6 8
10 12
RESULT
A + B = [6 8; 10 12].
Find the factorial of a number using recursion (here 5).
Compute n! recursively, refusing the inputs it cannot handle.
/* Experiment 9: Calculate the factorial of a given integer using recursion.
*
* The exam almost always asks you to identify the base case and the recursive
* case, so they are labelled below.
*
* Sample input: 5
* Sample output: 5! = 120
*/
#include <stdio.h>
/* Step 1: The recursive function: a base case and a recursive case */
unsigned long long factorial(int n)
{
if (n == 0 || n == 1) /* BASE CASE -- stops the recursion */
return 1;
return (unsigned long long) n * factorial(n - 1); /* RECURSIVE CASE */
}
int main(void)
{
int n;
/* Step 2: Read n, refusing a negative or an overflow */
printf("Enter a non-negative integer: ");
if (scanf("%d", &n) != 1 || n < 0) {
printf("Factorial is not defined for negative numbers\n");
return 1;
}
if (n > 20) {
printf("%d! overflows a 64-bit integer\n", n);
return 1;
}
/* Step 3: Print n! */
printf("%d! = %llu\n", n, factorial(n));
return 0;
}
OUTPUT
Enter a non-negative integer: 5
5! = 120
RESULT
5! = 120.
Multiply two square matrices (here two 2 × 2 matrices).
Multiply matrices with three nested loops.
THE METHOD
Three nested loops, and c[i][j] must be reset to 0 before the innermost loop
accumulates into it. Verify by hand on 2×2 matrices before trusting your code:
[1 2] × [5 6] = [1×5+2×7 1×6+2×8] = [19 22]
[3 4] [7 8] [3×5+4×7 3×6+4×8] [43 50]
/* Experiment 10: Multiplication of two N x N matrices.
*
* C[i][j] = sum over k of A[i][k] * B[k][j]
*
* Sample input: 2
* 1 2 3 4
* 5 6 7 8
* Sample output: 19 22
* 43 50
*/
#include <stdio.h>
#define MAX 10
/* Step 1: Multiply: reset each cell, then accumulate */
void multiply(int a[MAX][MAX], int b[MAX][MAX], int c[MAX][MAX], int n)
{
int i, j, k;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
c[i][j] = 0; /* must reset before accumulating */
for (k = 0; k < n; k++)
c[i][j] += a[i][k] * b[k][j];
}
}
}
int main(void)
{
int a[MAX][MAX], b[MAX][MAX], c[MAX][MAX];
int n, i, j;
/* Step 2: Read the order and both matrices */
printf("Enter N (order of the square matrices): ");
if (scanf("%d", &n) != 1 || n <= 0 || n > MAX) return 1;
printf("Enter %d elements of matrix A: ", n * n);
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
if (scanf("%d", &a[i][j]) != 1) return 1;
printf("Enter %d elements of matrix B: ", n * n);
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
if (scanf("%d", &b[i][j]) != 1) return 1;
/* Step 3: Multiply them, and print the product */
multiply(a, b, c, n);
printf("\nA x B =\n");
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++)
printf("%6d", c[i][j]);
printf("\n");
}
return 0;
}
OUTPUT
Enter N (order of the square matrices): 2
Enter 4 elements of matrix A: 1 2 3 4
Enter 4 elements of matrix B: 5 6 7 8
A x B =
19 22
43 50
RESULT
A × B = [19 22; 43 50], as worked by hand.
Sort a list in ascending order (here 64, 34, 25, 12, 22, 11).
Sort by bubble sort, stopping as soon as a pass makes no swap.
/* Experiment 11: Sort a given list of integers in ascending order.
*
* Bubble sort, with the early-exit flag -- exams ask for the flag as the
* "optimised" version. Best case O(n) on already-sorted data, worst O(n^2).
*
* Sample input: 6
* 64 34 25 12 22 11
* Sample output: 11 12 22 25 34 64
*/
#include <stdio.h>
#define MAX 100
/* Step 1: Bubble sort, with an early exit */
void bubble_sort(int list[], int n)
{
int i, j, temp, swapped;
for (i = 0; i < n - 1; i++) {
swapped = 0;
for (j = 0; j < n - 1 - i; j++) {
if (list[j] > list[j + 1]) {
temp = list[j];
list[j] = list[j + 1];
list[j + 1] = temp;
swapped = 1;
}
}
if (!swapped) /* nothing moved -- the list is already sorted */
break;
}
}
int main(void)
{
int list[MAX], n, i;
/* Step 2: Read the list */
printf("How many elements? ");
if (scanf("%d", &n) != 1 || n <= 0 || n > MAX) return 1;
printf("Enter %d elements: ", n);
for (i = 0; i < n; i++)
if (scanf("%d", &list[i]) != 1) return 1;
/* Step 3: Sort it, and print it */
bubble_sort(list, n);
printf("Sorted list: ");
for (i = 0; i < n; i++)
printf("%d ", list[i]);
printf("\n");
return 0;
}
OUTPUT
How many elements? 6
Enter 6 elements: 64 34 25 12 22 11
Sorted list: 11 12 22 25 34 64
RESULT
The sorted list is 11 12 22 25 34 64.
Using a structure, compute the gross and net salary of employees from their basic pay.
Hold each employee's record in a structure, and compute the pay by the syllabus rules.
THE METHOD
The rules from the syllabus, in order — each depends on the one before:
DA = 30% of Basic Pay
HRA = 15% of Basic Pay
Deduction = 10% of (Basic Pay + DA) <- includes DA, not just basic
Gross = Basic Pay + DA + HRA
Net = Gross − Deduction
For a basic pay of 50,000: DA = 15,000, HRA = 7,500, Deduction = 10% of 65,000 = 6,500, Gross = 72,500, Net = 66,000.
/* Experiment 12: Calculate the salaries of all employees using an Employee
* structure (ID, Name, Designation, Basic Pay, DA, HRA, Gross, Deduction, Net).
*
* Rules given in the syllabus:
* DA = 30% of Basic Pay
* HRA = 15% of Basic Pay
* Deduction = 10% of (Basic Pay + DA)
* Gross = Basic Pay + DA + HRA
* Net = Gross - Deduction
*
* Sample input: 2
* 101 Alice Manager 50000
* 102 Bob Clerk 20000
*/
#include <stdio.h>
#define MAX_EMP 50
/* Step 1: The employee structure */
struct Employee {
int id;
char name[50];
char designation[50];
float basic_pay;
float da;
float hra;
float gross_salary;
float deduction;
float net_salary;
};
/* Step 2: The salary rules, in order */
void compute_salary(struct Employee *e)
{
e->da = 0.30f * e->basic_pay;
e->hra = 0.15f * e->basic_pay;
e->deduction = 0.10f * (e->basic_pay + e->da);
e->gross_salary = e->basic_pay + e->da + e->hra;
e->net_salary = e->gross_salary - e->deduction;
}
int main(void)
{
struct Employee staff[MAX_EMP];
int n, i;
/* Step 3: Read each employee and compute the pay */
printf("How many employees? ");
if (scanf("%d", &n) != 1 || n <= 0 || n > MAX_EMP) return 1;
for (i = 0; i < n; i++) {
printf("Employee %d (id name designation basic_pay): ", i + 1);
if (scanf("%d %49s %49s %f", &staff[i].id, staff[i].name,
staff[i].designation, &staff[i].basic_pay) != 4)
return 1;
compute_salary(&staff[i]);
}
/* Step 4: Print the table */
printf("\n%-6s %-12s %-12s %10s %9s %9s %10s %10s %10s\n",
"ID", "Name", "Designation", "Basic", "DA", "HRA",
"Gross", "Deduction", "Net");
for (i = 0; i < n; i++) {
printf("%-6d %-12s %-12s %10.2f %9.2f %9.2f %10.2f %10.2f %10.2f\n",
staff[i].id, staff[i].name, staff[i].designation,
staff[i].basic_pay, staff[i].da, staff[i].hra,
staff[i].gross_salary, staff[i].deduction, staff[i].net_salary);
}
return 0;
}
OUTPUT
How many employees? 2
Employee 1 (id name designation basic_pay): 101 Alice Manager 50000
Employee 2 (id name designation basic_pay): 102 Bob Clerk 20000
ID Name Designation Basic DA HRA Gross Deduction Net
101 Alice Manager 50000.00 15000.00 7500.00 72500.00 6500.00 66000.00
102 Bob Clerk 20000.00 6000.00 3000.00 29000.00 2600.00 26400.00
RESULT
Alice's basic pay of 50,000 gives a gross of 72,500 and a net of 66,000; Bob's 20,000 gives 29,000 and 26,400.
Write text to a file and read it back.
Open, write, close, reopen and read a text file.
/* Experiment 13: Read data from / write data to a file.
*
* Demonstrates the full cycle: fopen in "w" mode, fprintf, fclose, then
* fopen in "r" mode, fgets, fclose. Always check that fopen succeeded --
* that check is worth marks.
*
* Takes no input; writes and reads back sample.txt in the current directory.
*/
#include <stdio.h>
int main(void)
{
FILE *fp;
char line[256];
const char *filename = "sample.txt";
/* Step 1: Write three lines */
fp = fopen(filename, "w");
if (fp == NULL) {
printf("Error: could not open %s for writing\n", filename);
return 1;
}
fprintf(fp, "Data Science Major 2025\n");
fprintf(fp, "Problem Solving Using C\n");
fprintf(fp, "File handling demonstration\n");
fclose(fp);
printf("Data written to %s\n\n", filename);
/* Step 2: Read them back */
fp = fopen(filename, "r");
if (fp == NULL) {
printf("Error: could not open %s for reading\n", filename);
return 1;
}
printf("Contents of %s:\n", filename);
while (fgets(line, sizeof(line), fp) != NULL)
printf(" %s", line);
fclose(fp);
return 0;
}
OUTPUT
Data written to sample.txt
Contents of sample.txt:
Data Science Major 2025
Problem Solving Using C
File handling demonstration
RESULT
The three lines written to sample.txt are read back unchanged.
Copy the contents of a file into another in reverse order.
Read a file backwards with fseek, and write what it reads.
THE METHOD
fseek(fp, -i, SEEK_END) for i = 1, 2, 3… walks backwards from the end one
byte at a time. Open in binary mode ("rb") so no line-ending translation
interferes.
/* Experiment 14: Reverse the contents of a file and store the result in
* another file.
*
* Method: seek to the end, then walk backwards one byte at a time with
* fseek(fp, -offset, SEEK_END), writing each character to the output file.
*
* Creates input.txt, then produces reversed.txt from it.
*/
#include <stdio.h>
int main(void)
{
FILE *in, *out;
long size, i;
int ch;
/* Step 1: Create the input file */
/* Create the input file so the program is self-contained. */
in = fopen("input.txt", "w");
if (in == NULL) {
printf("Error: could not create input.txt\n");
return 1;
}
fprintf(in, "ABCDEFG");
fclose(in);
in = fopen("input.txt", "rb");
if (in == NULL) {
printf("Error: could not open input.txt\n");
return 1;
}
out = fopen("reversed.txt", "wb");
if (out == NULL) {
printf("Error: could not create reversed.txt\n");
fclose(in);
return 1;
}
/* Step 2: Copy it backwards, one byte at a time from the end */
fseek(in, 0, SEEK_END);
size = ftell(in);
for (i = 1; i <= size; i++) {
fseek(in, -i, SEEK_END);
ch = fgetc(in);
if (ch == EOF)
break;
fputc(ch, out);
}
fclose(in);
fclose(out);
/* Step 3: Show both files */
/* Show the result. */
printf("input.txt : ");
in = fopen("input.txt", "r");
while ((ch = fgetc(in)) != EOF) putchar(ch);
fclose(in);
printf("\nreversed.txt : ");
out = fopen("reversed.txt", "r");
while ((ch = fgetc(out)) != EOF) putchar(ch);
fclose(out);
printf("\n");
return 0;
}
OUTPUT
input.txt : ABCDEFG
reversed.txt : GFEDCBA
RESULT
ABCDEFG is written out as GFEDCBA.
Create a Book structure (ISBN, Title, Author, Price, Pages, Publisher), store book details in a file, and add, search, update and delete books by ISBN.
Keep records in a binary file, and carry out all four operations on it.
THE METHOD
The largest program in the list. Four operations on a binary file of struct
Book records:
fopen in "ab" (append binary), then fwritefread in a loop until the ISBN matchesUpdate — fopen in "rb+", fread until found, then
fseek(fp, -sizeof(b), SEEK_CUR) to step back over the record just read, and
fwrite over it
Delete — copy every record except the target into a temporary file, then
remove() the original and rename() the temporary
That last technique is the one to remember: you cannot delete bytes from the middle of a file. Rewriting to a temporary file is the standard answer.
/* Experiment 15: Create a Book structure (ISBN, Title, Author, Price, Pages,
* Publisher), store book details in a file, and perform:
* a. Add book details
* b. Search for a book by ISBN and display it if present
* c. Update a book's details using its ISBN
* d. Delete a book by ISBN and display the remaining books
*
* This is the largest program in the lab list: it combines structures, file
* I/O and a menu-driven loop.
*
* The delete operation uses the standard technique -- copy every record except
* the doomed one into a temporary file, then rename it over the original. You
* cannot remove bytes from the middle of a file in place.
*
* Sample input (a menu choice, then what that choice asks for):
* 1
* 111 C_Programming Balaguruswamy 450.00 500 TMH
* 1
* 222 Python_Basics Thareja 550.00 600 Oxford
* 2
* 111
* 3
* 111 600.00
* 4
* 222
* 5
* 6
*/
#include <stdio.h>
#include <string.h>
#define DATAFILE "books.dat"
#define TEMPFILE "temp.dat"
/* Step 1: The book record */
struct Book {
int isbn;
char title[50];
char author[50];
float price;
int pages;
char publisher[50];
};
/* Step 2: Print a book */
static void print_header(void)
{
printf("%-8s %-20s %-15s %10s %7s %-15s\n",
"ISBN", "Title", "Author", "Price", "Pages", "Publisher");
}
static void print_book(const struct Book *b)
{
printf("%-8d %-20s %-15s %10.2f %7d %-15s\n",
b->isbn, b->title, b->author, b->price, b->pages, b->publisher);
}
/* (a) Append one book to the data file. */
/* Step 3: Add: append a record */
void add_book(void)
{
struct Book b;
FILE *fp = fopen(DATAFILE, "ab");
if (fp == NULL) {
printf("Error: cannot open %s\n", DATAFILE);
return;
}
printf("Enter ISBN title author price pages publisher: ");
if (scanf("%d %49s %49s %f %d %49s", &b.isbn, b.title, b.author,
&b.price, &b.pages, b.publisher) != 6) {
printf("Invalid book details\n");
fclose(fp);
return;
}
fwrite(&b, sizeof(b), 1, fp);
fclose(fp);
printf("Book %d added\n", b.isbn);
}
/* (b) Search by ISBN. */
/* Step 4: Search by ISBN */
void search_book(void)
{
struct Book b;
int isbn, found = 0;
FILE *fp = fopen(DATAFILE, "rb");
if (fp == NULL) {
printf("No books stored yet\n");
return;
}
printf("Enter ISBN to search: ");
if (scanf("%d", &isbn) != 1) {
fclose(fp);
return;
}
while (fread(&b, sizeof(b), 1, fp) == 1) {
if (b.isbn == isbn) {
print_header();
print_book(&b);
found = 1;
break;
}
}
fclose(fp);
if (!found)
printf("Book with ISBN %d not found\n", isbn);
}
/* (c) Update a book's price, writing the record back in place. */
/* Step 5: Update: overwrite the record in place */
void update_book(void)
{
struct Book b;
int isbn, found = 0;
float new_price;
FILE *fp = fopen(DATAFILE, "rb+");
if (fp == NULL) {
printf("No books stored yet\n");
return;
}
printf("Enter ISBN to update and the new price: ");
if (scanf("%d %f", &isbn, &new_price) != 2) {
fclose(fp);
return;
}
while (fread(&b, sizeof(b), 1, fp) == 1) {
if (b.isbn == isbn) {
b.price = new_price;
/* Step back over the record just read, then overwrite it. */
fseek(fp, -(long) sizeof(b), SEEK_CUR);
fwrite(&b, sizeof(b), 1, fp);
found = 1;
break;
}
}
fclose(fp);
printf(found ? "Book %d updated\n" : "Book with ISBN %d not found\n", isbn);
}
/* (d) Delete by ISBN: copy all survivors to a temp file, then rename. */
/* Step 6: Delete: copy the rest to a temporary file */
void delete_book(void)
{
struct Book b;
int isbn, found = 0;
FILE *fp, *temp;
fp = fopen(DATAFILE, "rb");
if (fp == NULL) {
printf("No books stored yet\n");
return;
}
temp = fopen(TEMPFILE, "wb");
if (temp == NULL) {
printf("Error: cannot create temporary file\n");
fclose(fp);
return;
}
printf("Enter ISBN to delete: ");
if (scanf("%d", &isbn) != 1) {
fclose(fp);
fclose(temp);
return;
}
while (fread(&b, sizeof(b), 1, fp) == 1) {
if (b.isbn == isbn)
found = 1; /* skip it -- this is the deletion */
else
fwrite(&b, sizeof(b), 1, temp);
}
fclose(fp);
fclose(temp);
remove(DATAFILE);
rename(TEMPFILE, DATAFILE);
if (found)
printf("Book %d deleted\n", isbn);
else
printf("Book with ISBN %d not found\n", isbn);
}
/* Step 7: Display all */
void display_all(void)
{
struct Book b;
int count = 0;
FILE *fp = fopen(DATAFILE, "rb");
if (fp == NULL) {
printf("No books stored yet\n");
return;
}
print_header();
while (fread(&b, sizeof(b), 1, fp) == 1) {
print_book(&b);
count++;
}
fclose(fp);
printf("(%d book(s))\n", count);
}
/* Step 8: The menu */
int main(void)
{
int choice;
for (;;) {
printf("\n1.Add 2.Search 3.Update 4.Delete 5.Display all 6.Exit\n");
printf("Enter your choice: ");
if (scanf("%d", &choice) != 1)
break;
switch (choice) {
case 1: add_book(); break;
case 2: search_book(); break;
case 3: update_book(); break;
case 4: delete_book(); break;
case 5: display_all(); break;
case 6: printf("Exiting\n"); return 0;
default: printf("Invalid choice\n");
}
}
return 0;
}
OUTPUT
1.Add 2.Search 3.Update 4.Delete 5.Display all 6.Exit
Enter your choice: 1
Enter ISBN title author price pages publisher: 111 C_Programming Balaguruswamy 450.00 500 TMH
Book 111 added
1.Add 2.Search 3.Update 4.Delete 5.Display all 6.Exit
Enter your choice: 1
Enter ISBN title author price pages publisher: 222 Python_Basics Thareja 550.00 600 Oxford
Book 222 added
1.Add 2.Search 3.Update 4.Delete 5.Display all 6.Exit
Enter your choice: 2
Enter ISBN to search: 111
ISBN Title Author Price Pages Publisher
111 C_Programming Balaguruswamy 450.00 500 TMH
1.Add 2.Search 3.Update 4.Delete 5.Display all 6.Exit
Enter your choice: 3
Enter ISBN to update and the new price: 111 600.00
Book 111 updated
1.Add 2.Search 3.Update 4.Delete 5.Display all 6.Exit
Enter your choice: 4
Enter ISBN to delete: 222
Book 222 deleted
1.Add 2.Search 3.Update 4.Delete 5.Display all 6.Exit
Enter your choice: 5
ISBN Title Author Price Pages Publisher
111 C_Programming Balaguruswamy 600.00 500 TMH
(1 book(s))
1.Add 2.Search 3.Update 4.Delete 5.Display all 6.Exit
Enter your choice: 6
Exiting
RESULT
Two books are added, book 111 is found and its price updated to 600.00, book 222 is deleted, and the file then holds one book.
Read the error message. "Expected ; before int" means the missing
semicolon is on the line above the one named.
Test edge cases before the examiner does: n = 0, an empty array, a negative number, a file that does not exist.
Print prompts. printf("Enter n: ") before every scanf. Marks are given
for a usable interface.
Comment the logic, not the syntax. /* peel off the last digit */ is
useful; /* increment i */ is not.
Expect a viva. Be ready for "why did you use a while here?" and "what
happens if I enter 0?"
For each experiment, the five parts set out above: 1. Question, the task as set; 2. Aim, in one line; 3. Steps, the method in numbered steps; 4. Programme, the program, each step marked by a comment; 5. Execution and Results, what it printed for the sample input, and the result in words.