Strings in C: Character Arrays & Text Manipulation π€
Mentor's Note: Think of a C string like a chain of train passenger cars containing letters, with one special final carβthe caboose. The caboose is the Null Terminator (
\0). Without the caboose, the system wouldn't know where the train ends, and would keep running down the tracks into garbage memory! π‘
π Educational Content: C strings are a common source of exam questions. Understanding the difference between safe and unsafe input (
fgetsvsscanf/gets) is critical for board exams and security audits.
By the end of this tutorial, you'll know:
- How C represents strings as character arrays with a null-terminator (
\0). - The security risks of
gets()and whyfgets()is the safe alternative. - How to output strings using
printf()andputs(). - How to manually calculate string length, reverse text, and perform palindrome checks.
π The Scenario: Word Scrabble with a Periodβ
Imagine you are playing Scrabble. To write words on the board, you place individual letter tiles side-by-side.
- To indicate that your word is finished, you must place a special black period tile (
.) immediately after the last letter. - If you write
HELLO., everyone knows the word is "HELLO". - If the period is missing, someone reading the board might read your word and then continue reading random tiles left over on the table, resulting in gibberish.
In C programming:
- The letter tiles are the character array.
- The period is the Null Character (
\0). - The word is a String.
π Concept Explanationβ
C does not have a native primitive string data type. Instead, strings are represented as one-dimensional arrays of characters (char) terminated by a special character called the null character (\0).
1. The Null Terminator (\0)β
The null terminator is a character with an ASCII value of 0. It is automatically appended to string literals by the compiler.
- Size Impact: A string of length $N$ requires an array of size at least $N + 1$ to store the null terminator. For example,
"HELLO"needs 6 bytes:HELLO\0
2. Declaration & Initializationβ
char name[6] = "HELLO"; // β
Declares size 6 (5 letters + '\0')
char name[] = "HELLO"; // β
Auto-sizes to 6
char name[6] = {'H', 'E', 'L', 'L', 'O', '\0'}; // β
Manual initialization
3. Reading Input: The Safe vs Unsafe Wayβ
scanf("%s", str): stops reading when it hits whitespace (space, tab, newline). It cannot read a full name like "Raj Patel". Furthermore, it does not check the array size, leading to buffer overflows.gets(str): reads a full line containing spaces. However, it is extremely unsafe because it has no bounds checking. It was officially removed from the C11 standard.fgets(str, size, stdin): The Safe Choice. It reads up tosize - 1characters, preserves spaces, and automatically appends\0.
π§ Algorithm & Step-by-Step Logicβ
Let's design a manual algorithm to check if a string is a Palindrome (reads the same forward and backward, like "radar"):
- Start π
- Find the length of the string,
len(loop untilstr[i] == '\0'). - Set index
start = 0andend = len - 1. - While
start < end:- If
str[start] != str[end], return $0$ (Not a palindrome). - Increment
start, decrementend.
- If
- If the loop completes without mismatches, return $1$ (Is a palindrome).
- End π
π» Implementationsβ
We will write two complete implementations without importing <string.h> to show manual string processing.
1. Safe Input and Manual Length Calculationβ
#include <stdio.h>
// Function to calculate string length manually
int get_string_length(char str[]) {
int length = 0;
while (str[length] != '\0') {
length++;
}
return length;
}
int main() {
char name[20]; // Buffer for 19 characters + '\0'
printf("Enter your name: ");
// Safe input reading
if (fgets(name, sizeof(name), stdin) != NULL) {
// Remove trailing newline character often added by fgets
int len = get_string_length(name);
if (len > 0 && name[len - 1] == '\n') {
name[len - 1] = '\0';
len--;
}
printf("Hello, %s!\n", name);
printf("Length of your name (excluding null terminator): %d\n", len);
}
return 0;
}
// Output:
// Enter your name: Raj Patel
// Hello, Raj Patel!
// Length of your name (excluding null terminator): 9
2. String Reversal and Palindrome Checkβ
#include <stdio.h>
// Returns 1 if palindrome, 0 otherwise
int check_palindrome(char str[], int len) {
int start = 0;
int end = len - 1;
while (start < end) {
if (str[start] != str[end]) {
return 0; // Characters mismatch
}
start++;
end--;
}
return 1; // All match
}
// Reverses a string in-place
void reverse_string(char str[], int len) {
int start = 0;
int end = len - 1;
while (start < end) {
// Swap characters
char temp = str[start];
str[start] = str[end];
str[end] = temp;
start++;
end--;
}
}
int main() {
char word[30] = "radar";
int len = 0;
// Find length
while (word[len] != '\0') {
len++;
}
printf("Original Word: %s\n", word);
if (check_palindrome(word, len)) {
printf("Palindrome status: Yes, it is a palindrome!\n");
} else {
printf("Palindrome status: No, it is not.\n");
}
reverse_string(word, len);
printf("Reversed Word: %s\n", word);
return 0;
}
// Output:
// Original Word: radar
// Palindrome status: Yes, it is a palindrome!
// Reversed Word: radar
π Sample Dry Runβ
Let's dry run the check_palindrome function on the string "level" (length = 5).
| Step | start Index | end Index | str[start] | str[end] | Comparison | Action | Description |
|---|---|---|---|---|---|---|---|
| 1 | 0 | 4 | 'l' | 'l' | 'l' == 'l' | Continue | Outer-most characters match. |
| 2 | 1 | 3 | 'e' | 'e' | 'e' == 'e' | Continue | Inner characters match. |
| 3 | 2 | 2 | 'v' | 'v' | - | Loop terminates | start < end condition ($2 < 2$) becomes false. |
| 4 | - | - | - | - | - | Return 1 | String is determined to be a palindrome. |
π Complexity Analysisβ
| Operation | Time Complexity β±οΈ | Space Complexity πΎ | Reason |
|---|---|---|---|
| Length Calculation | $O(N)$ | $O(1)$ | Must traverse all $N$ characters until hitting \0. |
| String Reversal | $O(N)$ | $O(1)$ | Performs $N/2$ swaps. |
| Palindrome Check | $O(N)$ | $O(1)$ | Checks $N/2$ character pairs. |
π¨ Visual Logic & Diagramsβ
Memory View of name buffer containing "C Code"β
If we allocate char name[10] = "C Code";, the layout is:
Indices: 0 1 2 3 4 5 6 7 8 9
+---+---+---+---+---+---+----+---+---+---+
Values: | C | | C | o | d | e | \0 | ? | ? | ? |
+---+---+---+---+---+---+----+---+---+---+
Note: Elements after index 6 are garbage values (?), but are ignored by string operations because the null terminator is hit at index 6.
π Best Practices & Common Mistakesβ
β Best Practicesβ
- Always leave space for
\0: When defining size, always writechar str[length + 1]. - Always use
fgets(): Never usegets(). - Remove Newlines from
fgets: Remember to check for and remove\nif your program's comparisons are sensitive to whitespace.
β Common Mistakes β οΈβ
- Forgetting the Null Terminator: Declaring
char word[5] = "HELLO";. There is no room for\0, which causes compiler warnings or undefined behavior when printed. - Direct Assignment: Writing
str1 = str2;to copy strings. In C, arrays cannot be assigned directly. You must copy character-by-character or use the standard library functionstrcpy(). - Using
==for comparison: Writingif (str1 == str2)checks if the memory addresses are equal, not the contents. Usestrcmp()or a manual comparison loop.
π― Practice Problemsβ
Easy Level π’β
- Write a program to count the number of vowels in a string.
- Design a program that converts all lowercase characters in a string to uppercase.
Medium Level π‘β
- Write a function
concat_strings(char dest[], char src[])that appends the source string to the end of the destination string manually. - Implement a custom string copy function
copy_string(char dest[], char src[]).
Hard Level π΄β
- Write a program to count the frequency of each character in a given string.
- Design a program that extracts a substring of length $L$ starting from index $I$ of a parent string.
β Frequently Asked Questionsβ
Q: What is the difference between single quotes 'A' and double quotes "A" in C?
Single quotes 'A' represent a single character constant (stored as its ASCII integer value, 65). Double quotes "A" represent a string literal, which is stored as a 2-byte array containing 'A' and the null terminator '\0'.
Q: Why is gets() considered so dangerous?
gets() reads input until a newline is hit, but does not know the size of the target buffer. If a user enters 100 characters into a buffer of size 10, gets() will overwrite adjacent RAM sectors. This security flaw, known as a buffer overflow, has been exploited to hack software for decades.
Q: What standard header contains string utilities?
The standard C library header <string.h> contains functions like strlen() (length), strcpy() (copy), strcmp() (comparison), and strcat() (concatenation). We implement them manually to build foundational logic skills.
β Summaryβ
In this tutorial, you've learned:
- β
Strings in C are character arrays terminated by
\0. - β
The null terminator is required so functions like
printfknow where to stop. - β
fgetsis the secure choice for reading input, preventing buffer overflows. - β You must use loops or library utilities to compare, copy, and modify strings.
- β Traditional string functions are simulated using basic index pointers.
π‘ Interview Tips & Board Focus πβ
- Board Exam Alert: Be ready to write programs for string length, reverse, and palindrome check. These are among the most repeated array questions in board exams.
- Viva Voce Alert: If asked "What is the ASCII value of the null character?", answer: "The ASCII value is 0 (not to be confused with character '0' which has ASCII 48)."
- Key Terms: Null Terminator, Buffer Overflow, gets, fgets, string decay.
π Further Readingβ
Continue your learning path:
Go deeper: