Advanced C Programming Guide

Arrays, Strings, Functions, Structs, and Sorting

Topic 1: The Core Building Blocks: Arrays, Strings, and Functions

This section covers the fundamental tools in C. Functions allow us to create modular, reusable code. Arrays and strings provide the mechanisms to store and manipulate collections of data.

Arrays

An array is a contiguous block of memory that stores multiple values of the same data type. You can access any element directly using its index, which starts at 0.

// Declaration: type name[size];
int numbers[10];  // An array to hold 10 integers

// Initialization
float grades[5] = {90.5, 88.0, 92.3, 79.9, 85.1};

// Accessing and modifying elements (zero-based index)
numbers[0] = 5;  // Set the first element
numbers[9] = -3; // Set the last element

int first_number = numbers[0]; // Read the first element

Functions

A function is a self-contained block of code that performs a specific task. It helps organize code, making it more readable, maintainable, and reusable. Every C program has at least one function: `main()`.

// Function prototype (declaration)
// Tells the compiler that this function exists
int add(int a, int b);

// main function - program entry point
int main() {
    int sum = add(5, 10); // Function call
    printf("The sum is: %d\n", sum);
    return 0;
}

// Function definition (implementation)
int add(int a, int b) {
    int result = a + b;
    return result; // Returns a value
}

Passing Arrays to Functions

When you pass an array to a function, you are actually passing a pointer to its first element. This means the function can modify the original array. It's crucial to also pass the size of the array so the function knows where to stop.

#include <stdio.h>

// The function takes a pointer to an int (the array) and its size
void printArray(int arr[], int size) {
    printf("Array elements: ");
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
        // arr[i] = 0; // This would modify the *original* array
    }
    printf("\n");
}

int main() {
    int myNumbers[5] = {10, 20, 30, 40, 50};
    // We pass the array and its size
    printArray(myNumbers, 5); 
    return 0;
}

Characters and Strings

In C, there is no built-in string type. A "string" is simply an array of characters (`char`) that ends with a special null-terminator character: `\0`.

The `\0` is critical. It's how functions like `printf` (with `%s`) or `strlen` know where the string ends.

// "Hello" is 5 letters, but needs 6 chars of storage
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};

// The compiler adds the \0 for us with string literals
char greeting_auto[20] = "Hello"; // [H][e][l][l][o][\0][...garbage...]

// Includes the  library for useful functions:
// strlen(str) - returns the length (excluding \0)
// strcpy(dest, src) - copies src string into dest
// strcat(dest, src) - appends src string onto dest
// strcmp(str1, str2) - compares two strings

Simulation: Manual String Length

This function simulates `strlen()` by manually finding the `\0`.

#include <stdio.h>

// A function to calculate string length
int my_strlen(char str[]) {
    int length = 0;
    // Keep counting until we find the null terminator
    while (str[length] != '\0') {
        length++;
    }
    return length;
}

int main() {
    char message[] = "Computer Science";
    int len = my_strlen(message);
    printf("String: '%s'\n", message);
    printf("Length: %d\n", len); // Output: 16
    return 0;
}

Reading and Writing a Sequence of Numbers

You can use a loop to read a sequence of numbers from the user into an array. `scanf` is often used, but be careful as it can lead to bugs if the user enters invalid input. Always check the return value of `scanf`!

#include <stdio.h>

int main() {
    int numbers[5];
    int count = 5;

    printf("Please enter %d integers:\n", count);
    for (int i = 0; i < count; i++) {
        printf("Enter number %d: ", i + 1);
        // We pass the *address* of the array element
        if (scanf("%d", &numbers[i]) != 1) {
            printf("Error reading input.\n");
            return 1; // Exit with an error
        }
    }

    printf("\nYou entered: ");
    for (int i = 0; i < count; i++) {
        printf("%d ", numbers[i]);
    }
    printf("\n");

    return 0;
}

Algorithms: Swapping and Min/Max

Functions are perfect for implementing common algorithms.

Swapping a Sequence (or elements)

To swap two values, you need a temporary variable. To make a reusable `swap` function, you must use pointers so the function can modify the original variables.

#include <stdio.h>

// This function takes pointers to the variables
void swap(int *a, int *b) {
    int temp = *a; // De-reference 'a' to get its value
    *a = *b;       // Set the value at address 'a'
    *b = temp;     // Set the value at address 'b'
}

int main() {
    int x = 10;
    int y = 20;
    printf("Before swap: x = %d, y = %d\n", x, y);
    swap(&x, &y); // Pass the *addresses* of x and y
    printf("After swap:  x = %d, y = %d\n", x, y);
    return 0;
}

Finding Min/Max in an Unsorted Sequence

The strategy is to assume the first element is the min/max, then loop through the rest of the array. If you find a smaller/larger element, update your min/max.

#include <stdio.h>

int findMax(int arr[], int size) {
    // 1. Handle edge case of an empty array
    if (size <= 0) {
        return -1; // Or some error indicator
    }

    // 2. Assume the first element is the max
    int max_val = arr[0];

    // 3. Loop from the *second* element
    for (int i = 1; i < size; i++) {
        // 4. Compare and update if a larger value is found
        if (arr[i] > max_val) {
            max_val = arr[i];
        }
    }
    
    // 5. Return the result
    return max_val;
}

int main() {
    int scores[] = {15, 88, 2, 99, 45, 76};
    int n = 6;
    int max_score = findMax(scores, n);
    printf("The highest score is: %d\n", max_score); // Output: 99
    return 0;
}