Created
February 1, 2022 16:32
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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