c - 是否有 strncmp() 的惯用用法?

标签 c strncmp

strncmp() 函数实际上只有一个用例(用于字典顺序):

其中一个字符串的长度已知, 另一个字符串已知以 NUL 结尾。 (作为奖励,已知长度的字符串根本不需要以 NUL 结尾。)

我认为只有一个用例的原因(前缀匹配检测不是字典顺序): (1) 如果两个字符串都以 NUL 终止,strcmp() 应该被使用,因为它会正确地完成工作; (2) 如果两个字符串的长度都已知,则应使用 memcmp(),因为它将避免在逐字节的基础上对 NUL 进行不必要的检查。

我正在寻找一种惯用(且可读)的方式来使用该函数按字典顺序正确比较两个这样的参数(其中一个以 NUL 终止,其中一个不一定以 NUL 终止,长度已知)。

Does an idiom exist? If so, what is it? If not, what should it be, or what should be used instead?

简单地使用 strncmp() 的结果是行不通的,因为在已知长度的参数比 NUL 终止的参数短的情况下,它会导致错误的相等结果,并且它恰好是一个前缀。因此,需要额外的代码来测试这种情况。

作为一个独立的函数,我看不出这种结构有什么问题,而且它看起来很地道:

/* s1 is NUL terminated */
int variation_as_function (const char *s1, const char *s2, size_t s2len) {
    int result = strncmp(s1, s2, s2len);
    if (result == 0) {
        result = (s1[s2len] != '\0');
    }
    return result;
}

但是,当将此构造内联到代码中时,当相等需要特殊操作时,它会导致对 0 进行双重测试:

int result = strncmp(key, input, inputlen);
if (result == 0) {
    result = (key[inputlen] != '\0');
}
if (result == 0) {
    do_something();
} else {
    do_something_else();
}

内联调用的动机是因为独立函数是深奥的:重要的是哪个字符串参数以 NUL 终止,哪个不是。

请注意,问题不是关于性能,而是关于编写惯用代码和采用编码风格的最佳实践。我发现比较中存在一些 DRY 违规行为。有没有直接的方法来避免重复?


† By known length, I mean the length is correct (there is no embedded NUL that would truncate the length). In other words, the input was validated at some earlier point in the program, and its length was recorded, but the input is not explicitly NUL terminated. As a hypothetical example, a scanner on a stream of text could have this property.
‡ As has been pointed out by addy2012, strncmp() could be used for prefix matching. I as focused on lexicographical ordering. However, (1) If the length of the prefix string is used as the length argument, both arguments need to be NUL terminated to guard against reading past an input string shorter than the prefix string. (2) If the minimum length is known between the prefix string and the input string, then memcmp() would be a better choice in terms of providing equivalent functionality at less CPU cost and no loss in readability.

最佳答案

The strncmp() function really only has one use case:

One of the strings has a known length, the other string is known to be NUL terminated.

不,你可以用它来比较两个字符串的开头,不管任何字符串的长度是否已知。例如,如果您有一个包含姓氏的数组/列表,并且您想要查找所有以“Mac”开头的内容。

关于c - 是否有 strncmp() 的惯用用法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30064870/

相关文章:

c - 如何将用户输入的字符串与C中文件中的字符串进行比较

c - 链接器/编译器/预处理问题

compilation - unistd.h 和 crypt.h 中的 crypt 有什么区别?

c - 使用 strcmp() 从客户端读取数据未按预期工作

C++:有趣的字符串比较崩溃

c - 结构字段中的 strcpy/strncpy 段错误

python - 为什么python中的字符串比较如此之快?

c - `int a[6][(2,2)]`数组是什么意思?

c - 启动没有标题栏的默认浏览器

为文件/目录树创建结构