/* * 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 # include 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