BIT102 C Programming

C ProgrammingUnit 810 min read

Strings & File Handling: Manipulation & Persistent Data

Unit 8 of C Programming: Explores string operations (manipulation, functions, and memory handling) alongside file handling (creation, reading, writing, and modes), with practical examples and real-world applications in data storage and processing.

TAKEAWAYS:

  • Strings in C are null-terminated character arrays (char str[10] = "hello";), requiring careful memory management.
  • Key string functions (strlen, strcpy, strcat, strstr) simplify manipulation but must be used safely to avoid buffer overflows.
  • File handling in C uses FILE* pointers and functions like fopen, fclose, fprintf, and fscanf to manage persistent data.
  • File modes ("r", "w", "a", "r+") determine read/write behavior, critical for data integrity.
  • Dynamic memory allocation (malloc, realloc) is essential for strings and files to handle variable-sized data.
  • Real-world applications include eSewa transaction logs, Daraz order databases, and Ncell call records.

1. Strings in C

Strings in C are arrays of characters terminated by a null character (\0). They are not a built-in data type but are handled using character arrays.

1.1 Declaration and Initialization

char str1[10] = "hello";  // Fixed-size array
char str2[] = "world";     // Size inferred from content
char str3[5];              // Empty array (no null terminator)

1.2 String Functions

C provides a library of string functions in <string.h> for manipulation:

Function Description
strlen() Returns the length of a string (excluding \0).
strcpy() Copies one string to another (risky if destination is too small).
strcat() Concatenates two strings (destination must have enough space).
strstr() Searches for a substring within a string.
strcmp() Compares two strings lexicographically.
strrev() Reverses a string (not standard in all compilers).

Example: Safe String Copy

flowchart TD
    A["Start"] --> B["Declare source and destination arrays"]
    B --> C["Check if destination has enough space"]
    C -->|"Yes"| D["Use strcpy_s() (safe version)"]
    C -->|"No"| E["Error: Buffer overflow risk"]
    D --> F["End"]
    E --> F

1.3 Memory Management and Buffer Overflow

Strings in C are not automatically resized. Writing beyond the array bounds causes buffer overflow, a critical security vulnerability.

Example: Unsafe vs. Safe String Copy

// UNSAFE: No bounds checking
char dest[5];
char src[] = "hello";
strcpy(dest, src);  // CRASH: dest only holds 4 chars + '\0'

// SAFE: Use strcpy_s (C11 standard)
strcpy_s(dest, sizeof(dest), src);  // Checks bounds

1.4 Dynamic String Allocation

For strings of unknown size, use malloc and realloc:

char *dynamicStr = (char*)malloc(10 * sizeof(char));
if (dynamicStr == NULL) {
    printf("Memory allocation failed!");
} else {
    strcpy(dynamicStr, "hello");
    printf("String: %s\n", dynamicStr);
    free(dynamicStr);  // Always free allocated memory!
}

2. File Handling in C

Files allow persistent data storage, essential for applications like eSewa transaction records or Daraz inventory logs.

2.1 File Pointers and Modes

Files are accessed via FILE* pointers. Common modes:

Mode Description
"r" Open for reading (file must exist).
"w" Open for writing (creates file or truncates existing).
"a" Open for appending (creates file if missing).
"r+" Open for reading and writing (file must exist).
"w+" Open for writing and reading (creates file or truncates).

Example: Opening a File

FILE *file = fopen("example.txt", "w");
if (file == NULL) {
    printf("Error opening file!\n");
} else {
    fprintf(file, "Hello, File Handling!");
    fclose(file);  // Always close files!
}

2.2 Writing to a File

Use fprintf to write formatted data:

FILE *file = fopen("numbers.txt", "w");
int num = 42;
fprintf(file, "The answer is %d\n", num);
fclose(file);

2.3 Reading from a File

Use fscanf to read formatted data:

FILE *file = fopen("numbers.txt", "r");
int num;
if (fscanf(file, "%d", &num) == 1) {
    printf("Read: %d\n", num);
}
fclose(file);

2.4 Reading Line by Line

Use fgets to read entire lines (including spaces):

FILE *file = fopen("data.txt", "r");
char line[100];
while (fgets(line, sizeof(line), file) != NULL) {
    printf("%s", line);
}
fclose(file);

3. Real-World Applications

In the Real World

  1. eSewa Transaction Logs

    • Idea: Files store transaction records (e.g., transactions.txt).
    • How: Each transaction is written as a line (e.g., "2024-05-20|12345|1000").
    • Why: Persistent storage for auditing and fraud detection.
  2. Daraz Order Processing

    • Idea: Orders are stored in a file (orders.txt) with fields like order_id, customer, items.
    • How: Each order is appended to the file using "a" mode.
    • Why: Tracks inventory and customer history.
  3. Ncell Call Records

    • Idea: Call logs are written to files (calls.txt) with timestamps and durations.
    • How: fprintf writes each call as timestamp|duration|phone_number.
    • Why: Billing and usage analytics.

4. Worked Example: Merging Two Files

Problem: Merge num1.txt and num2.txt into file3.txt.

Approach:

  1. Open all three files.
  2. Read integers from num1.txt and write to file3.txt.
  3. Repeat for num2.txt.
#include <stdio.h>
void mergeFiles() {
    FILE *f1 = fopen("num1.txt", "r");
    FILE *f2 = fopen("num2.txt", "r");
    FILE *f3 = fopen("file3.txt", "w");

    int num;
    while (fscanf(f1, "%d", &num) == 1) {
        fprintf(f3, "%d ", num);
    }
    while (fscanf(f2, "%d", &num) == 1) {
        fprintf(f3, "%d ", num);
    }
    fclose(f1); fclose(f2); fclose(f3);
}

Trace:

Step num1.txt num2.txt file3.txt (State)
1 10 20 (empty)
2 20 20 10
3 (EOF) 20 10 20
4 (EOF) 10 20 20

5. Advantages and Disadvantages of Global Variables

Advantages Disadvantages
Accessible from any function. Risk of unintended modifications.
Reduces need for passing arguments. Hard to debug (side effects).
Useful for constants (e.g., PI). Violates encapsulation principles.

6. Exam Tips

  1. String Handling:

    • Always check array bounds when copying/concatenating strings.
    • Prefer strcpy_s (safe) over strcpy (unsafe).
    • Understand strlen and strcat pitfalls (e.g., buffer overflow).
  2. File Handling:

    • Always close files (fclose) to free system resources.
    • Use fopen checks (if (file == NULL)) to handle errors.
    • Know the difference between "r" (read-only) and "r+" (read/write).
  3. Common Pitfalls:

    • Forgetting to include <stdio.h> or <string.h>.
    • Not freeing dynamically allocated memory.
    • Assuming files exist without checking (fopen returns NULL if file missing).
  4. Practical Focus:

    • Expect file manipulation questions (merge, copy, reverse).
    • String problems often test strcpy, strcat, or dynamic allocation.
    • Real-world tie-ins (e.g., "How would you store Daraz orders?") are likely.

7. Key Code Examples

Example 1: Reverse a String

#include <stdio.h>
#include <string.h>
void reverseString(char *str) {
    int len = strlen(str);
    for (int i = 0; i < len / 2; i++) {
        char temp = str[i];
        str[i] = str[len - 1 - i];
        str[len - 1 - i] = temp;
    }
}

Trace: Input: "hello" Step 1: Swap 'h' (0) ↔ 'o' (4) → "oellh" Step 2: Swap 'e' (1) ↔ 'l' (3) → "oellh" (no change, middle element).

Example 2: Copy File in Reverse

#include <stdio.h>
void copyReverse(const char *src, const char *dest) {
    FILE *in = fopen(src, "r");
    FILE *out = fopen(dest, "w");
    char ch;
    while (fscanf(in, "%c", &ch) == 1) {
        // Read all chars first, then write in reverse
    }
    rewind(in);  // Reset file pointer
    char buffer[1000];
    size_t bytesRead;
    while ((bytesRead = fread(buffer, 1, sizeof(buffer), in)) > 0) {
        for (int i = bytesRead - 1; i >= 0; i--) {
            fputc(buffer[i], out);
        }
    }
    fclose(in); fclose(out);
}

8. Summary Table: File Modes

Mode Creation Behavior Read/Write Example Use Case
"r" Fails if missing Read-only Reading existing data.
"w" Creates or truncates Write-only Writing new data.
"a" Creates if missing Append-only Adding to existing files.
"r+" Fails if missing Read/write Updating existing data.
"w+" Creates or truncates Read/write Overwriting and reading.

9. Visual Recap

Figure 1: String Memory Layout

Address: 1000 1001 1002 1003 1004 1005 1006
Value:   'h'   'e'   'l'   'l'   'o'   '\0'  (unused)
String:  "hello"

Figure 2: File Handling Flowchart

flowchart TD
    A["Start"] --> B{"File Exist?"}
    B -->|"Yes"| C["Open in 'r' mode"]
    B -->|"No"| D["Open in 'w' mode"]
    C --> E["Read/Write Data"]
    D --> E
    E --> F["Close File"]
    F --> G["End"]

Final Note: Master string bounds checking and file handling modes—these are the most tested concepts. Practice merging/copying files and reversing strings to build intuition. For exams, always include error handling (e.g., fopen checks) and memory management (e.g., free).

Based on the TU BIT syllabus for C Programming (BIT102), unit 8.

Discussion

Loading…