更好的搜索字符串的优化方式

时间:2014-05-23 13:13:48

标签: c substring

我有一个格式为Contact:

的字符串
<abcde@123.343:5060;gr=xyz123>;+g134,<more_text>

我需要在开场<和结束>之间提取内容 可能有<>的多个实例,但我必须从参数gr=所在的对中获取内容(仅出现一次)。

为了解决这个问题,我所做的是:

ptr = strstr(str,"gr=");
if(ptr)
{
   temp1= ptr;
   while(*temp1 && *temp1!='<')
   {
      temp1--;
   }
   strncpy(newstring,temp1,ptr-temp1); //will copy upto start of gr
   temp2 = strstr(ptr,">")
   if(temp2)
     strncat(newstring,ptr,temp2-ptr); // copy remaining string till it finds closing '>'
}

它工作正常,但我想知道是否有任何方法可以避免while循环并向后退?

3 个答案:

答案 0 :(得分:2)

您可以搜索第一次出现'&lt;'和'&gt;'看看'gr ='是否落在他们之间。

lt = strchr(ptr,'<');
gt = strchr(ptr,'>');
gr = strstr(ptr,"gr=");
if ( gr > lt && gr < gt) {
    strncat(newstring,lt,gt-lt);
}

答案 1 :(得分:1)

您可以使用strcspn获取下一个标记的偏移量。您的代码没有循环来查找下一个实例,但是这段代码确实如此。我假设你的循环在那之外,也许你需要适应一点。

size_t offset = 0, length;
offset = strcspn(str, "<");
while (str[offset] != '\0')
{
  ++offset;
  length = strcspn(str + offset, ">");
  ptr = strstr(str + offset, "gr=");
  if (ptr != NULL && ptr - str < offset + length)
  {
       strncpy(newstring, ptr + offset, length); 
       /* do what you need with newstring here */
  }
  offset = strcspn(str + offset + length + 1, "<");
}

答案 2 :(得分:1)

您可以通过解析字符串一次而不是更多来完成此操作(与此处的其他答案不同)。如果子字符串没有重复的字符,下面的代码可以处理您提供的任何子字符串。

我们的想法是在任何<>之间复制任何内容;当复制查找子字符串时,如果找不到,则继续,直到找到它为止。

char *str = "<abcde@123.343:5060;gr=xyz123>;+g134,<more_text>";
char result[MAX_LENGTH];
size_t i = 0, j = 0;
char copying = 0, found = 0;
const char *subs = "gr=";
const int subs_len = 3;
while ((char ch = *str))
{
    if (ch == '<')
       copying = 1;
    else if (ch == '>')
    {
       if (found)
          break;
       else
       {
          copying = 0;
          i = j = 0;
       }
    }
    else if (copying)
    {
       result[i++] = ch;
       if (!found)
       {
          if (ch == subs[j])
          {
             ++j;
             if (j == subs_len)
                found = 1;
          }
          else
          {
             j = (ch == subs[0]) ? 1 : 0;
          }
       }
    }
    ++str;
}
result[i] = '\0';