在C语言中比较以null结尾的字符串和非以null结尾的字符串

3
我正在使用的反序列化库(messagepack)不提供以null结尾的字符串。相反,我会得到一个指向字符串开头和长度的指针。比较这个字符串与普通的以null结尾的字符串的最快方法是什么?

首先比较字符串的长度:如果它们不相等,那么字符串也是不相等的。如果长度相等,你可以使用memcmp()函数比较字符串的内容。 - undefined
3个回答

4
最快的方式是使用 strncmp() 函数,该函数限制了要进行比较的长度。
 if (strncmp(sa, sb, length)==0)  
    ...

这假设你使用的长度是两个字符串中的最大长度。如果以 null 作为结尾的字符串可能具有更大的长度,则首先必须比较长度。
 if(strncmp(sa,sb, length)==0 && strlen(sa)<=length) // sa being the null terminated one
     ...

请注意,在比较之后有意地检查了strlen(),以避免在第一个字符甚至不匹配时不必要地迭代遍历所有以null结尾的字符串中的所有字符。最终变体是:
 if(strncmp(sa,sb, length)==0 && sa[length]==0) // sa being the null terminated one
     ...

问题是,如果我有一个没有空字符结尾的字符串"abc",和一个以空字符结尾的字符串"abcdef",那么使用n = 3的strncmp函数会返回它们相等。我可以先对"abcdef"进行strlen操作,但这会引入额外的遍历"abcdef"的过程。 - undefined
2
你不需要额外的步骤,只需在已知长度的以空字符结尾的字符串中检查是否存在空字符,如果它们与strncmp相等,则可以。但是,如果非以空字符结尾的字符串可能包含嵌入的空字符,你仍然可能遇到问题。 - undefined
@doynax 很聪明!感谢你和Christophe。 - undefined
它经过了太多次循环,并且在存在嵌入的NUL字符时完全错误。顺便问一下:length是什么意思? - undefined
@wildpasser收到的字符串是一个真实的字符串。只是它没有以空字符结尾(当然,反序列化库将读取的数据保存在缓冲区中,并且不会更改它)。 - undefined

3
这里有一种方法:
bool is_same_string(char const *s1, char const *s2, size_t s2_len)
{
    char const *s2_end = s2 + s2_len;
    for (;;)
    {
        if ( s1[0] == 0 || s2 == s2_end )
            return s1[0] == 0 && s2 == s2_end;

        if ( *s1++ != *s2++ )
            return false;
    }
}

1
int compare(char *one, size_t onelen, char *two, size_t twolen)
{
int dif;

  dif = memcmp(one, two, onelen < twolen ? onelen : twolen);
  if (dif) return dif;

  if (onelen == twolen) return 0;
  return onelen > twolen? 1 : -1;
}

使用方法:

...
int result;
char einz[4] = "einz"; // not terminated
char *zwei = "einz";   // terminated

result = compare(einz, sizeof einz, zwei, strlen(zwei));

...

这是一个不错的替代方案。不幸的是,尽管两个字符串相等,但你的使用示例返回-1。也许你可以将最后一条语句改为return onelen - twolen;。顺便说一下,你的使用场景需要太多次遍历,因为你总是要通过遍历以空字符结尾的字符串来获取其长度...;-) - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接