将未知长度的字符串与已知长度的字符串进行比较

Posted

技术标签:

【中文标题】将未知长度的字符串与已知长度的字符串进行比较【英文标题】:Compare string of unknown length against string of known length 【发布时间】:2020-02-16 17:28:58 【问题描述】:

我想比较一个未知长度的空终止字符串 (s1) 和一个已知长度的未终止字符串 (s2)。

!strncmp(s1, s2, s2_len) 接近正确,但如果 s2s1 的前缀,则结果也为 true。

strlen(s1) == s2_len && !strcmp(s1, s2) 是正确的,但会扫描两次 s1

显然,手动比较字符串也可以,但让我失去了 C 库在过去四十年中获得的所有闪亮优化。

有没有用 C 库函数实现这一点的好方法?

【问题讨论】:

第一个。但在比较相等之后,您还必须测试 s1[s2_len] == 0 @wildplasser 似乎值得作为实际答案发布 你去... 简单地说:“...使用 C 库函数”可能是因为库函数比使用纯 C 编写的等效函数更适合您的机器。但是:您是 结合两个库函数。组合功能是否仍会比具有 2 个测试条件的简单循环更快(如果我数对了)? @usr2564301,允许编译器用自己的版本替换几个标准函数(在 托管 环境中),这通常有额外的优化(例如 strlen 用于固定字符串)。 【参考方案1】:
if (!strncmp(s1, s2, s2_len) && s1[s2_len] == 0) ...

如果strncmp() 返回零,则s2s1 的前缀。

如果s1[s2_len] 为NUL,则字符串 相等 如果不是:那么strlen(s1) > s2_len 如果strncmp() 返回非零值,则跳过第二个测试(short-cicuit 评估)

【讨论】:

您不会将字符串结尾s1 的测试移到前面吗?这是一个重要的限制因素。 (补充)啊,等等。 s1 的长度在那时仍然未知。对。 :) 因为 s1 可以比 s2_len 短。 @usr2564301:访问s1[s2_len] 是不合适的,除非您知道字符串至少有那么长。如果s2_len 是10,并且s1s1[3] 处有一个空字节,那么访问s1[4] 或更高版本可能会有未定义的行为。【参考方案2】:

如果strncmp(s1, s2, s2_len) 返回0 你知道s1 至少和s2 一样长,所以你可以只检查终止符以排除s2 是@ 前缀的可能性987654326@:

if (!strncmp(s1, s2, s2_len) && s1[s2_len] == '\0') 
    // ...

【讨论】:

同上。如果 s1[s2_len] != '\0' strncmp 不应该被执行【参考方案3】:

您可以使用 strncmp 方法并检查 s1 中的 NUL 终止符:

!strncmp(s1, s2, s2_len) && !s1[s2_len]

【讨论】:

以上是关于将未知长度的字符串与已知长度的字符串进行比较的主要内容,如果未能解决你的问题,请参考以下文章

7.11牛课题

MD5绕过

在字符串中搜索未知模式的最有效方法?

ftl中比较两个字符串怎么比较

与包含它们的字符集进行比较时,只有 2 个表情符号返回错误的长度

关于如何使用一些已知的加密值查找解密公式的建议[关闭]