This laboratory covers fundamental structure operations in C, including sorting algorithms, data validation, and information display functions.
Exercise 1: Book Catalog Management System
Problem Statement
Implement functions to manage a book catalog with the following requirements:
- Display book information in a formatted output
- Sort books by sales quantity in descending order
- Calculate total sales revenue across all books
Solution
#include <stdio.h>
#define CATALOG_SIZE 10
typedef struct {
char isbn[20];
char title[80];
char author[80];
double unit_price;
int quantity_sold;
} Book;
void display_catalog(Book collection[], int count);
void sort_by_sales(Book collection[], int count);
double calculate_revenue(Book collection[], int count);
int main() {
Book catalog[CATALOG_SIZE] = {
{"978-0-13-110362-7", "The C Programming Language", "Kernighan", 45.0, 120},
{"978-0-13-468599-1", "Structure and Interpretation", "Abelson", 55.0, 85},
{"978-0-201-63371-8", "The Pragmatic Programmer", "Hunt", 50.0, 95},
{"978-0-132-27533-4", "Clean Code", "Martin", 40.0, 150},
{"978-0-13-235088-4", "Clean Architecture", "Martin", 38.0, 75},
{"978-0-201-61622-4", "Design Patterns", "Gamma", 48.0, 110},
{"978-0-596-52068-7", "JavaScript: The Good Parts", "Crockford", 29.0, 200},
{"978-0-13-468600-4", "Refactoring", "Fowler", 52.0, 65},
{"978-0-201-63371-8", "The Mythical Man-Month", "Brooks", 35.0, 90},
{"978-0-13-711008-2", "Code Complete", "McConnell", 55.0, 80}
};
printf("Book Catalog - Ranked by Sales Volume:\n");
sort_by_sales(catalog, CATALOG_SIZE);
display_catalog(catalog, CATALOG_SIZE);
printf("\nTotal Revenue: $%.2f\n", calculate_revenue(catalog, CATALOG_SIZE));
return 0;
}
void display_catalog(Book collection[], int count) {
int index;
for (index = 0; index < count; index++) {
printf("%s | %-25s | %-20s | $%-8.2f | %d units\n",
collection[index].isbn,
collection[index].title,
collection[index].author,
collection[index].unit_price,
collection[index].quantity_sold);
}
}
void sort_by_sales(Book collection[], int count) {
int outer, inner;
Book temporary;
for (outer = 0; outer < count - 1; outer++) {
for (inner = outer + 1; inner < count; inner++) {
if (collection[outer].quantity_sold < collection[inner].quantity_sold) {
temporary = collection[outer];
collection[outer] = collection[inner];
collection[inner] = temporary;
}
}
}
}
double calculate_revenue(Book collection[], int count) {
double total = 0.0;
int index;
for (index = 0; index < count; index++) {
total += collection[index].quantity_sold * collection[index].unit_price;
}
return total;
}
Output Analysis
This solution demonstrates bubble sort implementation for structure arrays and accumulator pattern for financial calculations.
Exercise 2: Date Utility Functions
Problem Statement
Create a date manipulation library that supports:
- Converting any date to its day-of-year position
- Comparing two dates to determine chronological order
- Validating date input from user
Solution
#include <stdio.h>
typedef struct {
int year;
int month;
int day;
} CalendarDate;
void read_date(CalendarDate *date_ptr);
int get_day_number(CalendarDate date);
int compare_dates(CalendarDate first, CalendarDate second);
void test_day_conversion() {
CalendarDate input_date;
int test_count;
printf("Test 1: Day of Year Calculation\n");
printf("Enter dates in YYYY-MM-DD format:\n");
for (test_count = 0; test_count < 3; test_count++) {
read_date(&input_date);
printf("%d-%02d-%02d is day #%d of the year\n\n",
input_date.year, input_date.month, input_date.day,
get_day_number(input_date));
}
}
void test_date_comparison() {
CalendarDate date_a, date_b;
int test_count;
int comparison_result;
printf("Test 2: Date Comparison\n");
printf("Enter two dates (Alice, then Bob) in YYYY-MM-DD format:\n");
for (test_count = 0; test_count < 3; test_count++) {
read_date(&date_a);
read_date(&date_b);
comparison_result = compare_dates(date_a, date_b);
if (comparison_result == 0) {
printf("Both dates are identical\n\n");
} else if (comparison_result < 0) {
printf("First date precedes second date\n\n");
} else {
printf("First date follows second date\n\n");
}
}
}
int main() {
test_day_conversion();
printf("\n----------------------------------------\n");
test_date_comparison();
return 0;
}
void read_date(CalendarDate *date_ptr) {
printf("Please enter date (YYYY-MM-DD):\n");
scanf("%d-%d-%d", &date_ptr->year, &date_ptr->month, &date_ptr->day);
}
int get_day_number(CalendarDate date) {
int accumulator = 0;
int month_index;
int days_per_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
for (month_index = 0; month_index < date.month - 1; month_index++) {
accumulator += days_per_month[month_index];
}
accumulator += date.day;
if ((date.year % 4 == 0 && date.year % 100 != 0) || date.year % 400 == 0) {
accumulator++;
}
return accumulator;
}
int compare_dates(CalendarDate first, CalendarDate second) {
if (first.year != second.year) {
return (first.year < second.year) ? -1 : 1;
}
if (first.month != second.month) {
return (first.month < second.month) ? -1 : 1;
}
if (first.day != second.day) {
return (first.day < second.day) ? -1 : 1;
}
return 0;
}
Key Concepts
This exercise introduces the concept of structure passing by value and pointer manipulation. The leap year calculation uses the standard Gregorian calendar rules.
Eexrcise 3: Account Management System
Problem Statement
Design an account management system with role-based access:
- Store multiple account records with username, password, and role type
- Display account information with masked passwords
- Support three role types: administrator, student, instructor
Solution
#include <stdio.h>
#include <string.h>
typedef enum {
ADMINISTRATOR,
STUDENT,
INSTRUCTOR
} UserRole;
typedef struct {
char username[20];
char password[20];
UserRole role;
} UserAccount;
void display_accounts(UserAccount records[], int count);
int main() {
UserAccount accounts[] = {
{"U1001", "pass123", STUDENT},
{"U1002", "secure456", STUDENT},
{"U1009", "xyz789", STUDENT},
{"A1009", "admin001", ADMINISTRATOR},
{"T11553", "teacher99", INSTRUCTOR},
{"U3005", "student007", STUDENT}
};
int account_count = sizeof(accounts) / sizeof(UserAccount);
display_accounts(accounts, account_count);
return 0;
}
void display_accounts(UserAccount records[], int count) {
int record_index, char_index;
printf("%-12s %-20s %s\n", "Username", "Password", "Role");
printf("----------------------------------------\n");
for (record_index = 0; record_index < count; record_index++) {
printf("%-12s", records[record_index].username);
int password_length = strlen(records[record_index].password);
for (char_index = 0; char_index < password_length; char_index++) {
putchar('*');
}
printf(" ");
switch (records[record_index].role) {
case ADMINISTRATOR:
printf("administrator\n");
break;
case STUDENT:
printf("student\n");
break;
case INSTRUCTOR:
printf("instructor\n");
break;
}
}
}
Design Notes
The enumerated type provides type-safe role representation. Password masking demonstrates strlen() usage and character output operations.
Exercise 4: Contact Directory with Priority Handling
Problem Statement
Build a contact directory system that:
- Manages a list of contacts with name, phone, and VIP status
- Allows marking specific contacts as emergency contacts (VIP)
- Displays contacts sorted alphabetically with VIP contacts first
Solution
#include <stdio.h>
#include <string.h>
#define MAX_CONTACTS 10
typedef struct {
char name[20];
char phone_number[12];
int is_emergency;
} ContactEntry;
void mark_as_emergency(ContactEntry contacts[], int count, char target_name[]);
void show_directory(ContactEntry contacts[], int count);
void list_priority_order(ContactEntry contacts[], int count);
int main() {
ContactEntry directory[MAX_CONTACTS] = {
{"Alice", "15510846604", 0},
{"Bob", "18038747351", 0},
{"Charlie", "18853253914", 0},
{"David", "13230584477", 0},
{"Eve", "15547571923", 0},
{"Frank", "18856659351", 0},
{"Grace", "17705843215", 0},
{"Henry", "15552933732", 0},
{"Irene", "18077702405", 0},
{"Jack", "18820725036", 0}
};
int emergency_count;
char input_name[20];
printf("Initial Contact Directory:\n");
show_directory(directory, MAX_CONTACTS);
printf("\nEnter number of emergency contacts: ");
scanf("%d", &emergency_count);
printf("Enter %d emergency contact names:\n", emergency_count);
int loop_index;
for (loop_index = 0; loop_index < emergency_count; loop_index++) {
scanf("%s", input_name);
mark_as_emergency(directory, MAX_CONTACTS, input_name);
}
printf("\nContact Directory (Alphabetical, Emergency First):\n");
list_priority_order(directory, MAX_CONTACTS);
return 0;
}
void mark_as_emergency(ContactEntry contacts[], int count, char target_name[]) {
int search_index;
for (search_index = 0; search_index < count; search_index++) {
if (strcmp(contacts[search_index].name, target_name) == 0) {
contacts[search_index].is_emergency = 1;
break;
}
}
}
void show_directory(ContactEntry contacts[], int count) {
int display_index;
for (display_index = 0; display_index < count; display_index++) {
printf("%-12s %-15s",
contacts[display_index].name,
contacts[display_index].phone_number);
if (contacts[display_index].is_emergency) {
printf(" %s", "[EMERGENCY]");
}
printf("\n");
}
}
void list_priority_order(ContactEntry contacts[], int count) {
int sort_outer, sort_inner;
ContactEntry temporary;
for (sort_outer = 0; sort_outer < count - 1; sort_outer++) {
for (sort_inner = sort_outer + 1; sort_inner < count; sort_inner++) {
if (strcmp(contacts[sort_outer].name, contacts[sort_inner].name) > 0) {
temporary = contacts[sort_outer];
contacts[sort_outer] = contacts[sort_inner];
contacts[sort_inner] = temporary;
}
}
}
int output_index;
for (output_index = 0; output_index < count; output_index++) {
if (contacts[output_index].is_emergency) {
printf("%-12s %-15s %s\n",
contacts[output_index].name,
contacts[output_index].phone_number,
"*");
}
}
for (output_index = 0; output_index < count; output_index++) {
if (!contacts[output_index].is_emergency) {
printf("%-12s %-15s\n",
contacts[output_index].name,
contacts[output_index].phone_number);
}
}
}
Summary
These laboratory exercises reinforce several critical C programming concepts:
- Structure definition and array manipulation
- Pointer notation for function parameters
- Enumerated types for type-safe constants
- Bubble sort implementation for custom data types
- Character array handling with string.h functions