C:字符串和指针。以特定模式更改字符串中的子字符串

时间:2012-07-20 08:23:49

标签: c string parsing

我很难理解如何执行以下操作:

我有一个像这样定义的单词列表:

typedef struct _StringNode {
  char *str;
  struct _StringNode* next;
} StringNode;

现在我需要编写一个接收字符串的函数和两个相同长度的单词列表,我需要用第二个列表中的相应单词替换字符串中第一个列表中单词的每个外观。

示例:

        text: "stack overflow siteoverflow oveflow stack"
    patterns: [ "stack", "overflow", "site" ]
replacements: [ "Hello", "guys", "here" ]
      result: "Hello guys hereguys guys Hello"

对于每个单词:我正在尝试使用strstr(),因此我将获得指向字符串副本中单词出现的指针,然后更改单词,并提升指针文本字符串的副本。

char* replace(const char *text,
              const StringNode *patterns,
              const StringNode *replacements);

2 个答案:

答案 0 :(得分:1)

您可以使用此

char *strnreplace(char *st,const int length, 
                  const char *orig,const char *repl) {

  static char buffer[length];
  char *ch;

  if (!(ch = strstr(st, orig)))
      return st;

  strncpy(buffer, st, ch-st);
  buffer[ch-st] = 0;
  sprintf(buffer+(ch-st), "%s%s", repl, ch+strlen(orig));
  return buffer;
}


void replace(const char *text,
              const StringNode *patterns,
              const StringNode *replacements)
{
  StringNode *pat, *rep;
  char *temp = text;
  int length = strlen(text);
  for( pat = patterns, rep = replacements;
        pat->next != NULL;
        pat = pat->next, rep = rep->next ) {
        temp = strnreplace(temp, length, pat->str, rep->str);
  }
}

答案 1 :(得分:0)

也许是这样的:

char* replace(const char *text,
              const StringNode *patterns,
              const StringNode *replacements)
{
  char *out = malloc(1024), *put = out;

  while(*text != '\0)
  {
    const StringNode *piter, *riter;
    int found = 0;

    /* Check if current start of text matches any pattern. */
    for(piter = patterns, riter = replacements;
        piter != NULL;
        piter = piter->next, riter = riter->next)
    {
      const size_t plen = strlen(piter->str);
      if(strncmp(text, piter->str, plen) == 0)
      {
        /* Hit found, emit replacement. */
        const size_t rlen = strlen(riter->str);
        memcpy(out, riter->str, rlen);
        out += rlen;
        text += plen;
        found = 1;
        break;
      }
    }
    if(!found)
      *put++ = *text++;
  }
  *put = '\0';

  return out;
}

请注意,上面的处理缓冲区溢出,为简洁起见省略。我建议在动态字符串数据类型之上实现类似的东西,以使核心操作(追加)根据需要自动增长目标字符串。

更新为了回应评论,上面尝试实施的算法是:

set output to empty string
while text remaining
  if start of text matches pattern[i]
    append replacement[i] to output
    remove len(pattern[i]) characters from start of text
  else
    append first character of text to output
    remove first character of text

所以,只要text还剩下任何内容,就会重复检查模式匹配。