Arrays

Declaring, initializing, and accessing elements of arrays. Working with single and multi-dimensional arrays.


Arrays and Strings in C

Arrays

An array is a data structure that stores a fixed-size sequential collection of elements of the same type. Each element in an array can be accessed using its index, which typically starts from 0 in C.

Key characteristics of arrays:

  • Homogeneous: All elements must be of the same data type.
  • Contiguous memory allocation: Elements are stored in adjacent memory locations.
  • Fixed size: The size of the array must be known at compile time (or dynamically allocated using functions like malloc, but even then, the maximum size is typically known when allocating).
  • Indexed access: Elements are accessed using their index, starting from 0.

Example of array declaration and initialization:

 int numbers[5]; // Declares an integer array of size 5
    numbers[0] = 10; // Assigns the value 10 to the first element
    numbers[1] = 20;
    numbers[2] = 30;
    numbers[3] = 40;
    numbers[4] = 50;

    // Alternatively, initialize during declaration:
    int scores[] = {95, 87, 92, 78, 99}; // Size is implicitly 5

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

    for (int i = 0; i < 5; i++) {
        printf("scores[%d] = %d\n", i, scores[i]);
    } 

Strings

In C, strings are not a built-in data type like in some other languages. Instead, they are represented as arrays of characters. The end of a string is marked by a special character called the null terminator, which is represented by '\0'.

C-style Strings as Character Arrays and Null Termination

A C-style string is simply an array of characters that is terminated by a null character ('\0'). This null terminator signals the end of the string to functions that process it.

Example of a string declaration:

 char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'}; // Explicit null termination
    char message[] = "Hello"; // Equivalent to the above; null termination is implicit
    printf("%s\n", greeting); // Output: Hello
    printf("%s\n", message);  // Output: Hello 

In the second example, the compiler automatically adds the null terminator to the end of the string literal "Hello".

Important: When declaring a character array to store a string, you need to allocate enough space for all the characters in the string *plus* the null terminator. Failing to do so can lead to buffer overflows and unpredictable behavior.

Common String Manipulation Functions

The string.h header file provides a number of functions for working with C-style strings.

  • strlen(str): Returns the length of the string str (excluding the null terminator).
  • strcpy(dest, src): Copies the string src to the string dest. Important: Ensure that dest has enough space to hold src, including the null terminator, to avoid buffer overflows.
  • strncpy(dest, src, n): Copies at most n characters from string src to string dest. If src has fewer than n characters, the rest of dest will be padded with null characters. If src has n or more characters, dest may not be null-terminated; you may need to manually add the null terminator.
  • strcat(dest, src): Appends the string src to the end of the string dest. Important: Ensure that dest has enough space to hold the combined string, including the null terminator, to avoid buffer overflows.
  • strncat(dest, src, n): Appends at most n characters from string src to the end of the string dest. Ensures dest is null-terminated.
  • strcmp(str1, str2): Compares the strings str1 and str2 lexicographically. Returns:
    • 0 if str1 and str2 are equal.
    • A negative value if str1 comes before str2.
    • A positive value if str1 comes after str2.
  • strncmp(str1, str2, n): Compares at most n characters of the strings str1 and str2 lexicographically.
  • strstr(haystack, needle): Finds the first occurrence of the substring needle in the string haystack. Returns a pointer to the beginning of the located substring, or NULL if the substring is not found.
  • strchr(str, character): Finds the first occurrence of the character character in the string str. Returns a pointer to the location of the character, or NULL if not found.
  • strrchr(str, character): Finds the last occurrence of the character character in the string str. Returns a pointer to the location of the character, or NULL if not found.

Buffer Overflow Considerations: The strcpy and strcat functions are particularly prone to buffer overflows if the destination buffer is not large enough. It's generally safer to use strncpy and strncat, which allow you to specify a maximum number of characters to copy, helping to prevent overflows. However, remember that strncpy might not null-terminate the destination string, so you may need to add the null terminator manually.

Examples of String Processing Using Arrays

Example 1: Counting vowels in a string

 #include <stdio.h>
    #include <string.h>
    #include <ctype.h> // For tolower()

    int countVowels(char str[]) {
        int count = 0;
        int len = strlen(str);

        for (int i = 0; i < len; i++) {
            char ch = tolower(str[i]); // Convert to lowercase for case-insensitive counting
            if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u') {
                count++;
            }
        }

        return count;
    }

    int main() {
        char text[] = "Hello World!";
        int vowelCount = countVowels(text);
        printf("Number of vowels in '%s': %d\n", text, vowelCount);
        return 0;
    } 

Example 2: Reversing a String

 #include <stdio.h>
    #include <string.h>

    void reverseString(char str[]) {
        int len = strlen(str);
        int i, j;
        char temp;

        for (i = 0, j = len - 1; i < j; i++, j--) {
            temp = str[i];
            str[i] = str[j];
            str[j] = temp;
        }
    }

    int main() {
        char text[] = "Reverse me!";
        printf("Original string: %s\n", text);
        reverseString(text);
        printf("Reversed string: %s\n", text);
        return 0;
    } 

Example 3: Checking if a string is a palindrome.

 #include  #include  #include  #include  bool isPalindrome(char str[]) {
    int len = strlen(str);
    int i, j;

    // Convert string to lowercase and remove non-alphanumeric characters (optional)
    char cleanStr[len + 1];  // +1 for the null terminator
    int cleanIndex = 0;
    for (i = 0; i < len; i++) {
        if (isalnum(str[i])) {  // Check if alphanumeric
            cleanStr[cleanIndex++] = tolower(str[i]);
        }
    }
    cleanStr[cleanIndex] = '\0';  // Null-terminate the clean string
    len = strlen(cleanStr);       // Update len to new string length


    for (i = 0, j = len - 1; i < j; i++, j--) {
        if (cleanStr[i] != cleanStr[j]) {
            return false;
        }
    }
    return true;
}

int main() {
    char str1[] = "racecar";
    char str2[] = "A man, a plan, a canal: Panama";
    char str3[] = "hello";

    if (isPalindrome(str1)) {
        printf("\"%s\" is a palindrome.\n", str1);
    } else {
        printf("\"%s\" is not a palindrome.\n", str1);
    }

    if (isPalindrome(str2)) {
        printf("\"%s\" is a palindrome.\n", str2);
    } else {
        printf("\"%s\" is not a palindrome.\n", str2);
    }

     if (isPalindrome(str3)) {
        printf("\"%s\" is a palindrome.\n", str3);
    } else {
        printf("\"%s\" is not a palindrome.\n", str3);
    }


    return 0;
}