1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
char * str_replace(char *str, char *old, char *new) { int i, count = 0; int newlen = strlen(new); int oldlen = strlen(old); for (i = 0; str[i]; ++i) if (strstr(&str[i], old) == &str[i]) ++count, i += oldlen - 1; char *ret = (char *) calloc(i + 1 + count * (newlen - oldlen), sizeof(char)); if (!ret) return; i = 0; while (*str) if (strstr(str, old) == str) strcpy(&ret[i], new), i += newlen, str += oldlen; else ret[i++] = *str++; ret[i] = '\0'; return ret; }
Refactorings
No refactoring yet !
R. Pate
June 27, 2009, June 27, 2009 06:15, permalink
My own weak first pass. (Tests included!)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
#include <assert.h> #include <stdlib.h> #include <stdio.h> #include <string.h> void str_replace_inline(char* str, char const* old, char const* new) { assert(str); assert(new); assert(old); int const newlen = strlen(new); int const oldlen = strlen(old); assert(oldlen > 0); assert(newlen <= oldlen); char* next = str; while (*str) { if (strncmp(str, old, oldlen) == 0) { strncpy(next, new, newlen); next += newlen; str += oldlen; } else { *next++ = *str++; } } while (*str) { *next++ = *str++; } *next = '\0'; } void str_replace_malloc(char** str, int* str_size, char const* old, char const* new) { assert(str != NULL); assert(*str != NULL); assert(str_size); assert(new != NULL); assert(old != NULL); int const newlen = strlen(new); int const oldlen = strlen(old); assert(oldlen > 0); if (newlen <= oldlen) { str_replace_inline(*str, old, new); } else { for (char* i = *str; *i; ++i) { if (strncmp(i, old, oldlen) == 0) { int new_str_size = (i - *str) + newlen * 2 + 100; char* new_str = malloc(new_str_size); if (!new_str) { perror("malloc failed"); abort(); // or whatever you want } strncpy(new_str, *str, i - *str); char* next = new_str + (i - *str); strncpy(next, new, newlen); next += newlen; i += oldlen; while (*i) { if (strncmp(i, old, oldlen) == 0) { strncpy(next, new, newlen); next += newlen; i += oldlen; } else { *next++ = *i++; } if ((next - new_str) + newlen >= new_str_size) { new_str_size *= 2; new_str_size += newlen + 1; char* new_new_str = malloc(new_str_size); if (!new_new_str) { perror("malloc failed"); abort(); // or whatever you want } strncpy(new_new_str, new_str, next - new_str); next = new_new_str + (next - new_str); free(new_str); new_str = new_new_str; } } *next = '\0'; *str = new_str; *str_size = new_str_size; return; } } } } typedef struct { int id; char const* old; char const* new; char const* initial; char const* expected; } Test; int main() { Test tests[] = { {__LINE__, "a", "b", "aaaa", "bbbb"}, {__LINE__, "a", "b", "abca", "bbcb"}, {__LINE__, "aa", "b", "aaaa", "bb"}, {__LINE__, "aa", "b", "aaab", "bab"}, {__LINE__, "a", "bb", "a", "bb"}, {__LINE__, "a", "bb", "aa", "bbbb"}, {__LINE__, "old", "newish", "blah blah old blah oldold blah", "blah blah newish blah newishnewish blah"}, {__LINE__, "old", "newish", "old blah old", "newish blah newish"}, }; for (Test* i = tests; i != tests + sizeof tests / sizeof *tests; ++i) { int size = strlen(i->initial) + 1; char* buf = malloc(size); strcpy(buf, i->initial); str_replace_malloc(&buf, &size, i->old, i->new); if (strcmp(buf, i->expected) != 0) { printf("failed test %d, expected '%s', got '%s'\n", i->id, i->expected, buf); } free(buf); } }
Pretty weak first pass at a character array substitution func