Replacing a substring means finding every occurrence of one piece of text inside a string and swapping it for another — for example, turning “the cat sat on the mat” into “the cog sog on the mog” by replacing “at” with “og”. C has no built-in function for this (unlike Python’s str.replace()), so it’s a common exercise for practicing manual string manipulation with pointers and indices.
This page builds a complete, safe replace-all implementation in C, walks through how it works, and covers the buffer-overflow trap that naive versions of this program fall into.
How It Works — Step by Step
- Scan the main string one position at a time.
- At each position, check whether the substring to replace starts there (using
strncmp). - If it matches, copy the replacement text into the result and skip past the matched substring.
- If it doesn’t match, copy just the current character into the result and move one position forward.
- Repeat until the entire input string has been scanned, then terminate the result with
'\0'.
Step-by-step trace
Replacing "an" with "XY" in "banana bread":
b -> no match at index 0, copy 'b' an -> match at index 1, write "XY", skip 2 an -> match at index 3, write "XY", skip 2 a -> no match, copy 'a' " bread" -> no more matches, copy the rest as-is Result: bXYXYa bread
C Program to Replace All Occurrences of a Substring
/* Replace All Occurrences of a Substring in C
* Compile: gcc -ansi -Wall -Wextra replacesub.c -o replacesub */
#include <stdio.h>
#include <string.h>
#define MAXLEN 500
void replace_all(const char *str, const char *old_sub, const char *new_sub, char *result)
{
int str_len = (int)strlen(str);
int old_len = (int)strlen(old_sub);
int new_len = (int)strlen(new_sub);
int i = 0, j = 0, k;
if (old_len == 0) {
strcpy(result, str);
return;
}
while (i < str_len && j < MAXLEN - 1) {
if (i <= str_len - old_len && strncmp(&str[i], old_sub, old_len) == 0) {
for (k = 0; k < new_len && j < MAXLEN - 1; k++)
result[j++] = new_sub[k];
i += old_len;
} else {
result[j++] = str[i++];
}
}
result[j] = '\0';
}
int main(void)
{
char str[MAXLEN], old_sub[100], new_sub[100], result[MAXLEN];
printf("Enter the main string: ");
fgets(str, sizeof(str), stdin);
str[strcspn(str, "\n")] = '\0';
printf("Enter substring to replace: ");
fgets(old_sub, sizeof(old_sub), stdin);
old_sub[strcspn(old_sub, "\n")] = '\0';
printf("Enter replacement string: ");
fgets(new_sub, sizeof(new_sub), stdin);
new_sub[strcspn(new_sub, "\n")] = '\0';
replace_all(str, old_sub, new_sub, result);
printf("Result: %s\n", result);
return 0;
}
How to Compile and Run
gcc -ansi -Wall -Wextra replacesub.c -o replacesub ./replacesub
Sample Input and Output — Test 1
Enter the main string: the cat sat on the mat Enter substring to replace: at Enter replacement string: ATX Result: the cATX sATX on the mATX
Sample Input and Output — Test 2
Enter the main string: banana bread Enter substring to replace: an Enter replacement string: XY Result: bXYXYa bread
Code Explanation
- The overflow guard:
j < MAXLEN - 1— if the replacement text is longer than the text it replaces, and there are many matches, the result can grow larger than the input. CheckingjagainstMAXLEN - 1on every write (in both the outer loop and the copy loop) stops the function from writing past the end of the buffer, at the cost of silently truncating extremely long results. i <= str_len - old_lenguard beforestrncmp— without this, near the end of the string,strncmpcould read past the null terminator while checking for a match that can’t possibly fit.- Empty
old_subedge case — replacing every occurrence of an empty string is undefined behavior in most implementations, so this program explicitly checks for it and just copies the string unchanged. - Why not modify the string in place — when the replacement text is a different length than the original, shifting the remaining characters correctly in place is error-prone; building a separate result buffer is simpler and safer.
Time and Space Complexity
| Case | Time | Space |
|---|---|---|
| Matching | O(n × m) worst case | O(n) for the result buffer |
n = length of the main string, m = length of the substring being replaced. In practice, matches are rare, so the actual comparisons done are close to O(n).
What This Program Teaches
- Building a result in a separate buffer — the standard, safe pattern whenever the output size differs from the input size.
- Defensive buffer bounds-checking — writing loop conditions that can never overflow the destination array, regardless of the input.
strncmpfor substring matching — comparing only a fixed number of characters instead of the whole string.
Related Programs
- Find the Position of a Substring in C
- String Functions in C – Complete Reference
- Find String Length Without strlen()
- Palindrome String Check in C
Recommended Books
- The C Programming Language – Kernighan & Ritchie (India) | Amazon.com
- C Programming: A Modern Approach – K.N. King (India) | Amazon.com
Practice C string handling with the C Programming Quiz App — 500+ MCQs covering strings, pointers, sorting, and more.
Download on Google Play →