2010-09-22 3 views
0

Я только начал заниматься программированием на С и был бы признателен за критику моей функции ReplaceString. Кажется довольно быстрым (он не выделяет никакой памяти, кроме одного malloc для строки результата), но это кажется ужасно подробным, и я знаю, что это может быть сделано лучше.Предложения по улучшению функции C ReplaceString?

Пример использования:

printf("New string: %s\n", ReplaceString("great", "ok", "have a g grea great day and have a great day great")); 
printf("New string: %s\n", ReplaceString("great", "fantastic", "have a g grea great day and have a great day great")); 

Код:

#ifndef uint 
    #define uint unsigned int 
#endif 

char *ReplaceString(char *needle, char *replace, char *haystack) 
{ 
    char *newString; 
    uint lNeedle = strlen(needle); 
    uint lReplace = strlen(replace); 
    uint lHaystack = strlen(haystack); 
    uint i; 
    uint j = 0; 
    uint k = 0; 
    uint lNew; 
    char active = 0; 
    uint start = 0; 
    uint end = 0; 

    /* Calculate new string size */  
    lNew = lHaystack; 

    for (i = 0; i < lHaystack; i++) 
    { 

     if ((!active) && (haystack[i] == needle[0])) 
     { 
      /* Start of needle found */ 
      active = 1; 
      start = i; 
      end = i; 
     } 
     else if ((active) && (i-start == lNeedle)) 
     { 
      /* End of needle */ 
      active = 0; 
      lNew += lReplace - lNeedle; 
     } 
     else if ((active) && (i-start < lNeedle) && (haystack[i] == needle[i-start])) 
     { 
      /* Next part of needle found */ 
      end++; 
     } 
     else if (active) 
     { 
      /* Didn't match the entire needle... */ 
      active = 0; 
     } 

    } 
    active= 0; 
    end = 0; 


    /* Prepare new string */ 
    newString = malloc(sizeof(char) * lNew + 1); 
    newString[sizeof(char) * lNew] = 0; 

    /* Build new string */ 
    for (i = 0; i < lHaystack; i++) 
    { 

     if ((!active) && (haystack[i] == needle[0])) 
     { 
      /* Start of needle found */ 
      active = 1; 
      start = i; 
      end = i; 
     } 
     else if ((active) && (i-start == lNeedle)) 
     { 
      /* End of needle - apply replacement */ 
      active = 0; 

      for (k = 0; k < lReplace; k++) 
      { 
       newString[j] = replace[k]; 
       j++; 
      } 
      newString[j] = haystack[i]; 
      j++; 

     } 
     else if ((active) && (i-start < lNeedle) && (haystack[i] == needle[i-start]) 
       ) 
     { 
      /* Next part of needle found */ 
      end++; 
     } 
     else if (active) 
     { 
      /* Didn't match the entire needle, so apply skipped chars */ 
      active = 0; 

      for (k = start; k < end+2; k++) 
      { 
       newString[j] = haystack[k]; 
       j++; 
      } 

     } 
     else if (!active) 
     { 
      /* No needle matched */ 
      newString[j] = haystack[i]; 
      j++; 
     } 

    } 

    /* If still matching a needle... */ 
    if (active && (i-start == lNeedle)) 
    { 
     /* If full needle */ 
     for (k = 0; k < lReplace; k++) 
     { 
      newString[j] = replace[k]; 
      j++; 
     } 
     newString[j] = haystack[i]; 
     j++; 
    } 
    else if (active) 
    { 
     for (k = start; k < end+2; k++) 
     { 
      newString[j] = haystack[k]; 
      j++; 
     } 
    } 

    return newString; 
} 

Любые идеи? Огромное спасибо!

+3

Нельзя ли использовать функции из строки. h'? –

+0

@ Карл, который в частности?(не говорите мне, что там где-то есть ReplaceString !!;)) – HoboBen

+2

Я не думаю, что есть, но есть 'strstr()', который находит подстроку. – linuxuser27

ответ

3

Не вызывайте strlen (стог сена). Вы уже проверять каждый символ в строке, поэтому вычисления длины строки неявно для вашего цикла, следующим образом:

for (i = 0; haystack[i] != '\0'; i++) 
{ 
    ... 
} 
lHaystack = i; 
+0

Уход, Спасибо Брайан! – HoboBen

1

При первом запуске вы должны хранить индексы там, где их нужно заменить, и пропустить их на функции strcopy/replace. Это приведет к циклу, в котором вы выполняете strncpy только с haystack или замену на новую строку.

2

Возможно, вы делаете это по-своему для практики. Если это так, вы получаете много очков за усилия.

Если нет, вы можете часто экономить время, используя функции, которые находятся в библиотеке времени выполнения (CRT), вместо кодирования собственной эквивалентной функции. Например, вы можете использовать strstr, чтобы найти строку, предназначенную для замены. Другие функции манипуляции с строкой также могут быть полезны для вас.

Хорошим упражнением было бы выполнить этот пример в соответствии с вашим удовлетворением, а затем перекодировать с помощью ЭЛТ, чтобы узнать, насколько быстрее он будет кодировать и выполнять.

+0

Thanks; Я обязательно это сделаю. Я могу думать о нескольких способах реализации функции, записи и синхронизации, все они звучат как хорошая идея. – HoboBen

+1

Для нового кодера это симпатичный код. Вы также можете рассмотреть возможность использования арифметики указателя при прохождении строк вместо индексов, например. 'for (char * next = haystack, i = 0; i

0

Сделать параметры const

char *ReplaceString(const char *needle, const char *replace, const char *haystack) 

О ... является функция должен работать только один раз за слово?

ReplaceString("BAR", "bar", "BARBARA WENT TO THE BAR")

0

Мой один предложение не имеет ничего общего с улучшением производительности, но с улучшением читаемости.

Названия параметров «Симпатичные» гораздо труднее понять, чем описательные. Какой из следующих параметров, по вашему мнению, лучше передает их цель?

char *ReplaceString(char *needle, char *replace, char *haystack) 
char *ReplaceString(char *oldText, char *newText, char *inString) 

С одной целью вы должны сознательно сопоставить имя с целью. С другой целью это имя. Жонглирование связью имен в вашей голове при попытке понять часть кода может стать затруднительным, особенно по мере увеличения числа переменных.

Возможно, это не так важно, когда вы используете только один код, но это имеет первостепенное значение, когда ваш код используется или читается кем-то другим. И иногда «кто-то еще» - это вы сами, через год, глядя на свой собственный код, задаваясь вопросом, почему вы просматриваете стога сена и пытаетесь заменить иглы;)

+1

В этом случае я бы сказал, что каждый программист C должен использоваться для _needle_ и _haystack_, так как это традиционные имена параметров strstr(). – ninjalj

+0

Yup, что я привык с PHP и несколькими диалектами BASIC & Pascal, хотя я ценю озабоченность – HoboBen

Смежные вопросы