F1e3ab214a976a39cfd713bc93deb10f

Pretty weak first pass at a character array substitution func

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 !

48ccd8d56bce9ebd25c1720c13e9d442

R. Pate

June 27, 2009, June 27, 2009 06:15, permalink

No rating. Login to rate!

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);
  }
}

Your refactoring





Format Copy from initial code

or Cancel