Learn string manipulation techniques in C including reversing strings, converting case, checking palindromes, removing characters, and extracting substrings.
String manipulation is one of the most common tasks in C programming. Since C doesn't provide high-level string methods like modern languages, you need to work directly with character arrays — iterating through them, modifying characters in place, and managing memory manually. This hands-on approach gives you deep understanding of how text processing actually works at the memory level.
Reversing a String
In-Place Reversal Using Two Pointers
#include <stdio.h>
#include <string.h>
void reverseString(char str[]) {
int left = 0;
int right = strlen(str) - 1;
while (left < right) {
char temp = str[left];
str[left] = str[right];
str[right] = temp;
left++;
right--;
}
}
int main() {
char str[] = "Programming";
printf("Original: %s\n", str);
reverseString(str);
printf("Reversed: %s\n", str);
return 0;
}
Original: Programming
Reversed: gnimmargorP
| Step 0 | [H][e][l][l][o] left=0, right=4 |
| Step 1 | [o][e][l][l][H] swap H↔o, left=1, right=3 |
| Step 2 | [o][l][l][e][H] swap e↔l, left=2, right=2 |
| Step 3 | STOP (left >= right) |
| Result | "olleH" |
Recursive Reversal
#include <stdio.h>
#include <string.h>
void reverseRecursive(char str[], int start, int end) {
if (start >= end) return;
char temp = str[start];
str[start] = str[end];
str[end] = temp;
reverseRecursive(str, start + 1, end - 1);
}
int main() {
char str[] = "Recursion";
reverseRecursive(str, 0, strlen(str) - 1);
printf("Reversed: %s\n", str);
return 0;
}
Case Conversion
Converting to Uppercase
#include <stdio.h>
#include <ctype.h>
void toUpperCase(char str[]) {
for (int i = 0; str[i] != '\0'; i++) {
if (str[i] >= 'a' && str[i] <= 'z') {
str[i] = str[i] - 32; // ASCII difference between 'a' and 'A'
}
}
}
// Using ctype.h (cleaner)
void toUpperCaseClean(char str[]) {
for (int i = 0; str[i] != '\0'; i++) {
str[i] = toupper(str[i]);
}
}
int main() {
char str[] = "Hello, World! 123";
toUpperCase(str);
printf("Uppercase: %s\n", str);
return 0;
}
Uppercase: HELLO, WORLD! 123
Converting to Lowercase
#include <stdio.h>
void toLowerCase(char str[]) {
for (int i = 0; str[i] != '\0'; i++) {
if (str[i] >= 'A' && str[i] <= 'Z') {
str[i] = str[i] + 32;
}
}
}
int main() {
char str[] = "HELLO WORLD";
toLowerCase(str);
printf("Lowercase: %s\n", str);
return 0;
}
Toggle Case
#include <stdio.h>
void toggleCase(char str[]) {
for (int i = 0; str[i] != '\0'; i++) {
if (str[i] >= 'A' && str[i] <= 'Z')
str[i] += 32;
else if (str[i] >= 'a' && str[i] <= 'z')
str[i] -= 32;
}
}
int main() {
char str[] = "Hello World";
toggleCase(str);
printf("Toggled: %s\n", str);
return 0;
}
Palindrome Check
A palindrome reads the same forwards and backwards (e.g., "madam", "racecar").
#include <stdio.h>
#include <string.h>
#include <ctype.h>
// Simple palindrome check
int isPalindrome(const char str[]) {
int left = 0;
int right = strlen(str) - 1;
while (left < right) {
if (str[left] != str[right])
return 0; // Not a palindrome
left++;
right--;
}
return 1; // Is a palindrome
}
// Case-insensitive palindrome (ignoring non-alpha characters)
int isPalindromeAdvanced(const char str[]) {
int left = 0;
int right = strlen(str) - 1;
while (left < right) {
// Skip non-alphabetic characters
while (left < right && !isalpha(str[left])) left++;
while (left < right && !isalpha(str[right])) right--;
if (tolower(str[left]) != tolower(str[right]))
return 0;
left++;
right--;
}
return 1;
}
int main() {
char test1[] = "madam";
char test2[] = "hello";
char test3[] = "A man, a plan, a canal: Panama";
printf("\"%s\" → %s\n", test1, isPalindrome(test1) ? "Palindrome" : "Not palindrome");
printf("\"%s\" → %s\n", test2, isPalindrome(test2) ? "Palindrome" : "Not palindrome");
printf("\"%s\" → %s\n", test3, isPalindromeAdvanced(test3) ? "Palindrome" : "Not palindrome");
return 0;
}
"madam" → Palindrome
"hello" → Not palindrome
"A man, a plan, a canal: Panama" → Palindrome
Removing Characters from a String
Remove All Occurrences of a Character
#include <stdio.h>
void removeChar(char str[], char ch) {
int i, j = 0;
for (i = 0; str[i] != '\0'; i++) {
if (str[i] != ch) {
str[j++] = str[i];
}
}
str[j] = '\0';
}
int main() {
char str[] = "Hello, World!";
printf("Before: %s\n", str);
removeChar(str, 'l');
printf("After removing 'l': %s\n", str);
return 0;
}
Before: Hello, World!
After removing 'l': Heo, Word!
Remove Leading and Trailing Spaces (Trim)
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void trim(char str[]) {
int start = 0, end = strlen(str) - 1;
// Skip leading spaces
while (isspace(str[start])) start++;
// Skip trailing spaces
while (end > start && isspace(str[end])) end--;
// Shift characters
int i;
for (i = 0; start <= end; i++, start++) {
str[i] = str[start];
}
str[i] = '\0';
}
int main() {
char str[] = " Hello, World! ";
printf("Before: [%s]\n", str);
trim(str);
printf("After: [%s]\n", str);
return 0;
}
Before: [ Hello, World! ]
After: [Hello, World!]
Counting Characters
#include <stdio.h>
#include <ctype.h>
void analyzeString(const char str[]) {
int vowels = 0, consonants = 0, digits = 0, spaces = 0, special = 0;
for (int i = 0; str[i] != '\0'; i++) {
char ch = tolower(str[i]);
if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u')
vowels++;
else if (ch >= 'a' && ch <= 'z')
consonants++;
else if (ch >= '0' && ch <= '9')
digits++;
else if (ch == ' ')
spaces++;
else
special++;
}
printf("Vowels: %d\n", vowels);
printf("Consonants: %d\n", consonants);
printf("Digits: %d\n", digits);
printf("Spaces: %d\n", spaces);
printf("Special: %d\n", special);
}
int main() {
char str[] = "Hello World! 123";
printf("Analyzing: \"%s\"\n\n", str);
analyzeString(str);
return 0;
}
Analyzing: "Hello World! 123"
Vowels: 3
Consonants: 7
Digits: 3
Spaces: 2
Special: 1
Replacing Characters
#include <stdio.h>
void replaceChar(char str[], char old, char new) {
for (int i = 0; str[i] != '\0'; i++) {
if (str[i] == old) {
str[i] = new;
}
}
}
int main() {
char str[] = "Hello World";
printf("Before: %s\n", str);
replaceChar(str, ' ', '_');
printf("After: %s\n", str);
return 0;
}
Before: Hello World
After: Hello_World
#include <stdio.h>
#include <string.h>
void substring(const char src[], char dest[], int start, int length) {
int srcLen = strlen(src);
if (start >= srcLen) {
dest[0] = '\0';
return;
}
int i;
for (i = 0; i < length && src[start + i] != '\0'; i++) {
dest[i] = src[start + i];
}
dest[i] = '\0';
}
int main() {
char str[] = "Hello, World!";
char sub[20];
substring(str, sub, 7, 5);
printf("Substring from index 7, length 5: \"%s\"\n", sub);
return 0;
}
Substring from index 7, length 5: "World"
Interview Questions
Q1: How do you reverse a string without using any library functions?
Use two pointers (left and right), swap characters at both positions, then move them inward until they meet. This requires only a temp variable and works in-place with O(n) time and O(1) space.
Q2: How do you check if two strings are anagrams of each other?
Count the frequency of each character in both strings using arrays of size 26. If all frequencies match, the strings are anagrams. Time: O(n), Space: O(1).
Q3: What's the ASCII difference between 'A' and 'a'?
- In ASCII, 'A' is 65 and 'a' is 97. To convert uppercase to lowercase, add 32. To convert lowercase to uppercase, subtract 32. The
ctype.h functions toupper() and tolower() handle this portably.
Q4: How would you reverse individual words in a sentence without reversing the sentence order?
First, reverse the entire string. Then, reverse each word individually (using spaces as delimiters). This gives O(n) time with O(1) extra space.
Summary
- String reversal uses the two-pointer technique — swap from both ends inward
- Case conversion exploits the 32-gap between uppercase and lowercase ASCII values
- Palindrome checking compares characters from both ends moving inward
- Character removal uses a read/write pointer pattern to overwrite unwanted characters
- Always null-terminate strings after manipulation to avoid undefined behavior
- Use
ctype.h functions (toupper, tolower, isalpha) for portable character handling