mirror of
https://gitlab.com/80486DX2-66/gists
synced 2024-11-08 08:54:34 +05:30
129 lines
2.9 KiB
C
129 lines
2.9 KiB
C
/*
|
|
* str_replace.c
|
|
*
|
|
* TODO: Add the ability to replace from the end
|
|
*
|
|
* Author: Intel A80486DX2-66
|
|
* License: Unlicense
|
|
*/
|
|
|
|
#include "str_replace.h"
|
|
|
|
char* str_replace(
|
|
const char* str,
|
|
const char* substr,
|
|
const char* replacement,
|
|
size_t max_count,
|
|
bool direction
|
|
) {
|
|
/*
|
|
* input arguments:
|
|
* max_count: N <= 0 for all replacements, N > 0 for N replacement
|
|
*
|
|
* the output string should be freed!
|
|
*/
|
|
size_t substr_len = strlen(substr),
|
|
replacement_len = strlen(replacement),
|
|
count = 0;
|
|
|
|
if (direction == STR_REPLACE_DIR_BACKWARD) {
|
|
// TODO: implement replacing from the end
|
|
fprintf(stderr, "str_replace, STR_REPLACE_DIR_BACKWARD: Work in "
|
|
"progress\n");
|
|
return str_replace(str, substr, replacement, max_count,
|
|
STR_REPLACE_DIR_FORWARD);
|
|
}
|
|
|
|
const char* p = str;
|
|
|
|
// count the number of occurrences of the substring
|
|
for (; (p = strstr(p, substr)) != NULL; count++) {
|
|
if (max_count > 0 && count >= (size_t) max_count)
|
|
break;
|
|
p += substr_len;
|
|
}
|
|
|
|
// allocate a buffer to hold the modified string
|
|
size_t new_len = strlen(str) + count * (replacement_len - substr_len);
|
|
|
|
char* result = malloc((new_len + 1) * sizeof(char));
|
|
if (result == NULL)
|
|
return NULL;
|
|
|
|
const char* q = str;
|
|
char* r = result;
|
|
for (; (p = strstr(q, substr)) != NULL && count > 0; count--) {
|
|
size_t len = p - q;
|
|
memcpy(r, q, len);
|
|
r += len;
|
|
memcpy(r, replacement, replacement_len);
|
|
r += replacement_len;
|
|
q = p + substr_len;
|
|
}
|
|
strcpy(r, q);
|
|
|
|
return result;
|
|
}
|
|
|
|
#ifdef TEST
|
|
# include <stdint.h>
|
|
# include <stdio.h>
|
|
|
|
uintmax_t tests_failed = 0;
|
|
|
|
static void func_expect(
|
|
const char* str,
|
|
const char* substr,
|
|
const char* replacement,
|
|
size_t max_count,
|
|
bool direction,
|
|
const char* expected_output
|
|
);
|
|
|
|
static void func_expect(
|
|
const char* str,
|
|
const char* substr,
|
|
const char* replacement,
|
|
size_t max_count,
|
|
bool direction,
|
|
const char* expected_output
|
|
) {
|
|
char* result = str_replace(str, substr, replacement, max_count, direction);
|
|
if (result == NULL) {
|
|
perror("str_replace");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
if (strcmp(result, expected_output)) {
|
|
puts("Failed!\n");
|
|
tests_failed++;
|
|
return;
|
|
}
|
|
|
|
puts("Passed\n");
|
|
}
|
|
|
|
int main(void) {
|
|
func_expect("Hello; peace! This is a peaceful test.",
|
|
"; peace",
|
|
", universe",
|
|
STR_REPLACE_ALL,
|
|
STR_REPLACE_DIR_FORWARD,
|
|
"Hello, universe! This is a peaceful test.");
|
|
const char* str = "Hello; peace! This is a peaceful test.",
|
|
* substr = "peace",
|
|
* replacement1 = "universe",
|
|
* replacement2 = "_____";
|
|
|
|
char* result1 = str_replace(str, substr, replacement1, STR_REPLACE_ALL,
|
|
STR_REPLACE_DIR_FORWARD),
|
|
* result2 = str_replace(str, substr, replacement2, 1,
|
|
STR_REPLACE_DIR_FORWARD);
|
|
|
|
puts(result1); free(result1);
|
|
puts(result2); free(result2);
|
|
|
|
return 0;
|
|
}
|
|
#endif
|