Skip to content

Instantly share code, notes, and snippets.

@yalue
Created February 1, 2022 16:32
Show Gist options
  • Save yalue/b79e9bfc556ce1f208758fdfabb1e04a to your computer and use it in GitHub Desktop.
Save yalue/b79e9bfc556ce1f208758fdfabb1e04a to your computer and use it in GitHub Desktop.
Just a quick string replacement function in C, so I don't need to think about it next time I need it.
#include <stdint.h>
#include <string.h>
// Replaces all instances of the string match in input with r. Returns a new
// null-terminated string, or NULL on error. The returned string must be freed
// by the caller when no longer needed. Even if no replacements are made, this
// will return a new copy of the input string.
char* StringReplace(const char *input, const char *match, const char *r) {
char *input_pos = NULL;
const char *prev_input_pos = NULL;
char *output_pos = NULL;
char *to_return = NULL;
int occurrences = 0;
int new_length = 0;
int unchanged_length = 0;
int original_length = strlen(input);
int match_length = strlen(match);
int sub_length = strlen(r);
// Start by counting the number of occurrences so we can preallocate an
// output buffer of the correct size.
input_pos = strstr(input, match);
while (input_pos != NULL) {
occurrences++;
input_pos += match_length;
input_pos = strstr(input_pos, match);
}
if (occurrences == 0) return strdup(input);
// Allocate the new string's memory, including space for the null char
new_length = original_length - (occurrences * match_length) +
(occurrences * sub_length);
if (new_length < 0) return NULL;
to_return = (char *) calloc(new_length + 1, sizeof(char));
if (!to_return) return NULL;
if (new_length == 0) return to_return;
// Build the string with replacements.
output_pos = to_return;
prev_input_pos = input;
input_pos = strstr(input, match);
while (input_pos != NULL) {
// Copy the part of the string before the replacement to the output.
unchanged_length = ((uintptr_t) input_pos) - ((uintptr_t) prev_input_pos);
memcpy(output_pos, prev_input_pos, unchanged_length);
output_pos += unchanged_length;
// Copy the replacement to the output.
memcpy(output_pos, r, sub_length);
output_pos += sub_length;
// Advance past the matched string in the input and find the next
// occurrence.
input_pos += match_length;
prev_input_pos = input_pos;
input_pos = strstr(input_pos, match);
}
// Finally, copy any remaining input past the final output.
unchanged_length = original_length - (((uintptr_t) prev_input_pos) -
((uintptr_t) input));
memcpy(output_pos, prev_input_pos, unchanged_length);
return to_return;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment