How to replace a part of a string with another substring
Replacing a substring with another is easy if both substrings have the same length:
- locate the position of the substring with
strstr
- if it is present, use
memcpy
to overwrite it with the new substring. - assigning the pointer with
*strstr(m, "on") = "in";
is incorrect and should generate a compiler warning. You would avoid such mistakes withgcc -Wall -Werror
. - note however that you cannot modify a string literal, you need to define an initialized array of
char
so you can modify it.
Here is a corrected version:
#include <stdio.h>
#include <string.h>
int main(void) {
char m[] = "cat on couch";
char *p = strstr(m, "on");
if (p != NULL) {
memcpy(p, "in", 2);
}
printf("%s\n", m);
return 0;
}
If the replacement is shorter, the code is a little more complicated:
#include <stdio.h>
#include <string.h>
int main(void) {
char m[] = "cat is out roaming";
char *p = strstr(m, "out");
if (p != NULL) {
memcpy(p, "in", 2);
memmove(p + 2, p + 3, strlen(p + 3) + 1);
}
printf("%s\n", m);
return 0;
}
In the generic case, it is even more complicated and the array must be large enough to accommodate for the length difference:
#include <stdio.h>
#include <string.h>
int main(void) {
char m[30] = "cat is inside the barn";
char *p = strstr(m, "inside");
if (p != NULL) {
memmove(p + 7, p + 6, strlen(p + 6) + 1);
memcpy(p, "outside", 7);
}
printf("%s\n", m);
return 0;
}
Here is a generic function that handles all cases:
#include <stdio.h>
#include <string.h>
char *strreplace(char *s, const char *s1, const char *s2) {
char *p = strstr(s, s1);
if (p != NULL) {
size_t len1 = strlen(s1);
size_t len2 = strlen(s2);
if (len1 != len2)
memmove(p + len2, p + len1, strlen(p + len1) + 1);
memcpy(p, s2, len2);
}
return s;
}
int main(void) {
char m[30] = "cat is inside the barn";
printf("%s\n", m);
printf("%s\n", strreplace(m, "inside", "in"));
printf("%s\n", strreplace(m, "in", "on"));
printf("%s\n", strreplace(m, "on", "outside"));
return 0;
}
How to replace substring in a string with another string in C?
Your code is a good start, but there are many problems:
- the test
if (str1[i+j] != str1[i+j])
is always true - you copy incomplete fragments and fail to skip it after copying.
- you forgot to null terminate the destination.
Here is a modified version:
#include <stdio.h>
char *str_replace(char *dest, const char *str1, const char *str2, const char *str3) {
size_t i = 0, j, k = 0;
// replacing substring `str2` with `str3`, assuming sufficient space
while (str1[i] != '\0') {
for (j = 0; str2[j] != '\0'; j++) {
if (str1[i + j] != str2[j]) {
break;
}
}
if (str2[j] == '\0' && j > 0) {
// we have a match: copy the replacement and skip it
i += j;
for (j = 0; str3[j] != '\0'; j++) {
dest[k++] = str3[j];
}
} else {
// copy the byte and skip it.
dest[k++] = str1[i++];
}
}
dest[k] = '\0'; // null terminate the destination
return dest;
}
int main() {
char new_string[50];
printf("%s\n", str_replace(new_string, "123abc890", "abc", "abc"));
printf("%s\n", str_replace(new_string, "123abc890", "abc", "xyz"));
printf("%s\n", str_replace(new_string, "123abc890", "a", "xyz"));
printf("%s\n", str_replace(new_string, "123abc890", "abc", ""));
return 0;
}
Output:
123abc890
123xyz890
123xyzbc890
123890
Replace all occurrences of a substring in a string in C
For starters:
This line
strncpy(buffer, string, p-string);
not necessarily appends a 0
-terminator to what had been copied to buffer
.
The following line
strcat(buffer, replace);
however relies on buffer
being 0
-terminated.
As buffer
had not been initialised and though the 0
-terminator most likely misses the latter line may very well read beyond buffer
's memory and with this invoke the infamous Undefined Behaviour.
Efficiently replace a substring in a string
Your code seems like you're trying to re-inventing your own wheel.
By using standard C functions, which is strstr() and memset(), you can achieve the same result as you expected.
#include <stdio.h>
#include <string.h>
char string[] = "foobar foobar foobar";
char substr[] = "foo";
char replace = '~';
int main() {
int substr_size = strlen(substr);
// Make a copy of your `string` pointer.
// This is to ensure we can safely modify this pointer value, without 'touching' the original one.
char *ptr = string;
// while true (infinite loop)
while(1) {
// Find pointer to next substring
ptr = strstr(ptr, substr);
// If no substring found, then break from the loop
if(ptr == NULL) { break; }
// If found, then replace it with your character
memset(ptr, replace, substr_size);
// iIncrement our string pointer, pass replaced substring
ptr += substr_size;
}
printf("%s\n", string);
return 0;
}
C - Replace substring in string
Question 1: When this line is executed in main() it causes a segfault.
However, when executed within the function everything seems to work
fine. Why?
No, printf("input: %d\t%s\n", len, buffer); // <- Question 1
is not the cause of your segfault.
printf("output: %ld\t%s\n", strlen(output), output);
This part is, strlen
doesn't return int
but it returns size_t
. As noted in the comments, use %zu
to print it out.
Also, while(input[a])
will stop at the NULL terminator which means that your output
will never hold a terminator and thus printf
will keep on reading, you should add it at the end:
output[c] = '\0';
Also, as noted by @LPs in the comments, you should zero initialize the variables you work with :
int a = 0, b = 0, c = 0;
Question 2: I have realized that I need a pretty large piece of memory
allocated for the output to look as expected. strlen(input)*5 is an
arbitrary number which seems to work, but why do I get seemingly
'random' errors when lowering the number?
Probably because you haven't allocated enough memory. Because the string length depends on runtime factors there's no way to know the exact memory needed you should allocate the maximum amount required:
char *output = malloc(strlen(input) * strlen(new) + 1);
replace a substring of a given string in c++
Yet, the output of s3 is, "There Bob and Bill go again!". Could
anyone help to explain?
Not quite. The output is "There Bob and Billey go again". Starting from the word they
it took the first two characters (th
) and replaced them with Bob and Bill
. The result is There Bob and Billey go again!
.
This behavior is consistent with this documentation's explanation of std::string::replace
:
Replaces the portion of the string that begins at character
pos
and
spanslen
characters (or the part of the string in the range between
[i1,i2)) by new contents:(1) string
Copiesstr
.
If you wanted your output to be "There Boey go again!"
, you can do it like this:
int size = 2; // amount of characters that should be replaced
if (pos != string::npos)
s3.replace(pos, size, s4.substr(0, size));
Related Topics
How Can a Windows Service Execute a Gui Application
Boolean Expression (Grammar) Parser in C++
How to Make My Program Watch For File Modification in C++
_File_, _Line_, and _Function_ Usage in C++
Is Floating-Point Addition and Multiplication Associative
Library Function For Permutation and Combination in C++
How to Render Offscreen on Opengl
"Invalid Use of Incomplete Type" Error With Partial Template Specialization
Enforcing Statement Order in C++
How to Read a Complete Line from the User Using Cin
Create Random Number Sequence With No Repeats
How Does C++ Linking Work in Practice
When Should I Use Std::Thread::Detach
How to Loop Through a C++ Map of Maps
Is It a Conforming Compiler Extension to Treat Non-Constexpr Standard Library Functions as Constexpr
How to Change Mode from C++98 Mode in Dev-C++ to a Mode That Supports C++0X (Range Based For)