C:循环中的字符串替换(c初学者)

时间:2014-08-18 07:40:51

标签: c string

我需要在某些文本中替换字符串。我在stackoverflow找到了这个函数:

char *replace(const char *s, const char *old, const char *new)
{
    char *ret;
    int i, count = 0;
    size_t newlen = strlen(new);
    size_t oldlen = strlen(old);

    for (i = 0; s[i] != '\0'; i++) {
        if (strstr(&s[i], old) == &s[i]) {
        count++;
        i += oldlen - 1;
        }
    }

    ret = malloc(i + count * (newlen - oldlen));
    if (ret == NULL)
        exit(EXIT_FAILURE);

    i = 0;
    while (*s) {
        if (strstr(s, old) == s) {
            strcpy(&ret[i], new);
            i += newlen;
            s += oldlen;
        } else
            ret[i++] = *s++;
    }
    ret[i] = '\0';

    return ret;
}

此功能对我来说非常适合单次更换。但我需要更换整个数组" str2rep"到"替换"。所以我想做的事情(我只是一个初学者)

****
    #define MAXTEXT 39016
    int l;
    int j;
    char *newsms = NULL;
    char text[MAXTEXT];
    char *str2rep[] = {":q:",":n:"};
    char *replacement[] = {"?","\n"};

    strcpy((char *)text,(char *)argv[5]);

    l = sizeof(str2rep) / sizeof(*str2rep);

    for(j = 0; j < l; j++)
    {
        newsms = replace(text,(char *)str2rep[j],(char *)replacement[j]);
        strcpy(text,newsms);
        free(newsms);       
    }

    textlen = strlen(text);

这个代码甚至在本地工作,如果我从单个文件构建它...但这是星号模块,所以当执行此操作时,星号将停止:

*检测到glibc * / usr / sbin / asterisk:双重免费或损坏(!prev):0x00007fa720006310 *

2 个答案:

答案 0 :(得分:1)

的问题:

  1. ret = malloc(i + count * (newlen - oldlen));太小了。需要+ 1.
    考虑replace("", "", "")会发生什么。如果你的SO参考是this,那也是错误的。

  2. 混合签名/未签名的可疑结果。 count已签名。 newlen, oldlen未签名 我认为原始代码工作正常,但我不喜欢使用无符号数学的环绕特性,这可以避免newlen < oldlen时发生的情况。

    // i + count * (newlen - oldlen)
    size_t newsize = i + 1;  // + 1 for above reason
    if (newlen > oldlen) newsize += count * (newlen - oldlen);
    if (newlen < oldlen) newsize -= count * (oldlen - newlen);
    ret = malloc(newsize);
    
  3. 确保足够的空间。 @hyde这里有各种方法。

    // strcpy(text, newsms);
    if (strlen(newsms) >= sizeof text) Handle_Error();
    strcpy(text, newsms);
    
  4. 次要

    1. 无需演员阵容

      // newsms = replace(text, (char *) str2rep[j], (char *) replacement[j]);
      newsms = replace(text, str2rep[j], replacement[j]);
      
    2. 最好将size_t用于i。一个迂腐的解决方案也会使用size_t count

      // int i;
      size_t i;
      

答案 1 :(得分:0)

我会建议一些对我来说更清晰的替代方案,取代适当的动态字符串实现。异常处理留给读者添加的练习。 :)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *appendn(char *to, char *from, int length)
{
  return strncat(realloc(to, strlen(to) + length + 1), from, length);
}

char *replace(char *string, char *find, char *sub)
{
  char *result = calloc(1, 1);

  while (1)
    {
      char *found = strstr(string, find);
      if (!found)
        break;

      result = appendn(result, string, found - string);
      result = appendn(result, sub, strlen(sub));
      string = found + strlen(find);
    }

  return appendn(result, string, strlen(string));
}

int main()
{
  const char text[] = "some [1] with [2] to [3] with other [2]";
  char *find[] = {"[1]", "[2]", "[3]", NULL};
  char *sub[] = {"text", "words", "replace"};
  char *result, *s;
  int i;

  result = malloc(sizeof(text));
  (void) strcpy(result, text);
  for (i = 0; find[i]; i ++)
    {
      s = replace(result, find[i], sub[i]);
      free(result);
      result = s;
    }

  (void) printf("%s\n", result);
  free(result);
}