There is no direct function to do that. You have to write something like this, using strchr:
char* replace_char(char* str, char find, char replace){
char *current_pos = strchr(str,find);
while (current_pos) {
*current_pos = replace;
current_pos = strchr(current_pos,find);
}
return str;
}
For whole strings, I refer to this answered question
Answer from Superlokkus on Stack OverflowThere is no direct function to do that. You have to write something like this, using strchr:
char* replace_char(char* str, char find, char replace){
char *current_pos = strchr(str,find);
while (current_pos) {
*current_pos = replace;
current_pos = strchr(current_pos,find);
}
return str;
}
For whole strings, I refer to this answered question
There are not such functions in the standard libraries.
You can easily roll your own using strchr for replacing one single char, or strstr to replace a substring (the latter will be slightly more complex).
int replacechar(char *str, char orig, char rep) {
char *ix = str;
int n = 0;
while((ix = strchr(ix, orig)) != NULL) {
*ix++ = rep;
n++;
}
return n;
}
This one returns the number of chars replaced and is even immune to replacing a char by itself
Indexing in C arrays start from 0. So you have to replace c[1] = 'B' with c[0] = 'B'.
Also, see similar question from today: Smiles in output C++ - I've put a more detailed description there :)
Below is a code that ACTUALLY WORKS!
char * replace_char(char * input, char find, char replace)
{
char * output = (char*)malloc(strlen(input));
for (int i = 0; i < strlen(input); i++)
{
if (input[i] == find) output[i] = replace;
else output[i] = input[i];
}
output[strlen(input)] = '\0';
return output;
}
Replacing strings in an array in C - Stack Overflow
How to replace a specific but changing series of characters in an array in C? - Stack Overflow
Replacing a string in char array - C++ Forum
Replacing a character in a string (char array) with multiple characters in C - Stack Overflow
#include <stdio.h>
int main(void) {
char* words[3] = {"cat", "dog", "bird"};
printf("The Initial List\n");
for(int i=0; i<3; ++i)
{
printf("%d : %s\n", i, words[i]);
}
// Replace the middle entry
char* replacement = "mouse";
words[1] = replacement;
printf("The Final List\n");
for(int i=0; i<3; ++i)
{
printf("%d : %s\n", i, words[i]);
}
return 0;
}
Output:
Success #stdin #stdout 0.01s 5464KB
The Initial List
0 : cat
1 : dog
2 : bird
The Final List
0 : cat
1 : mouse
2 : bird
This code:
char * words[3];
words[0] = "cat";
words[1] = "dog";
words[2] = "bird";
...is roughly equivalent to:
// Internal memory you can't see:
char _string1[] = {'c','a','t','\0'} // Address 0x001234
char _string2[] = {'d','o','g','\0'} // Address 0x001238
char _string3[] = {'b','i','r','d','\0'} // Address 0x001242
// Your program memory:
char * words[3];
words[0] = (char *)0x001234;
words[1] = (char *)0x001238;
words[2] = (char *)0x001242;
The important thing is char * s is not the same as char s[], so trying to copy "mouse" over 0x001238 doesn't do what you want.
Given char word[] = "mouse";, word does have an address so you can assign that as in words[1] = word; and that will work. Of course if you change word[0] = 'h'; to make it "house" then words[1] will also be "house".
If that's not a problem for you, then it's fine, otherwise you'll need words to be an array of characters rather than an array of pointers, and make sure there are enough characters to hold all the words you want. Since most words will be shorter than that, a lot of characters will be unused, but that's not normally a big problem.
Otherwise you will have to use malloc(), free(), strdup(), and so on to manage the memory and that gets complicated, so best avoid that unless you really need to.
If I have correctly understood, you do not want to copy the terminating null. The standard library function to use is void *memcpy(void *dest, void *src, size_t size) that copies exactly size bytes from src to dest.
But you have to ensure that there is enough room at dest to accept the size bytes
You can take a look at
https://www.tutorialspoint.com/c_standard_library/string_h.htm
And for you,
char *strcpy(char *dest, const char *src)
char *strncpy(char *dest, const char *src, size_t n)
They can make your code cleaner, but i think that deep inside, they do what you're doing manually.
You can do it like this:
- Compute the length of the new array by adding the number of
'2's tostrlenof your string plus one for null terminator - Allocate the required number of
chars usingmalloc - Go through your string in a loop; if you see
'2', add'B'followed by'a'to the output; - Otherwise, copy the current character to the output.
Note: now that your string is allocated dynamically, you need to call free once you are done using it.
const char* str = ...
int cnt = strlen(str)+1;
for (const char *p = str ; *p ; cnt += (*p++ == '2'))
;
char *res = malloc(cnt);
char *out = res;
const char *in = str;
while (*in) {
if (*in == '2') {
*out++ = 'B';
*out++ = 'a';
} else {
*out++ = *in;
}
in++;
}
*out++ = '\0';
Demo.
Many of the solutions are excessively complex, pointlessly verbose, and are inefficient (e.g., strlen means three scans when only two are needed).
int newlen = 1;
for (char* p = str; *p; p++)
newlen += *p == '2' ? 2 : 1;
char newstr[newlen];
for (char *p = str, *q = newstr;; p++)
if (*p == '2')
{
*q++ = 'B';
*q++ = 'a';
}
else if (!(*q++ = *p))
break;
Got the following exercise:
Given a string, use a function to replace each character with the following character in the alphabet. That is, if the string is ABC, the new string would have to be BCD. If Z (or z) is in the string, it should be replaced with A (or a). The function must have the following scope:
void shift_string (char* str);
I got the replacement for the next letter with no issues. However, my code is not replacing "z" with "a". Here's my code
#include <stdio.h>
#include <stdlib.h>
#define MAX 255
void shift_string (char* str)
{
int i;
char c1 = 'Z';
char c2 = 'z';
char new_c1 = 'A';
char new_c2 = 'a';
for (i = 0; str[i] != '\0'; i++)
{
str[i] = (int)str[i] + 1;
if (str[i] == c1)
str[i] = new_c1;
else if (str[i] == c2)
str[i] = new_c2;
}
}And the main function:
int main (void)
{
char *str;
str = (char*) malloc(MAX * sizeof(int));
printf("Enter a string (max. %d characters): ", MAX);
scanf(" %255[^\n]", str);
int size = sizeof(str) / sizeof( str[0]);
printf("\nString: %s", str);
printf("\n");
shift_string (str);
printf("\n");
printf("New string: %s", str);
printf("\n\n");
return 0;
}
However, if I input something like ZXCVB, I get the following output:
[YDWC
What am I doing wrong here? Why isn't the if statement working?
Replace character with character
This code will replace every occurrence of the character 'n' with the character '1'.
#include <stdio.h>
int main(void)
{
char str[15];
printf("Input: ");
scanf("%14s", str); // prevent buffer overflow
for (int i = 0; str[i]; ++i) { // iterate over str
if (str[i] == 'n')
str[i] = '1';
}
printf("Modified: %s\n", str);
return 0;
}
Replace character with string
This code will replace every occurrence of the character 'n' with the string "1+k" using the function strcat. The modified string is saved to char mod[].
#include <stdio.h>
#include <string.h>
#include <stdio.h>
int main(void)
{
char str[15];
printf("Input: ");
scanf("%14s", str); // prevent buffer overflow
char mod[] = "";
for (int i = 0; str[i]; ++i) { // iterate over str
if (str[i] == 'n') {
char *repl = "1+k";
strcat(mod, repl); // add "1+k" to mod
} else {
strncat(mod, &str[i], 1); // add str[i] to mod
}
}
printf("Modified: %s\n", mod);
return 0;
}
Such a trivial question deserves a non trivial answer
Note that this approach with branching, demonstrated by @Andy Sukowski-Bang, is - when compiled with -O3 - roughly 6.5x time slower than my approach, illustratating the efficiency of bitwise operations over branching instructions (not to mention Meltdown and Spectre vulnerabilities and its on branching if mitigations are enabled).
The following program will convert every occurence of the letter from to the designated letter.
It is able to replace all characters from 'A' to 'z' to '8' in a string of 8,286,208 bytes in only 0.07s:
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <time.h>
// gcc -O3 replace.c && ./a.out
void replace(char *s, char from, char to, long n) {
char eq;
while (n--) {
eq = !(*s ^ from);
*s = !eq * *s + eq * to;
s++;
}
}
void replace_branching(char *s, char from, char to, long n) {
while (n--) {
if (*s == from)
*s = to;
s++;
}
}
void read_file_to_buffer(FILE *f, long length) {
char buffer[length + 1];
fseek(f, 0, SEEK_SET);
void (*fptr[2]) (char *s, char from, char to, long n) = {replace_branching, replace};
if (fread (buffer, 1, length, f) ) {
buffer[length] = '\0';
fclose (f);
char subbuff[33];
subbuff[32] = '\0';
char from = 'A';
char to = '8';
clock_t start, end;
double cpu_time_used[2];
for (int j = 0; j < 2; j++){
start = clock();
for (int i = 0; i < 0x20 + 26; i++) {
fptrj;
//memcpy( subbuff, &buffer[0], 32 );
//printf("Modified: %s\n", subbuff);
}
end = clock();
cpu_time_used[j] = ((double) (end - start)) / CLOCKS_PER_SEC;
printf("Time: %fs\n", cpu_time_used[j]);
}
printf("Without branching it is %fx faster\n", cpu_time_used[0] / cpu_time_used[1]);
}
}
int main(void)
{
FILE * f;
long length;
if ((f = fopen ("test.txt", "rb"))) // NB: test.txt is a file of 8,286,208 bytes
{
fseek (f, 0, SEEK_END);
read_file_to_buffer(f, ftell(f));
}
return 0;
}
/*
Time: 0.475005s
Time: 0.070859s
Without branching it is 6.703524x faster
*/
Some explanations
eq = !(*s ^ from); // eq will equal 0 if letters are same, else it will equal 1
*s = !eq * *s + eq * to; // we assign to the pointer its same old value with !eq if the character 'from' was absent, else we will assign the character 'to'.
PS: No malloc were used, I used VLA and it is bad, very bad, don't do this at home!