C Programming Curriculum - All Levels
BEGINNER LEVEL SOLUTIONS
Week 1 Solutions
Solution 1.1: Personal Hello World
#include <stdio.h>
int main() {
printf("Hello, my name is [Student Name]!\n");
printf("I am learning C programming.\n");
return 0;
}
Solution 1.2: Asterisk Pattern
#include <stdio.h>
int main() {
printf("*****\n");
printf("* *\n");
printf("* *\n");
printf("* *\n");
printf("*****\n");
return 0;
}
Solution 1.3: Numbers 1-10
#include <stdio.h>
int main() {
printf("Numbers from 1 to 10:\n");
for(int i = 1; i <= 10; i++) {
printf("%d\n", i);
}
return 0;
}
Week 2 Solutions
Solution 2.1: Rectangle Area Calculator
#include <stdio.h>
int main() {
float length, width, area;
printf("Enter the length of rectangle: ");
scanf("%f", &length);
printf("Enter the width of rectangle: ");
scanf("%f", &width);
area = length * width;
printf("Area of rectangle = %.2f square units\n", area);
return 0;
}
Solution 2.2: Temperature Converter
#include <stdio.h>
int main() {
float fahrenheit, celsius;
printf("Enter temperature in Fahrenheit: ");
scanf("%f", &fahrenheit);
celsius = (fahrenheit - 32) * 5.0 / 9.0;
printf("%.2f°F = %.2f°C\n", fahrenheit, celsius);
return 0;
}
Solution 2.3: Simple Interest Calculator
#include <stdio.h>
int main() {
float principal, rate, time, interest;
printf("Enter principal amount: $");
scanf("%f", &principal);
printf("Enter rate of interest: ");
scanf("%f", &rate);
printf("Enter time period (years): ");
scanf("%f", &time);
interest = (principal * rate * time) / 100;
printf("Simple Interest = $%.2f\n", interest);
printf("Total Amount = $%.2f\n", principal + interest);
return 0;
}
Solution 2.4: Swap Numbers Without Third Variable
#include <stdio.h>
int main() {
int a, b;
printf("Enter two numbers: ");
scanf("%d %d", &a, &b);
printf("Before swapping: a = %d, b = %d\n", a, b);
// Swapping without third variable
a = a + b;
b = a - b;
a = a - b;
printf("After swapping: a = %d, b = %d\n", a, b);
return 0;
}
Week 3 Solutions
Solution 3.1: Even or Odd Checker
#include <stdio.h>
int main() {
int number;
printf("Enter a number: ");
scanf("%d", &number);
if (number % 2 == 0) {
printf("%d is even.\n", number);
} else {
printf("%d is odd.\n", number);
}
return 0;
}
Solution 3.2: Largest of Three Numbers
#include <stdio.h>
int main() {
int a, b, c, largest;
printf("Enter three numbers: ");
scanf("%d %d %d", &a, &b, &c);
if (a >= b && a >= c) {
largest = a;
} else if (b >= a && b >= c) {
largest = b;
} else {
largest = c;
}
printf("The largest number is: %d\n", largest);
return 0;
}
Solution 3.3: Simple Calculator
#include <stdio.h>
int main() {
float num1, num2, result;
char operator;
printf("Enter first number: ");
scanf("%f", &num1);
printf("Enter operator (+, -, *, /): ");
scanf(" %c", &operator);
printf("Enter second number: ");
scanf("%f", &num2);
switch(operator) {
case '+':
result = num1 + num2;
printf("%.2f + %.2f = %.2f\n", num1, num2, result);
break;
case '-':
result = num1 - num2;
printf("%.2f - %.2f = %.2f\n", num1, num2, result);
break;
case '*':
result = num1 * num2;
printf("%.2f * %.2f = %.2f\n", num1, num2, result);
break;
case '/':
if (num2 != 0) {
result = num1 / num2;
printf("%.2f / %.2f = %.2f\n", num1, num2, result);
} else {
printf("Error: Division by zero!\n");
}
break;
default:
printf("Error: Invalid operator!\n");
}
return 0;
}
Solution 3.4: Multiplication Table
#include <stdio.h>
int main() {
int number;
printf("Enter a number: ");
scanf("%d", &number);
printf("Multiplication table of %d:\n", number);
for (int i = 1; i <= 10; i++) {
printf("%d x %d = %d\n", number, i, number * i);
}
return 0;
}
Week 4 Solutions
Solution 4.1: Fibonacci Series
#include <stdio.h>
int main() {
int n, first = 0, second = 1, next;
printf("Enter number of terms: ");
scanf("%d", &n);
printf("Fibonacci Series: ");
if (n >= 1) {
printf("%d ", first);
}
if (n >= 2) {
printf("%d ", second);
}
for (int i = 3; i <= n; i++) {
next = first + second;
printf("%d ", next);
first = second;
second = next;
}
printf("\n");
return 0;
}
Solution 4.2: Factorial Calculator
#include <stdio.h>
int main() {
int number;
long long factorial = 1;
printf("Enter a number: ");
scanf("%d", &number);
if (number < 0) {
printf("Factorial is not defined for negative numbers.\n");
} else {
for (int i = 1; i <= number; i++) {
factorial *= i;
}
printf("Factorial of %d = %lld\n", number, factorial);
}
return 0;
}
Solution 4.3: Palindrome Checker
#include <stdio.h>
int main() {
int number, original, reversed = 0, remainder;
printf("Enter a number: ");
scanf("%d", &number);
original = number;
while (number != 0) {
remainder = number % 10;
reversed = reversed * 10 + remainder;
number /= 10;
}
if (original == reversed) {
printf("%d is a palindrome.\n", original);
} else {
printf("%d is not a palindrome.\n", original);
}
return 0;
}
Solution 4.4: Prime Numbers 1-100
#include <stdio.h>
int main() {
int isPrime;
printf("Prime numbers between 1 and 100:\n");
for (int num = 2; num <= 100; num++) {
isPrime = 1; // Assume number is prime
for (int i = 2; i * i <= num; i++) {
if (num % i == 0) {
isPrime = 0; // Number is not prime
break;
}
}
if (isPrime) {
printf("%d ", num);
}
}
printf("\n");
return 0;
}
INTERMEDIATE LEVEL SOLUTIONS
Week 5 Solutions
Solution 5.1: Prime Number Function
#include <stdio.h>
int isPrime(int n) {
if (n <= 1) {
return 0; // Not prime
}
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) {
return 0; // Not prime
}
}
return 1; // Prime
}
int main() {
int number;
printf("Enter a number: ");
scanf("%d", &number);
if (isPrime(number)) {
printf("%d is a prime number.\n", number);
} else {
printf("%d is not a prime number.\n", number);
}
return 0;
}
Solution 5.2: Recursive Fibonacci
#include <stdio.h>
int fibonacci(int n) {
if (n <= 1) {
return n;
}
return fibonacci(n - 1) + fibonacci(n - 2);
}
int main() {
int terms;
printf("Enter number of terms: ");
scanf("%d", &terms);
printf("Fibonacci Series: ");
for (int i = 0; i < terms; i++) {
printf("%d ", fibonacci(i));
}
printf("\n");
return 0;
}
Solution 5.3: Recursive Power Function
#include <stdio.h>
double power(double base, int exponent) {
if (exponent == 0) {
return 1;
} else if (exponent > 0) {
return base * power(base, exponent - 1);
} else {
return 1 / power(base, -exponent);
}
}
int main() {
double base;
int exponent;
printf("Enter base: ");
scanf("%lf", &base);
printf("Enter exponent: ");
scanf("%d", &exponent);
printf("%.2f^%d = %.2f\n", base, exponent, power(base, exponent));
return 0;
}
Solution 5.4: Number Reverser Function
#include <stdio.h>
int reverseNumber(int num) {
int reversed = 0;
while (num != 0) {
reversed = reversed * 10 + num % 10;
num /= 10;
}
return reversed;
}
int main() {
int number;
printf("Enter a number: ");
scanf("%d", &number);
printf("Reversed number: %d\n", reverseNumber(number));
return 0;
}
Week 6 Solutions
Solution 6.1: Largest Element in Array
#include <stdio.h>
int main() {
int n, largest;
printf("Enter number of elements: ");
scanf("%d", &n);
int arr[n];
printf("Enter %d elements: ", n);
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
largest = arr[0];
for (int i = 1; i < n; i++) {
if (arr[i] > largest) {
largest = arr[i];
}
}
printf("Largest element: %d\n", largest);
return 0;
}
Solution 6.2: Array Reverser
#include <stdio.h>
void printArray(int arr[], int size) {
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
int main() {
int n;
printf("Enter number of elements: ");
scanf("%d", &n);
int arr[n];
printf("Enter %d elements: ", n);
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
printf("Original array: ");
printArray(arr, n);
// Reverse the array
for (int i = 0; i < n/2; i++) {
int temp = arr[i];
arr[i] = arr[n-1-i];
arr[n-1-i] = temp;
}
printf("Reversed array: ");
printArray(arr, n);
return 0;
}
Solution 6.3: Vowel Counter
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int countVowels(char str[]) {
int count = 0;
int len = strlen(str);
for (int i = 0; i < len; i++) {
char ch = tolower(str[i]);
if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u') {
count++;
}
}
return count;
}
int main() {
char str[100];
printf("Enter a string: ");
fgets(str, sizeof(str), stdin);
// Remove newline character
str[strcspn(str, "\n")] = '\0';
int vowels = countVowels(str);
printf("Number of vowels: %d\n", vowels);
return 0;
}
Solution 6.4: Bubble Sort
#include <stdio.h>
void bubbleSort(int arr[], int n) {
for (int i = 0; i < n-1; i++) {
for (int j = 0; j < n-i-1; j++) {
if (arr[j] > arr[j+1]) {
// Swap elements
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
void printArray(int arr[], int size) {
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
int main() {
int n;
printf("Enter number of elements: ");
scanf("%d", &n);
int arr[n];
printf("Enter %d elements: ", n);
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
printf("Original array: ");
printArray(arr, n);
bubbleSort(arr, n);
printf("Sorted array: ");
printArray(arr, n);
return 0;
}
Week 7 Solutions
Solution 7.1: Maximum Using Pointers
#include <stdio.h>
int findMax(int *a, int *b) {
return (*a > *b) ? *a : *b;
}
int main() {
int num1, num2;
printf("Enter two numbers: ");
scanf("%d %d", &num1, &num2);
int max = findMax(&num1, &num2);
printf("Maximum of %d and %d is: %d\n", num1, num2, max);
return 0;
}
Solution 7.2: String Length Using Pointers
#include <stdio.h>
int stringLength(char *str) {
int length = 0;
while (*str != '\0') {
length++;
str++;
}
return length;
}
int main() {
char str[100];
printf("Enter a string: ");
fgets(str, sizeof(str), stdin);
// Remove newline character
if (str[stringLength(str) - 1] == '\n') {
str[stringLength(str) - 1] = '\0';
}
printf("Length of string: %d\n", stringLength(str));
return 0;
}
Solution 7.3: String Reverser Using Pointers
#include <stdio.h>
#include <string.h>
void reverseString(char *str) {
char *start = str;
char *end = str + strlen(str) - 1;
while (start < end) {
// Swap characters
char temp = *start;
*start = *end;
*end = temp;
start++;
end--;
}
}
int main() {
char str[100];
printf("Enter a string: ");
fgets(str, sizeof(str), stdin);
// Remove newline character
str[strcspn(str, "\n")] = '\0';
printf("Original string: %s\n", str);
reverseString(str);
printf("Reversed string: %s\n", str);
return 0;
}
Solution 7.4: Array Sort Using Pointers
#include <stdio.h>
void sortArray(int *arr, int n) {
for (int i = 0; i < n-1; i++) {
for (int j = 0; j < n-i-1; j++) {
if (*(arr + j) > *(arr + j + 1)) {
// Swap using pointers
int temp = *(arr + j);
*(arr + j) = *(arr + j + 1);
*(arr + j + 1) = temp;
}
}
}
}
void printArray(int *arr, int size) {
for (int i = 0; i < size; i++) {
printf("%d ", *(arr + i));
}
printf("\n");
}
int main() {
int n;
printf("Enter number of elements: ");
scanf("%d", &n);
int arr[n];
printf("Enter %d elements: ", n);
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
printf("Original array: ");
printArray(arr, n);
sortArray(arr, n);
printf("Sorted array: ");
printArray(arr, n);
return 0;
}
Week 8 Solutions
Solution 8.1: Matrix Multiplication
#include <stdio.h>
void multiplyMatrices(int first[10][10], int second[10][10], int result[10][10],
int r1, int c1, int r2, int c2) {
// Initialize result matrix to zero
for (int i = 0; i < r1; i++) {
for (int j = 0; j < c2; j++) {
result[i][j] = 0;
}
}
// Multiply matrices
for (int i = 0; i < r1; i++) {
for (int j = 0; j < c2; j++) {
for (int k = 0; k < c1; k++) {
result[i][j] += first[i][k] * second[k][j];
}
}
}
}
void printMatrix(int matrix[10][10], int rows, int cols) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("%d ", matrix[i][j]);
}
printf("\n");
}
}
int main() {
int first[10][10], second[10][10], result[10][10];
int r1, c1, r2, c2;
printf("Enter rows and columns for first matrix: ");
scanf("%d %d", &r1, &c1);
printf("Enter rows and columns for second matrix: ");
scanf("%d %d", &r2, &c2);
if (c1 != r2) {
printf("Matrix multiplication not possible!\n");
return 1;
}
printf("Enter elements of first matrix:\n");
for (int i = 0; i < r1; i++) {
for (int j = 0; j < c1; j++) {
scanf("%d", &first[i][j]);
}
}
printf("Enter elements of second matrix:\n");
for (int i = 0; i < r2; i++) {
for (int j = 0; j < c2; j++) {
scanf("%d", &second[i][j]);
}
}
multiplyMatrices(first, second, result, r1, c1, r2, c2);
printf("Result matrix:\n");
printMatrix(result, r1, c2);
return 0;
}
Solution 8.2: Word Count with Command Line Arguments
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int countWords(FILE *file) {
int words = 0;
int inWord = 0;
int ch;
while ((ch = fgetc(file)) != EOF) {
if (isspace(ch)) {
inWord = 0;
} else if (!inWord) {
inWord = 1;
words++;
}
}
return words;
}
int main(int argc, char *argv[]) {
if (argc != 2) {
printf("Usage: %s <filename>\n", argv[0]);
return 1;
}
FILE *file = fopen(argv[1], "r");
if (file == NULL) {
printf("Error: Cannot open file '%s'\n", argv[1]);
return 1;
}
int wordCount = countWords(file);
fclose(file);
printf("File '%s' contains %d words.\n", argv[1], wordCount);
return 0;
}
Solution 8.3: String Tokenizer
#include <stdio.h>
#include <string.h>
void tokenizeString(char *str, char delimiter) {
char *token = strtok(str, &delimiter);
int count = 0;
printf("Tokens:\n");
while (token != NULL) {
count++;
printf("%d: %s\n", count, token);
token = strtok(NULL, &delimiter);
}
printf("Total tokens: %d\n", count);
}
int main() {
char str[200];
char delimiter;
printf("Enter a string: ");
fgets(str, sizeof(str), stdin);
// Remove newline character
str[strcspn(str, "\n")] = '\0';
printf("Enter delimiter: ");
scanf("%c", &delimiter);
tokenizeString(str, delimiter);
return 0;
}
Solution 8.4: Tic-Tac-Toe Game
#include <stdio.h>
char board[3][3];
void initializeBoard() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
board[i][j] = ' ';
}
}
}
void printBoard() {
printf("\n");
for (int i = 0; i < 3; i++) {
printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
if (i < 2) {
printf("---|---|---\n");
}
}
printf("\n");
}
int checkWin() {
// Check rows
for (int i = 0; i < 3; i++) {
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ') {
return 1;
}
}
// Check columns
for (int j = 0; j < 3; j++) {
if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[0][j] != ' ') {
return 1;
}
}
// Check diagonals
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ') {
return 1;
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ') {
return 1;
}
return 0;
}
int isBoardFull() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (board[i][j] == ' ') {
return 0;
}
}
}
return 1;
}
int main() {
int row, col;
char currentPlayer = 'X';
initializeBoard();
printf("Tic-Tac-Toe Game\n");
printf("Players take turns. Enter row (0-2) and column (0-2).\n");
while (1) {
printBoard();
printf("Player %c, enter your move (row col): ", currentPlayer);
scanf("%d %d", &row, &col);
if (row < 0 || row > 2 || col < 0 || col > 2 || board[row][col] != ' ') {
printf("Invalid move! Try again.\n");
continue;
}
board[row][col] = currentPlayer;
if (checkWin()) {
printBoard();
printf("Player %c wins!\n", currentPlayer);
break;
}
if (isBoardFull()) {
printBoard();
printf("It's a draw!\n");
break;
}
currentPlayer = (currentPlayer == 'X') ? 'O' : 'X';
}
return 0;
}
ADVANCED LEVEL SOLUTIONS
Week 9 Solutions
Solution 9.1: Student Management System
#include <stdio.h>
#include <string.h>
#define MAX_STUDENTS 100
struct Student {
int id;
char name[50];
int age;
float gpa;
};
struct Student students[MAX_STUDENTS];
int studentCount = 0;
void addStudent() {
if (studentCount >= MAX_STUDENTS) {
printf("Cannot add more students. Database full!\n");
return;
}
struct Student *s = &students[studentCount];
printf("Enter student ID: ");
scanf("%d", &s->id);
printf("Enter student name: ");
scanf("%s", s->name);
printf("Enter student age: ");
scanf("%d", &s->age);
printf("Enter student GPA: ");
scanf("%f", &s->gpa);
studentCount++;
printf("Student added successfully!\n");
}
void displayStudents() {
if (studentCount == 0) {
printf("No students in database.\n");
return;
}
printf("\n--- Student Database ---\n");
printf("ID\tName\t\tAge\tGPA\n");
printf("--------------------------------\n");
for (int i = 0; i < studentCount; i++) {
printf("%d\t%-15s\t%d\t%.2f\n",
students[i].id, students[i].name,
students[i].age, students[i].gpa);
}
}
void searchStudent() {
int id;
printf("Enter student ID to search: ");
scanf("%d", &id);
for (int i = 0; i < studentCount; i++) {
if (students[i].id == id) {
printf("Student found:\n");
printf("ID: %d\n", students[i].id);
printf("Name: %s\n", students[i].name);
printf("Age: %d\n", students[i].age);
printf("GPA: %.2f\n", students[i].gpa);
return;
}
}
printf("Student with ID %d not found.\n", id);
}
int main() {
int choice;
while (1) {
printf("\n--- Student Management System ---\n");
printf("1. Add Student\n");
printf("2. Display All Students\n");
printf("3. Search Student\n");
printf("4. Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);
switch (choice) {
case 1:
addStudent();
break;
case 2:
displayStudents();
break;
case 3:
searchStudent();
break;
case 4:
printf("Goodbye!\n");
return 0;
default:
printf("Invalid choice!\n");
}
}
}
Solution 9.2: Library Book Management System
#include <stdio.h>
#include <string.h>
#define MAX_BOOKS 100
struct Book {
int id;
char title[100];
char author[50];
int year;
float price;
int isAvailable;
};
struct Book library[MAX_BOOKS];
int bookCount = 0;
void addBook() {
if (bookCount >= MAX_BOOKS) {
printf("Library is full!\n");
return;
}
struct Book *b = &library[bookCount];
printf("Enter book ID: ");
scanf("%d", &b->id);
printf("Enter book title: ");
getchar(); // consume newline
fgets(b->title, sizeof(b->title), stdin);
b->title[strcspn(b->title, "\n")] = '\0'; // remove newline
printf("Enter author name: ");
fgets(b->author, sizeof(b->author), stdin);
b->author[strcspn(b->author, "\n")] = '\0'; // remove newline
printf("Enter publication year: ");
scanf("%d", &b->year);
printf("Enter price: ");
scanf("%f", &b->price);
b->isAvailable = 1; // Book is available by default
bookCount++;
printf("Book added successfully!\n");
}
void displayBooks() {
if (bookCount == 0) {
printf("No books in library.\n");
return;
}
printf("\n--- Library Catalog ---\n");
printf("ID\tTitle\t\t\tAuthor\t\tYear\tPrice\tStatus\n");
printf("-----------------------------------------------------------------------\n");
for (int i = 0; i < bookCount; i++) {
printf("%d\t%-20s\t%-15s\t%d\t%.2f\t%s\n",
library[i].id, library[i].title, library[i].author,
library[i].year, library[i].price,
library[i].isAvailable ? "Available" : "Borrowed");
}
}
void borrowBook() {
int id;
printf("Enter book ID to borrow: ");
scanf("%d", &id);
for (int i = 0; i < bookCount; i++) {
if (library[i].id == id) {
if (library[i].isAvailable) {
library[i].isAvailable = 0;
printf("Book '%s' borrowed successfully!\n", library[i].title);
} else {
printf("Book is already borrowed!\n");
}
return;
}
}
printf("Book with ID %d not found.\n", id);
}
void returnBook() {
int id;
printf("Enter book ID to return: ");
scanf("%d", &id);
for (int i = 0; i < bookCount; i++) {
if (library[i].id == id) {
if (!library[i].isAvailable) {
library[i].isAvailable = 1;
printf("Book '%s' returned successfully!\n", library[i].title);
} else {
printf("Book is already available!\n");
}
return;
}
}
printf("Book with ID %d not found.\n", id);
}
int main() {
int choice;
while (1) {
printf("\n--- Library Management System ---\n");
printf("1. Add Book\n");
printf("2. Display All Books\n");
printf("3. Borrow Book\n");
printf("4. Return Book\n");
printf("5. Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);
switch (choice) {
case 1:
addBook();
break;
case 2:
displayBooks();
break;
case 3:
borrowBook();
break;
case 4:
returnBook();
break;
case 5:
printf("Goodbye!\n");
return 0;
default:
printf("Invalid choice!\n");
}
}
}
Week 10 Solutions
Solution 10.1: File Copying Utility
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
if (argc != 3) {
printf("Usage: %s <source_file> <destination_file>\n", argv[0]);
return 1;
}
FILE *source = fopen(argv[1], "rb");
if (source == NULL) {
printf("Error: Cannot open source file '%s'\n", argv[1]);
return 1;
}
FILE *destination = fopen(argv[2], "wb");
if (destination == NULL) {
printf("Error: Cannot create destination file '%s'\n", argv[2]);
fclose(source);
return 1;
}
int ch;
long bytescopied = 0;
while ((ch = fgetc(source)) != EOF) {
fputc(ch, destination);
bytescopied++;
}
fclose(source);
fclose(destination);
printf("File copied successfully!\n");
printf("Bytes copied: %ld\n", bytescopied);
return 0;
}
Solution 10.2: Word Frequency Counter
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX_WORDS 1000
#define MAX_WORD_LENGTH 50
struct WordCount {
char word[MAX_WORD_LENGTH];
int count;
};
struct WordCount wordList[MAX_WORDS];
int wordCount = 0;
void toLowerCase(char *str) {
for (int i = 0; str[i]; i++) {
str[i] = tolower(str[i]);
}
}
int findWord(char *word) {
for (int i = 0; i < wordCount; i++) {
if (strcmp(wordList[i].word, word) == 0) {
return i;
}
}
return -1;
}
void addWord(char *word) {
toLowerCase(word);
int index = findWord(word);
if (index != -1) {
wordList[index].count++;
} else if (wordCount < MAX_WORDS) {
strcpy(wordList[wordCount].word, word);
wordList[wordCount].count = 1;
wordCount++;
}
}
int main(int argc, char *argv[]) {
if (argc != 2) {
printf("Usage: %s <filename>\n", argv[0]);
return 1;
}
FILE *file = fopen(argv[1], "r");
if (file == NULL) {
printf("Error: Cannot open file '%s'\n", argv[1]);
return 1;
}
char word[MAX_WORD_LENGTH];
while (fscanf(file, "%49s", word) == 1) {
// Remove punctuation
int len = strlen(word);
while (len > 0 && !isalnum(word[len-1])) {
word[len-1] = '\0';
len--;
}
if (len > 0) {
addWord(word);
}
}
fclose(file);
printf("Word Frequency Report\n");
printf("=====================\n");
for (int i = 0; i < wordCount; i++) {
printf("%-20s: %d\n", wordList[i].word, wordList[i].count);
}
printf("\nTotal unique words: %d\n", wordCount);
return 0;
}
Week 11 Solutions
Solution 11.1: Dynamic String Manipulation
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* createString(const char* initial) {
if (initial == NULL) {
return NULL;
}
int len = strlen(initial);
char* str = (char*)malloc((len + 1) * sizeof(char));
if (str != NULL) {
strcpy(str, initial);
}
return str;
}
char* concatenateStrings(const char* str1, const char* str2) {
if (str1 == NULL || str2 == NULL) {
return NULL;
}
int len1 = strlen(str1);
int len2 = strlen(str2);
char* result = (char*)malloc((len1 + len2 + 1) * sizeof(char));
if (result != NULL) {
strcpy(result, str1);
strcat(result, str2);
}
return result;
}
char* resizeString(char* str, int newSize) {
if (str == NULL || newSize <= 0) {
return NULL;
}
char* newStr = (char*)realloc(str, newSize * sizeof(char));
return newStr;
}
int main() {
char* str1 = createString("Hello");
char* str2 = createString(" World");
if (str1 == NULL || str2 == NULL) {
printf("Memory allocation failed!\n");
return 1;
}
printf("String 1: %s\n", str1);
printf("String 2: %s\n", str2);
char* combined = concatenateStrings(str1, str2);
if (combined != NULL) {
printf("Combined: %s\n", combined);
}
// Resize string to accommodate more text
str1 = resizeString(str1, 100);
if (str1 != NULL) {
strcat(str1, " from C!");
printf("Extended string 1: %s\n", str1);
}
// Free allocated memory
free(str1);
free(str2);
free(combined);
printf("Memory freed successfully!\n");
return 0;
}
Solution 11.2: Resizable Array Implementation
#include <stdio.h>
#include <stdlib.h>
struct DynamicArray {
int* data;
int size;
int capacity;
};
struct DynamicArray* createArray(int initialCapacity) {
struct DynamicArray* arr = (struct DynamicArray*)malloc(sizeof(struct DynamicArray));
if (arr != NULL) {
arr->data = (int*)malloc(initialCapacity * sizeof(int));
if (arr->data != NULL) {
arr->size = 0;
arr->capacity = initialCapacity;
} else {
free(arr);
arr = NULL;
}
}
return arr;
}
int resize(struct DynamicArray* arr, int newCapacity) {
if (arr == NULL || newCapacity <= 0) {
return 0;
}
int* newData = (int*)realloc(arr->data, newCapacity * sizeof(int));
if (newData == NULL) {
return 0; // Reallocation failed
}
arr->data = newData;
arr->capacity = newCapacity;
if (arr->size > newCapacity) {
arr->size = newCapacity;
}
return 1; // Success
}
int append(struct DynamicArray* arr, int value) {
if (arr == NULL) {
return 0;
}
if (arr->size >= arr->capacity) {
// Double the capacity
if (!resize(arr, arr->capacity * 2)) {
return 0;
}
}
arr->data[arr->size] = value;
arr->size++;
return 1;
}
void printArray(struct DynamicArray* arr) {
if (arr == NULL) {
printf("Array is NULL\n");
return;
}
printf("Array (size: %d, capacity: %d): [", arr->size, arr->capacity);
for (int i = 0; i < arr->size; i++) {
printf("%d", arr->data[i]);
if (i < arr->size - 1) {
printf(", ");
}
}
printf("]\n");
}
void freeArray(struct DynamicArray* arr) {
if (arr != NULL) {
free(arr->data);
free(arr);
}
}
int main() {
struct DynamicArray* arr = createArray(2);
if (arr == NULL) {
printf("Failed to create array!\n");
return 1;
}
// Add elements
for (int i = 1; i <= 10; i++) {
append(arr, i * 10);
printArray(arr);
}
// Manually resize
printf("\nResizing to capacity 5...\n");
resize(arr, 5);
printArray(arr);
freeArray(arr);
printf("Array freed successfully!\n");
return 0;
}
EXPERT LEVEL SOLUTIONS
Week 13 Solutions
Solution 13.1: File Copy Using System Calls
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#define BUFFER_SIZE 4096
int main(int argc, char *argv[]) {
if (argc != 3) {
fprintf(stderr, "Usage: %s <source> <destination>\n", argv[0]);
return 1;
}
int src_fd = open(argv[1], O_RDONLY);
if (src_fd == -1) {
fprintf(stderr, "Error opening source file '%s': %s\n",
argv[1], strerror(errno));
return 1;
}
struct stat src_stat;
if (fstat(src_fd, &src_stat) == -1) {
fprintf(stderr, "Error getting source file stats: %s\n", strerror(errno));
close(src_fd);
return 1;
}
int dst_fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, src_stat.st_mode);
if (dst_fd == -1) {
fprintf(stderr, "Error creating destination file '%s': %s\n",
argv[2], strerror(errno));
close(src_fd);
return 1;
}
char buffer[BUFFER_SIZE];
ssize_t bytes_read, bytes_written;
off_t total_bytes = 0;
while ((bytes_read = read(src_fd, buffer, BUFFER_SIZE)) > 0) {
bytes_written = write(dst_fd, buffer, bytes_read);
if (bytes_written != bytes_read) {
fprintf(stderr, "Error writing to destination file: %s\n",
strerror(errno));
close(src_fd);
close(dst_fd);
return 1;
}
total_bytes += bytes_written;
}
if (bytes_read == -1) {
fprintf(stderr, "Error reading from source file: %s\n", strerror(errno));
close(src_fd);
close(dst_fd);
return 1;
}
close(src_fd);
close(dst_fd);
printf("Successfully copied %ld bytes from '%s' to '%s'\n",
total_bytes, argv[1], argv[2]);
return 0;
}
Solution 13.2: Process Monitor Utility
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <signal.h>
#include <string.h>
volatile sig_atomic_t keep_running = 1;
void signal_handler(int sig) {
keep_running = 0;
}
void print_process_info(pid_t pid, const char* command) {
struct timeval tv;
gettimeofday(&tv, NULL);
printf("[%ld.%06ld] Process %d (%s) ",
tv.tv_sec, tv.tv_usec, pid, command);
}
int main(int argc, char *argv[]) {
if (argc < 2) {
fprintf(stderr, "Usage: %s <command> [args...]\n", argv[0]);
return 1;
}
signal(SIGINT, signal_handler);
pid_t pid = fork();
if (pid == -1) {
perror("fork failed");
return 1;
}
if (pid == 0) {
// Child process - execute the command
execvp(argv[1], &argv[1]);
perror("execvp failed");
return 1;
} else {
// Parent process - monitor the child
print_process_info(pid, argv[1]);
printf("started\n");
int status;
struct timeval start_time, end_time;
gettimeofday(&start_time, NULL);
// Monitor process
while (keep_running) {
pid_t result = waitpid(pid, &status, WNOHANG);
if (result == pid) {
// Process has terminated
gettimeofday(&end_time, NULL);
double elapsed = (end_time.tv_sec - start_time.tv_sec) +
(end_time.tv_usec - start_time.tv_usec) / 1000000.0;
print_process_info(pid, argv[1]);
if (WIFEXITED(status)) {
printf("exited with status %d after %.3f seconds\n",
WEXITSTATUS(status), elapsed);
} else if (WIFSIGNALED(status)) {
printf("terminated by signal %d after %.3f seconds\n",
WTERMSIG(status), elapsed);
}
break;
} else if (result == -1) {
perror("waitpid failed");
break;
}
// Sleep for a short time before checking again
usleep(100000); // 100ms
}
if (!keep_running) {
// Interrupted by signal, kill child process
kill(pid, SIGTERM);
waitpid(pid, &status, 0);
print_process_info(pid, argv[1]);
printf("terminated by user\n");
}
}
return 0;
}
Week 14 Solutions
Solution 14.1: Memory Pool Allocator with Debugging
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#define POOL_SIZE 4096
#define MAGIC_NUMBER 0xDEADBEEF
struct BlockHeader {
size_t size;
uint32_t magic;
int is_free;
struct BlockHeader* next;
};
struct MemoryPool {
char* pool;
struct BlockHeader* free_list;
size_t total_size;
size_t used_size;
int allocation_count;
};
struct MemoryPool* create_pool(size_t size) {
struct MemoryPool* pool = malloc(sizeof(struct MemoryPool));
if (!pool) return NULL;
pool->pool = malloc(size);
if (!pool->pool) {
free(pool);
return NULL;
}
pool->total_size = size;
pool->used_size = 0;
pool->allocation_count = 0;
// Initialize free list with entire pool
pool->free_list = (struct BlockHeader*)pool->pool;
pool->free_list->size = size - sizeof(struct BlockHeader);
pool->free_list->magic = MAGIC_NUMBER;
pool->free_list->is_free = 1;
pool->free_list->next = NULL;
return pool;
}
void* pool_alloc(struct MemoryPool* pool, size_t size) {
if (!pool || size == 0) return NULL;
// Align size to 8 bytes
size = (size + 7) & ~7;
struct BlockHeader* current = pool->free_list;
struct BlockHeader* prev = NULL;
while (current) {
if (current->is_free && current->size >= size) {
// Found suitable block
if (current->size > size + sizeof(struct BlockHeader)) {
// Split block
struct BlockHeader* new_block =
(struct BlockHeader*)((char*)current + sizeof(struct BlockHeader) + size);
new_block->size = current->size - size - sizeof(struct BlockHeader);
new_block->magic = MAGIC_NUMBER;
new_block->is_free = 1;
new_block->next = current->next;
current->size = size;
current->next = new_block;
}
current->is_free = 0;
pool->used_size += current->size + sizeof(struct BlockHeader);
pool->allocation_count++;
return (char*)current + sizeof(struct BlockHeader);
}
prev = current;
current = current->next;
}
return NULL; // No suitable block found
}
void pool_free(struct MemoryPool* pool, void* ptr) {
if (!pool || !ptr) return;
struct BlockHeader* header =
(struct BlockHeader*)((char*)ptr - sizeof(struct BlockHeader));
if (header->magic != MAGIC_NUMBER) {
printf("ERROR: Invalid magic number! Possible corruption or invalid pointer.\n");
return;
}
if (header->is_free) {
printf("WARNING: Double free detected!\n");
return;
}
header->is_free = 1;
pool->used_size -= header->size + sizeof(struct BlockHeader);
pool->allocation_count--;
// Coalesce adjacent free blocks
struct BlockHeader* current = pool->free_list;
while (current && current->next) {
if (current->is_free && current->next->is_free) {
struct BlockHeader* next = current->next;
if ((char*)current + sizeof(struct BlockHeader) + current->size == (char*)next) {
current->size += next->size + sizeof(struct BlockHeader);
current->next = next->next;
continue;
}
}
current = current->next;
}
}
void print_pool_stats(struct MemoryPool* pool) {
if (!pool) return;
printf("\n--- Memory Pool Statistics ---\n");
printf("Total size: %zu bytes\n", pool->total_size);
printf("Used size: %zu bytes\n", pool->used_size);
printf("Free size: %zu bytes\n", pool->total_size - pool->used_size);
printf("Active allocations: %d\n", pool->allocation_count);
printf("Fragmentation: %.2f%%\n",
(double)pool->used_size / pool->total_size * 100);
printf("\nBlock list:\n");
struct BlockHeader* current = pool->free_list;
int block_num = 0;
while (current) {
printf("Block %d: size=%zu, %s\n",
block_num++, current->size,
current->is_free ? "FREE" : "USED");
current = current->next;
}
}
void destroy_pool(struct MemoryPool* pool) {
if (pool) {
if (pool->allocation_count > 0) {
printf("WARNING: Destroying pool with %d active allocations!\n",
pool->allocation_count);
}
free(pool->pool);
free(pool);
}
}
int main() {
struct MemoryPool* pool = create_pool(POOL_SIZE);
if (!pool) {
printf("Failed to create memory pool!\n");
return 1;
}
printf("Memory pool created successfully!\n");
print_pool_stats(pool);
// Test allocations
void* ptr1 = pool_alloc(pool, 100);
void* ptr2 = pool_alloc(pool, 200);
void* ptr3 = pool_alloc(pool, 50);
printf("\nAfter allocations:\n");
print_pool_stats(pool);
// Test free
pool_free(pool, ptr2);
printf("\nAfter freeing middle block:\n");
print_pool_stats(pool);
// Test allocation in freed space
void* ptr4 = pool_alloc(pool, 150);
printf("\nAfter reallocating:\n");
print_pool_stats(pool);
// Clean up
pool_free(pool, ptr1);
pool_free(pool, ptr3);
pool_free(pool, ptr4);
printf("\nAfter freeing all:\n");
print_pool_stats(pool);
destroy_pool(pool);
return 0;
}
This comprehensive solution set covers all exercises from beginner to expert level, providing detailed implementations that demonstrate proper C programming techniques, memory management, error handling, and system programming concepts. Each solution includes proper error checking, clear comments, and follows good coding practices.