c
exercises
exercises.cπ§c
/**
* =============================================================================
* FILE BASICS - EXERCISES
* =============================================================================
*
* Practice exercises for file opening, closing, and basic operations.
* Complete each exercise by implementing the required functionality.
*
* Compile: gcc -o exercises exercises.c -Wall -Wextra
* Run: ./exercises
* =============================================================================
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
/* Exercise function prototypes */
void exercise1_simple_file_creation(void);
void exercise2_check_file_existence(void);
void exercise3_safe_file_opener(void);
void exercise4_file_mode_explorer(void);
void exercise5_error_reporter(void);
void exercise6_copy_file_contents(void);
void exercise7_multiple_file_handler(void);
void exercise8_stream_redirector(void);
void exercise9_file_statistics(void);
void exercise10_binary_file_creator(void);
void print_exercise_header(int num, const char *title);
void run_all_exercises(void);
/* =============================================================================
* MAIN FUNCTION
* =============================================================================
*/
int main(void) {
printf("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n");
printf("β FILE BASICS - EXERCISES β\n");
printf("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n\n");
run_all_exercises();
return 0;
}
void print_exercise_header(int num, const char *title) {
printf("\nββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n");
printf("β EXERCISE %d: %-52s β\n", num, title);
printf("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n\n");
}
void run_all_exercises(void) {
exercise1_simple_file_creation();
exercise2_check_file_existence();
exercise3_safe_file_opener();
exercise4_file_mode_explorer();
exercise5_error_reporter();
exercise6_copy_file_contents();
exercise7_multiple_file_handler();
exercise8_stream_redirector();
exercise9_file_statistics();
exercise10_binary_file_creator();
printf("\nββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n");
printf("β ALL EXERCISES COMPLETED! β\n");
printf("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n");
}
/* =============================================================================
* EXERCISE 1: Simple File Creation
* =============================================================================
*
* Task:
* Create a function that creates a text file with your personal information.
* The file should contain:
* - Your name
* - Today's date
* - A greeting message
*
* Requirements:
* - Open file in write mode
* - Check for errors
* - Close file properly
* - Print confirmation message
*/
void exercise1_simple_file_creation(void) {
print_exercise_header(1, "Simple File Creation");
/* TODO: Implement your solution here */
/* SOLUTION */
const char *filename = "personal_info.txt";
FILE *fp = NULL;
printf("Creating personal information file...\n\n");
/* Open file for writing */
fp = fopen(filename, "w");
if (fp == NULL) {
perror("Error creating file");
return;
}
/* Write personal information */
fprintf(fp, "βββββββββββββββββββββββββββββββββββ\n");
fprintf(fp, " PERSONAL INFORMATION\n");
fprintf(fp, "βββββββββββββββββββββββββββββββββββ\n\n");
fprintf(fp, "Name: C Programming Student\n");
fprintf(fp, "Date: 2024-01-20\n");
fprintf(fp, "Message: Hello! I'm learning C file handling.\n");
fprintf(fp, "\nβββββββββββββββββββββββββββββββββββ\n");
/* Close file */
if (fclose(fp) != 0) {
perror("Error closing file");
return;
}
printf("File '%s' created successfully!\n\n", filename);
/* Read and display contents */
fp = fopen(filename, "r");
if (fp != NULL) {
printf("File contents:\n");
char buffer[100];
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
printf(" %s", buffer);
}
fclose(fp);
}
/* Clean up */
remove(filename);
printf("\n[Temporary file cleaned up]\n");
}
/* =============================================================================
* EXERCISE 2: Check File Existence
* =============================================================================
*
* Task:
* Create a function that checks if a file exists and prints detailed
* information about it.
*
* Requirements:
* - Accept filename as parameter
* - Return 1 if file exists, 0 if not
* - If file doesn't exist, provide helpful message
* - If file exists, try to determine if it's readable
*/
/* Your function prototype */
int check_file_exists(const char *filename);
void exercise2_check_file_existence(void) {
print_exercise_header(2, "Check File Existence");
/* TODO: Implement your solution here */
/* SOLUTION */
/* Implementation of check_file_exists */
/* Test files */
const char *existing = "test_exists.txt";
const char *nonexisting = "this_does_not_exist.txt";
/* Create a test file */
FILE *fp = fopen(existing, "w");
if (fp != NULL) {
fprintf(fp, "Test content\n");
fclose(fp);
}
printf("Testing file existence checker:\n\n");
/* Check existing file */
printf("Checking '%s':\n", existing);
fp = fopen(existing, "r");
if (fp != NULL) {
printf(" β File EXISTS\n");
printf(" β File is READABLE\n");
/* Try to get file size */
fseek(fp, 0, SEEK_END);
long size = ftell(fp);
printf(" β File size: %ld bytes\n", size);
fclose(fp);
} else {
printf(" β File DOES NOT EXIST or is not accessible\n");
printf(" Error: %s\n", strerror(errno));
}
/* Check non-existing file */
printf("\nChecking '%s':\n", nonexisting);
fp = fopen(nonexisting, "r");
if (fp != NULL) {
printf(" β File EXISTS\n");
fclose(fp);
} else {
printf(" β File DOES NOT EXIST\n");
printf(" Error code: %d\n", errno);
printf(" Error message: %s\n", strerror(errno));
printf(" Suggestion: Check the filename and path.\n");
}
/* Clean up */
remove(existing);
}
/* =============================================================================
* EXERCISE 3: Safe File Opener
* =============================================================================
*
* Task:
* Create a robust file opening function with the following features:
* - Validates input parameters
* - Provides detailed error messages
* - Supports verbose and quiet modes
* - Returns NULL on failure with appropriate errno
*/
/* Your function prototype */
FILE *open_file_safely(const char *filename, const char *mode, int verbose);
void exercise3_safe_file_opener(void) {
print_exercise_header(3, "Safe File Opener");
/* TODO: Implement your solution here */
/* SOLUTION */
/* Define the safe opener inline */
FILE *open_safe(const char *filename, const char *mode, int verbose) {
/* Validate parameters */
if (filename == NULL) {
if (verbose) {
fprintf(stderr, "ERROR: Filename is NULL\n");
}
errno = EINVAL;
return NULL;
}
if (mode == NULL) {
if (verbose) {
fprintf(stderr, "ERROR: Mode is NULL\n");
}
errno = EINVAL;
return NULL;
}
if (strlen(filename) == 0) {
if (verbose) {
fprintf(stderr, "ERROR: Filename is empty\n");
}
errno = EINVAL;
return NULL;
}
/* Validate mode */
const char *valid_modes[] = {"r", "w", "a", "r+", "w+", "a+",
"rb", "wb", "ab", "r+b", "w+b", "a+b",
"rb+", "wb+", "ab+"};
int valid = 0;
for (size_t i = 0; i < sizeof(valid_modes)/sizeof(valid_modes[0]); i++) {
if (strcmp(mode, valid_modes[i]) == 0) {
valid = 1;
break;
}
}
if (!valid) {
if (verbose) {
fprintf(stderr, "ERROR: Invalid mode '%s'\n", mode);
}
errno = EINVAL;
return NULL;
}
/* Try to open file */
FILE *fp = fopen(filename, mode);
if (fp == NULL && verbose) {
fprintf(stderr, "ERROR: Cannot open '%s' with mode '%s'\n",
filename, mode);
fprintf(stderr, " Reason: %s\n", strerror(errno));
}
if (fp != NULL && verbose) {
printf("SUCCESS: Opened '%s' in mode '%s'\n", filename, mode);
}
return fp;
}
printf("Testing safe file opener:\n\n");
/* Test 1: Normal operation */
printf("Test 1: Opening file for writing (verbose)\n");
FILE *fp = open_safe("safe_test.txt", "w", 1);
if (fp != NULL) fclose(fp);
remove("safe_test.txt");
/* Test 2: NULL filename */
printf("\nTest 2: NULL filename\n");
fp = open_safe(NULL, "r", 1);
/* Test 3: Invalid mode */
printf("\nTest 3: Invalid mode\n");
fp = open_safe("test.txt", "xyz", 1);
/* Test 4: Non-existent file in read mode */
printf("\nTest 4: Non-existent file in read mode\n");
fp = open_safe("does_not_exist.txt", "r", 1);
/* Test 5: Quiet mode */
printf("\nTest 5: Same error in quiet mode (no output expected)\n");
fp = open_safe(NULL, "r", 0);
printf(" (No error message printed - quiet mode)\n");
printf(" errno is set to: %d (%s)\n", errno, strerror(errno));
}
/* =============================================================================
* EXERCISE 4: File Mode Explorer
* =============================================================================
*
* Task:
* Create a demonstration that shows the behavior of different file modes.
* For each mode, show:
* - What happens when file exists
* - What happens when file doesn't exist
* - Whether content is preserved or lost
*/
void exercise4_file_mode_explorer(void) {
print_exercise_header(4, "File Mode Explorer");
/* TODO: Implement your solution here */
/* SOLUTION */
const char *filename = "mode_test.txt";
FILE *fp;
printf("Exploring file modes:\n\n");
/* Create initial file */
fp = fopen(filename, "w");
if (fp != NULL) {
fprintf(fp, "Original content\n");
fclose(fp);
}
/* Mode "r" */
printf("βββ Mode 'r' (Read) βββ\n");
printf("File exists with content: 'Original content'\n");
fp = fopen(filename, "r");
if (fp != NULL) {
printf("Result: File opened successfully\n");
char buf[50];
fgets(buf, sizeof(buf), fp);
printf("Content: %s", buf);
fclose(fp);
}
printf("\nTrying non-existent file:\n");
fp = fopen("nonexistent.txt", "r");
printf("Result: %s\n\n", fp == NULL ? "NULL returned (correct)" : "Unexpected");
if (fp) fclose(fp);
/* Mode "w" */
printf("βββ Mode 'w' (Write) βββ\n");
printf("Opening existing file in 'w' mode:\n");
fp = fopen(filename, "w");
if (fp != NULL) {
printf("Result: File opened (truncated!)\n");
fclose(fp);
}
fp = fopen(filename, "r");
if (fp != NULL) {
char buf[50];
if (fgets(buf, sizeof(buf), fp) == NULL) {
printf("Content: <empty - file was truncated>\n");
}
fclose(fp);
}
/* Mode "a" */
printf("\nβββ Mode 'a' (Append) βββ\n");
printf("Creating file and appending:\n");
fp = fopen(filename, "w");
if (fp) {
fprintf(fp, "Line 1\n");
fclose(fp);
}
fp = fopen(filename, "a");
if (fp) {
fprintf(fp, "Line 2 (appended)\n");
fclose(fp);
}
fp = fopen(filename, "r");
if (fp) {
printf("Content after append:\n");
char buf[50];
while (fgets(buf, sizeof(buf), fp)) {
printf(" %s", buf);
}
fclose(fp);
}
/* Summary table */
printf("\nβββ Summary Table βββ\n");
printf("ββββββββ¬βββββββββββββββ¬ββββββββββββββββ¬ββββββββββββ\n");
printf("β Mode β File Exists β File Missing β Truncate? β\n");
printf("ββββββββΌβββββββββββββββΌββββββββββββββββΌββββββββββββ€\n");
printf("β r β Open read β NULL β No β\n");
printf("β w β Truncate β Create β YES β\n");
printf("β a β Append β Create β No β\n");
printf("β r+ β Read/Write β NULL β No β\n");
printf("β w+ β Read/Write β Create β YES β\n");
printf("β a+ β Read/Append β Create β No β\n");
printf("ββββββββ΄βββββββββββββββ΄ββββββββββββββββ΄ββββββββββββ\n");
remove(filename);
}
/* =============================================================================
* EXERCISE 5: Comprehensive Error Reporter
* =============================================================================
*
* Task:
* Create a function that attempts various file operations and reports
* detailed error information including errno values and suggestions.
*/
void exercise5_error_reporter(void) {
print_exercise_header(5, "Comprehensive Error Reporter");
/* TODO: Implement your solution here */
/* SOLUTION */
void report_file_error(const char *operation, const char *filename) {
printf("\nββββββββββββββββββββββββββββββββββββββββββ\n");
printf("β FILE OPERATION ERROR REPORT β\n");
printf("ββββββββββββββββββββββββββββββββββββββββββ€\n");
printf("β Operation: %-27s β\n", operation);
printf("β Filename: %-27s β\n", filename);
printf("β Error #: %-27d β\n", errno);
printf("β Message: %-27s β\n", strerror(errno));
printf("ββββββββββββββββββββββββββββββββββββββββββ\n");
/* Provide suggestions based on errno */
printf("\nSuggestion: ");
switch (errno) {
case ENOENT:
printf("File or directory doesn't exist.\n");
printf(" - Check the file path\n");
printf(" - Ensure all parent directories exist\n");
break;
case EACCES:
printf("Permission denied.\n");
printf(" - Check file permissions\n");
printf(" - Try running with elevated privileges\n");
break;
case EEXIST:
printf("File already exists.\n");
printf(" - Use a different filename\n");
printf(" - Delete existing file first\n");
break;
case EISDIR:
printf("Path is a directory, not a file.\n");
printf(" - Append a filename to the path\n");
break;
case EMFILE:
printf("Too many open files.\n");
printf(" - Close some files\n");
printf(" - Increase file descriptor limit\n");
break;
case ENOSPC:
printf("No space left on device.\n");
printf(" - Free up disk space\n");
printf(" - Use a different location\n");
break;
default:
printf("Unknown error - check documentation.\n");
}
}
printf("Testing various error conditions:\n");
/* Test 1: Non-existent file */
printf("\nβββ Test 1: Reading non-existent file βββ");
FILE *fp = fopen("/nonexistent/path/file.txt", "r");
if (fp == NULL) {
report_file_error("fopen (read)", "/nonexistent/path/file.txt");
}
/* Test 2: Permission denied (might not work everywhere) */
printf("\nβββ Test 2: Writing to protected location βββ");
fp = fopen("/etc/protected_test.txt", "w");
if (fp == NULL) {
report_file_error("fopen (write)", "/etc/protected_test.txt");
} else {
fclose(fp);
remove("/etc/protected_test.txt");
}
/* Test 3: Invalid path */
printf("\nβββ Test 3: Directory as file βββ");
fp = fopen("/tmp", "r");
if (fp == NULL) {
report_file_error("fopen (read)", "/tmp");
} else {
fclose(fp);
}
}
/* =============================================================================
* EXERCISE 6: File Copy Utility
* =============================================================================
*
* Task:
* Create a function that copies the contents of one file to another.
* Handle all error conditions properly.
*/
int copy_file(const char *source, const char *destination);
void exercise6_copy_file_contents(void) {
print_exercise_header(6, "File Copy Utility");
/* TODO: Implement your solution here */
/* SOLUTION */
/* Create source file */
FILE *fp = fopen("source.txt", "w");
if (fp != NULL) {
fprintf(fp, "This is line 1 of the source file.\n");
fprintf(fp, "This is line 2 of the source file.\n");
fprintf(fp, "This is line 3 of the source file.\n");
fclose(fp);
}
printf("Copying 'source.txt' to 'destination.txt'\n\n");
/* Open source for reading */
FILE *src = fopen("source.txt", "r");
if (src == NULL) {
perror("Error opening source file");
return;
}
/* Open destination for writing */
FILE *dst = fopen("destination.txt", "w");
if (dst == NULL) {
perror("Error opening destination file");
fclose(src);
return;
}
/* Copy contents */
char buffer[256];
int lines_copied = 0;
while (fgets(buffer, sizeof(buffer), src) != NULL) {
if (fputs(buffer, dst) == EOF) {
perror("Error writing to destination");
break;
}
lines_copied++;
}
/* Check for read errors */
if (ferror(src)) {
perror("Error reading from source");
}
/* Close files */
fclose(src);
fclose(dst);
printf("Copy complete! %d lines copied.\n\n", lines_copied);
/* Verify by reading destination */
printf("Contents of destination.txt:\n");
printf("βββββββββββββββββββββββββββ\n");
dst = fopen("destination.txt", "r");
if (dst != NULL) {
while (fgets(buffer, sizeof(buffer), dst) != NULL) {
printf(" %s", buffer);
}
fclose(dst);
}
/* Clean up */
remove("source.txt");
remove("destination.txt");
}
/* =============================================================================
* EXERCISE 7: Multiple File Handler
* =============================================================================
*
* Task:
* Create a program that opens multiple files, processes them, and properly
* cleans up all resources even if an error occurs.
*/
void exercise7_multiple_file_handler(void) {
print_exercise_header(7, "Multiple File Handler");
/* TODO: Implement your solution here */
/* SOLUTION */
FILE *files[5] = {NULL, NULL, NULL, NULL, NULL};
const char *names[] = {"file1.txt", "file2.txt", "file3.txt",
"file4.txt", "file5.txt"};
int num_files = 5;
int files_opened = 0;
int success = 1;
printf("Opening %d files:\n", num_files);
/* Open all files */
for (int i = 0; i < num_files; i++) {
files[i] = fopen(names[i], "w");
if (files[i] == NULL) {
fprintf(stderr, " β Failed to open '%s': %s\n",
names[i], strerror(errno));
success = 0;
break;
}
printf(" β Opened '%s'\n", names[i]);
files_opened++;
}
if (success) {
printf("\nWriting to all files:\n");
/* Write to all files */
for (int i = 0; i < num_files; i++) {
fprintf(files[i], "This is file #%d\n", i + 1);
fprintf(files[i], "Created by multiple file handler exercise.\n");
printf(" β Wrote to '%s'\n", names[i]);
}
}
/* Close all opened files (even on error) */
printf("\nClosing files:\n");
for (int i = 0; i < files_opened; i++) {
if (files[i] != NULL) {
if (fclose(files[i]) == 0) {
printf(" β Closed '%s'\n", names[i]);
} else {
printf(" β Error closing '%s'\n", names[i]);
}
files[i] = NULL;
}
}
/* Verify one file */
if (success) {
printf("\nVerifying 'file1.txt':\n");
FILE *fp = fopen("file1.txt", "r");
if (fp != NULL) {
char buffer[100];
while (fgets(buffer, sizeof(buffer), fp)) {
printf(" %s", buffer);
}
fclose(fp);
}
}
/* Clean up all files */
printf("\nCleaning up:\n");
for (int i = 0; i < num_files; i++) {
if (remove(names[i]) == 0) {
printf(" β Removed '%s'\n", names[i]);
}
}
}
/* =============================================================================
* EXERCISE 8: Stream Redirector
* =============================================================================
*
* Task:
* Create a logging utility that redirects stdout to a file temporarily,
* then restores it.
*/
void exercise8_stream_redirector(void) {
print_exercise_header(8, "Stream Redirector");
/* TODO: Implement your solution here */
/* SOLUTION */
printf("This message goes to normal stdout.\n\n");
printf("Implementing a simple logging system:\n");
printf("βββββββββββββββββββββββββββββββββββββ\n\n");
/* Save original stdout using file descriptor */
int stdout_fd = dup(fileno(stdout));
/* Open log file */
FILE *log = fopen("output.log", "w");
if (log == NULL) {
perror("Cannot open log file");
return;
}
printf("Redirecting next 3 printf calls to 'output.log'...\n\n");
/* Redirect stdout to log file */
fflush(stdout);
dup2(fileno(log), fileno(stdout));
/* These go to the log file */
printf("Log entry 1: Program started\n");
printf("Log entry 2: Processing data\n");
printf("Log entry 3: Processing complete\n");
/* Restore stdout */
fflush(stdout);
dup2(stdout_fd, fileno(stdout));
close(stdout_fd);
fclose(log);
printf("stdout restored. Messages went to log file.\n\n");
/* Read and display log contents */
printf("Contents of output.log:\n");
printf("βββββββββββββββββββββββ\n");
log = fopen("output.log", "r");
if (log != NULL) {
char buffer[100];
while (fgets(buffer, sizeof(buffer), log)) {
printf(" %s", buffer);
}
fclose(log);
}
remove("output.log");
}
/* =============================================================================
* EXERCISE 9: File Statistics
* =============================================================================
*
* Task:
* Create a function that analyzes a text file and reports:
* - Number of characters
* - Number of words
* - Number of lines
* - File size in bytes
*/
void exercise9_file_statistics(void) {
print_exercise_header(9, "File Statistics");
/* TODO: Implement your solution here */
/* SOLUTION */
/* Create a sample file */
const char *filename = "sample.txt";
FILE *fp = fopen(filename, "w");
if (fp != NULL) {
fprintf(fp, "Hello World!\n");
fprintf(fp, "This is a sample text file.\n");
fprintf(fp, "It contains multiple lines.\n");
fprintf(fp, "We will count characters, words, and lines.\n");
fclose(fp);
}
/* Analyze the file */
fp = fopen(filename, "r");
if (fp == NULL) {
perror("Cannot open file");
return;
}
long characters = 0;
long words = 0;
long lines = 0;
int in_word = 0;
int ch;
while ((ch = fgetc(fp)) != EOF) {
characters++;
if (ch == '\n') {
lines++;
}
/* Count words (space/newline/tab separated) */
if (ch == ' ' || ch == '\n' || ch == '\t') {
if (in_word) {
words++;
in_word = 0;
}
} else {
in_word = 1;
}
}
/* Count last word if file doesn't end with whitespace */
if (in_word) {
words++;
}
/* Get file size */
fseek(fp, 0, SEEK_END);
long file_size = ftell(fp);
fclose(fp);
/* Display statistics */
printf("File: %s\n\n", filename);
printf("βββββββββββββββββββββββββββββββββββββββββ\n");
printf("β FILE STATISTICS β\n");
printf("βββββββββββββββββββββββββββββββββββββββββ€\n");
printf("β Characters: %-20ld β\n", characters);
printf("β Words: %-20ld β\n", words);
printf("β Lines: %-20ld β\n", lines);
printf("β File size: %-17ld bytesβ\n", file_size);
printf("βββββββββββββββββββββββββββββββββββββββββ\n");
/* Display file contents for reference */
printf("\nFile contents:\n");
printf("βββββββββββββββββββββββββββββββββββββββββ\n");
fp = fopen(filename, "r");
if (fp != NULL) {
char buffer[100];
while (fgets(buffer, sizeof(buffer), fp)) {
printf(" %s", buffer);
}
fclose(fp);
}
remove(filename);
}
/* =============================================================================
* EXERCISE 10: Binary File Creator
* =============================================================================
*
* Task:
* Create a program that:
* 1. Creates a binary file with structured data
* 2. Reads it back
* 3. Verifies data integrity
*/
void exercise10_binary_file_creator(void) {
print_exercise_header(10, "Binary File Creator");
/* TODO: Implement your solution here */
/* SOLUTION */
struct Student {
int id;
char name[50];
float gpa;
};
const char *filename = "students.bin";
/* Create sample data */
struct Student students[] = {
{1001, "Alice Johnson", 3.85},
{1002, "Bob Smith", 3.42},
{1003, "Carol Williams", 3.91},
{1004, "David Brown", 3.15},
{1005, "Eve Davis", 3.78}
};
int num_students = sizeof(students) / sizeof(students[0]);
printf("Creating binary file with student records:\n\n");
/* Write to binary file */
FILE *fp = fopen(filename, "wb");
if (fp == NULL) {
perror("Cannot create binary file");
return;
}
/* Write number of records first */
fwrite(&num_students, sizeof(int), 1, fp);
/* Write all student records */
size_t written = fwrite(students, sizeof(struct Student), num_students, fp);
printf("Wrote %zu student records.\n\n", written);
fclose(fp);
/* Read back from binary file */
printf("Reading back from binary file:\n");
printf("ββββββββββββββββββββββββββββββ\n\n");
fp = fopen(filename, "rb");
if (fp == NULL) {
perror("Cannot open binary file");
return;
}
/* Read number of records */
int count;
fread(&count, sizeof(int), 1, fp);
printf("Number of records: %d\n\n", count);
/* Read and display each record */
printf("ββββββββ¬βββββββββββββββββββββ¬ββββββββ\n");
printf("β ID β Name β GPA β\n");
printf("ββββββββΌβββββββββββββββββββββΌββββββββ€\n");
struct Student loaded;
int verified = 1;
for (int i = 0; i < count; i++) {
fread(&loaded, sizeof(struct Student), 1, fp);
printf("β %4d β %-18s β %5.2f β\n",
loaded.id, loaded.name, loaded.gpa);
/* Verify data integrity */
if (loaded.id != students[i].id ||
strcmp(loaded.name, students[i].name) != 0 ||
loaded.gpa != students[i].gpa) {
verified = 0;
}
}
printf("ββββββββ΄βββββββββββββββββββββ΄ββββββββ\n\n");
printf("Data integrity check: %s\n",
verified ? "β PASSED" : "β FAILED");
fclose(fp);
remove(filename);
}
/* =============================================================================
* ANSWER KEY AND EXPLANATIONS
* =============================================================================
*
* EXERCISE 1: Simple File Creation
* --------------------------------
* Key concepts:
* - fopen() with "w" mode creates a new file or truncates existing
* - Always check fopen() return value for NULL
* - Use fprintf() to write formatted text
* - Always fclose() after you're done
* - Use fgets() in a loop to read file line by line
*
* EXERCISE 2: Check File Existence
* --------------------------------
* Key concepts:
* - Opening in "r" mode fails if file doesn't exist
* - fseek(fp, 0, SEEK_END) + ftell(fp) gives file size
* - Always close file even when just checking existence
* - strerror(errno) gives human-readable error message
*
* EXERCISE 3: Safe File Opener
* ----------------------------
* Key concepts:
* - Validate all input parameters before use
* - Check for NULL and empty strings
* - Validate mode strings against known valid modes
* - errno should be set on error
* - Verbose mode allows caller to control error output
*
* EXERCISE 4: File Mode Explorer
* ------------------------------
* Key concepts:
* - "r" fails if file doesn't exist
* - "w" ALWAYS truncates/creates - USE WITH CAUTION
* - "a" preserves content, writes at end
* - "+" modes add both read and write capability
* - Binary modes ("rb", "wb") important for non-text data
*
* EXERCISE 5: Comprehensive Error Reporter
* ----------------------------------------
* Key concepts:
* - errno is set by failed system calls
* - Different errno values indicate different problems
* - Providing suggestions based on error helps users
* - perror() and strerror() format error messages
*
* EXERCISE 6: File Copy Utility
* -----------------------------
* Key concepts:
* - Open source for reading, destination for writing
* - Use a buffer with fgets()/fputs() for text files
* - Check for both read and write errors
* - Close both files even if copying fails
* - ferror() checks if stream encountered an error
*
* EXERCISE 7: Multiple File Handler
* ---------------------------------
* Key concepts:
* - Initialize all file pointers to NULL
* - Track how many files were successfully opened
* - Close ALL opened files in cleanup, even on error
* - Loop cleanup handles partial success scenarios
*
* EXERCISE 8: Stream Redirector
* -----------------------------
* Key concepts:
* - dup() duplicates a file descriptor
* - dup2() redirects one descriptor to another
* - fileno() gets file descriptor from FILE*
* - fflush() before redirecting ensures buffered data written
* - Restore original descriptor when done
*
* EXERCISE 9: File Statistics
* ---------------------------
* Key concepts:
* - fgetc() reads one character at a time
* - Track state (in_word) to count words correctly
* - Count lines by counting newline characters
* - fseek() + ftell() for file size
* - EOF marks end of file
*
* EXERCISE 10: Binary File Creator
* --------------------------------
* Key concepts:
* - Use "wb" and "rb" for binary mode
* - fwrite() writes raw binary data
* - fread() reads raw binary data
* - Structure padding may affect binary file portability
* - Write metadata (count) before actual data for reading
*
* =============================================================================
*/