Elective Programming In C

Programming In CUnit 911 min read

Strings, Functions & Debugging: Handling Text in C

Unit 9 of Programming In C covers string manipulation (declaration, input/output, functions), debugging techniques (logical errors, syntax errors, testing), and practical applications of strings in real-world systems like eSewa’s transaction logs or Daraz’s search filters.

TAKEAWAYS:

  • Strings in C are null-terminated character arrays (char str[10] = "hello";), not built-in types, requiring special functions (strlen, strcpy, etc.).
  • String functions (strcat, strcmp, strstr) perform operations like concatenation, comparison, and substring search—critical for parsing user input (e.g., eSewa’s PIN validation).
  • Debugging involves logical error detection (e.g., infinite loops in Pathao’s ride-matching algorithm) and testing (unit tests for Ncell’s SMS gateway).
  • Unions vs. structures: Unions share memory (saving space for NEPSE’s stock records), while structures allocate separate memory (better for Daraz’s order structs with multiple fields).
  • String handling pitfalls: Buffer overflows (e.g., gets()) can crash programs; always use fgets() or scanf("%s", str, size).
  • Real-world tie: Kathmandu’s traffic management uses string hashing to prioritize routes (e.g., hash("Ring Road") maps to a traffic light controller).

1. Strings in C: Definition and Basics

Strings in C are arrays of characters terminated by a null character ('\0'). Unlike other languages, C does not have a native string type, so we use char arrays and special functions from <string.h>.

How Strings Work

  • Declaration:
    char name[20];          // Uninitialized string (garbage values)
    char greeting[] = "Hello"; // Automatically adds '\0'
    
  • Null terminator: Every string must end with '\0' (ASCII 0). Without it, functions like strlen() behave unpredictably.

Visual: String Storage in Memory

Key Point: The null terminator marks the end of the string. Forgetting it causes buffer overflows (e.g., strcpy(dest, src) without checking dest's size).

'H'0'e'1'l'2'l'3'o'4'\0'5
String "Hello" stored in memory (null-terminated)

2. String Input/Output

Common Functions

Function Purpose Example
scanf("%s", str) Reads a string (stops at whitespace) scanf("%s", name);
gets(str) Deprecated: Reads until \n (unsafe!) Avoid in exams!
fgets(str, n, fp) Safe: Reads n-1 chars or until \n fgets(input, 100, stdin);
puts(str) Prints string + newline puts("Hello");
printf("%s", str) Prints string (no newline) printf("%s\n", str);

Worked Example: Safe String Input

Problem: Read a user’s name (max 50 chars) safely.

#include <stdio.h>
int main() {
    char name[51]; // 50 chars + '\0'
    printf("Enter name: ");
    fgets(name, 51, stdin); // Safe: stops at 50 chars or '\n'
    printf("You entered: %s", name);
    return 0;
}

Trace:

Step name Array (Memory) Explanation
Input `K a
Output Prints Kathmandu (truncates \n). printf stops at '\0'.

Real-World Tie:

  • eSewa’s PIN Input: Uses fgets() to read 6-digit PINs safely, preventing buffer overflows that could crash the system.
  • Khalti’s Transaction IDs: Stored as strings (e.g., "TXN12345") and validated using strncmp() to check length.

3. String Manipulation Functions

Essential Functions

Function Purpose Example
strlen(str) Returns length (excluding '\0') len = strlen("Hi"); → 2
strcpy(dest, src) Copies src to dest strcpy(copy, "Hello");
strcat(dest, src) Concatenates src to dest strcat(str, " World");
strcmp(str1, str2) Compares strings (returns <0, 0, >0) strcmp("a", "b") → -1
strchr(str, ch) Finds first occurrence of ch ptr = strchr("hello", 'e');
strstr(str, substr) Finds substring ptr = strstr("hello", "ell");

Visual: strcpy Operation

Pitfall: strcpy does not check buffer size. Always ensure dest has enough space:

char dest[10];
strcpy(dest, "HelloWorld"); // **Buffer Overflow!** (needs 11 bytes)

Worked Example: Concatenate Two Strings

Problem: Combine "Hello" and "World" with a space.

#include <string.h>
int main() {
    char str1[20] = "Hello";
    char str2[] = "World";
    strcat(str1, " "); // Add space
    strcat(str1, str2);
    printf("%s", str1); // Output: "Hello World"
    return 0;
}

Trace:

Step str1 Array Action
Initial `H e
After strcat(str1, " ") `H e
After strcat(str1, str2) `H e

Real-World Tie:

  • Daraz’s Search Filter: Uses strstr() to find products matching keywords (e.g., strstr("Samsung Galaxy", "Galaxy")).
  • Ncell’s SMS Gateway: Concatenates sender names and messages using strcat before sending.

strcmp Behavior

Comparison Return Value
str1 == str2 0
str1 < str2 Negative
str1 > str2 Positive

Example:

strcmp("apple", "banana") → Negative (because 'a' < 'b')
strcmp("apple", "apple") → 0

Worked Example: Validate eSewa PIN

Problem: Check if a 6-digit PIN is numeric.

#include <string.h>
#include <ctype.h>
int isNumericPIN(char pin[]) {
    if (strlen(pin) != 6) return 0;
    for (int i = 0; i < 6; i++) {
        if (!isdigit(pin[i])) return 0;
    }
    return 1;
}

Trace:

Input PIN strlen(pin) Loop Checks (isdigit) Result
"12345" 5 N/A 0 (too short)
"12A45" 5 Fails at 'A' 0 (non-digit)
"123456" 6 All digits 1 (valid)

Real-World Tie:

  • eSewa’s PIN Validation: Uses strlen and isdigit to ensure PINs are exactly 6 digits.
  • Bank ATMs: Compare PINs using strcmp (e.g., strcmp(userPIN, "1234")).

5. Debugging and Testing Strings

  1. Buffer Overflow:
    char small[5];
    strcpy(small, "Hello"); // Crashes! Needs 6 bytes.
    
  2. Forgetting Null Terminator:
    char str[] = {'H', 'i'}; // Missing '\0' → Undefined behavior.
    
  3. Off-by-One Errors:
    for (int i = 0; i <= strlen(str); i++) // Accesses beyond '\0'!
    

Debugging Techniques

  • Print Debugging: Insert printf statements to track string values.
    printf("Current string: '%s' (length: %d)\n", str, strlen(str));
    
  • Compiler Warnings: Enable -Wall in GCC to catch unsafe functions like gets().
  • Unit Testing: Test edge cases (empty strings, max-length inputs).

Worked Example: Debugging a String Copy Bug

Buggy Code:

char dest[5];
strcpy(dest, "Hello"); // Buffer overflow!

Fixed Code:

char dest[6]; // 5 chars + '\0'
strncpy(dest, "Hello", 5); // Safe: copies up to 5 chars
dest[5] = '\0'; // Ensure null termination

Real-World Tie:

  • Pathao’s Ride-Matching: Debugging involves checking if strcpy fails when copying driver names (e.g., strcpy(driverName, "Rajesh Kumar") must have a buffer of at least 13 bytes).

6. Unions vs. Structures

Comparison Table

Feature Structure (struct) Union (union)
Memory Allocation Separate for each member Shared (overlapping)
Use Case Multiple fields (e.g., struct Order { char item[50]; int price; }) Exclusive fields (e.g., union Data { int id; float temp; })
Size sizeof(struct) = sum of all members sizeof(union) = size of largest member
Safety Safer (no data corruption) Risky (writing to one field overwrites others)

Visual: Memory Layout

classDiagram
    class Structure {
        +char name[50]
        +int age
    }
    class Union {
        +int id
        +float salary
    }
    Structure : +-----------+-----------+
                | name[50]  | age (4)  |
                +-----------+-----------+
    Union : +---------------------+
            | id (4) or salary (4)|
            +---------------------+

Key Point:

  • Use struct for Daraz’s order records (multiple fields like item, price, quantity).
  • Use union for NEPSE’s stock data (e.g., storing either stockCode or price in the same memory).

7. Practical Applications

Case Study: eSewa Transaction Logs

Problem: Store and search transaction records (ID, amount, timestamp). Solution: Use a struct with string fields.

#include <string.h>
#define MAX_ID 20
#define MAX_TIME 50

struct Transaction {
    char id[MAX_ID];
    float amount;
    char time[MAX_TIME];
};

void searchByID(struct Transaction logs[], int n, char searchID[]) {
    for (int i = 0; i < n; i++) {
        if (strcmp(logs[i].id, searchID) == 0) {
            printf("Found: ID=%s, Amount=%.2f, Time=%s\n",
                   logs[i].id, logs[i].amount, logs[i].time);
        }
    }
}

Trace:

logs Array (3 entries) searchID = "TXN101" Output
`TXN101 500.00 "2023-10-01"`
`TXN102 300.00 "2023-10-02"`
`TXN103 750.00 "2023-10-03"`

Real-World Tie:

  • eSewa’s Backend: Uses struct arrays to store transactions and strcmp to search by ID.
  • Bank Statements: String fields like accountHolder and transactionDate are compared using strncmp.

8. Exam Tip: How to Score Full Marks

  1. For Short Notes (2x5):

    • String Functions: List 3-4 functions with examples (e.g., strlen, strcpy, strcmp).
    • Debugging: Mention logical errors, syntax errors, and testing techniques (unit testing, print debugging).
    • Unions vs. Structures: Compare memory usage and use cases (e.g., "Use union for saving memory in NEPSE’s stock data").
  2. For Programming Questions:

    • Always declare strings with size: char str[50] (not char str[] without input).
    • Use fgets instead of gets: Examiners deduct marks for unsafe functions.
    • Validate inputs: Check strlen before copying (e.g., if (strlen(src) < sizeof(dest))).
    • Trace your code: Show a table of variable changes (like the strcpy example above).
  3. Common Pitfalls to Avoid:

    • Forgetting '\0' in string literals.
    • Using == to compare strings (always use strcmp).
    • Off-by-one errors in loops (e.g., for (i = 0; i <= strlen(str); i++)).

Final Visual: String Handling in Kathmandu Traffic Explanation:

  • Kathmandu’s traffic system uses string hashing to prioritize routes.
  • strstr checks if a route contains keywords like "Ring".
  • strcat builds commands (e.g., "SET_LIGHT_Ring_GREEN").

Based on the PU BE Computer (PU) syllabus for Programming In C, unit 9.

Discussion

Loading…