好的,到此结束。让我们想想什么是字符串比较。首先,让我们忽略 NULL 指针,并假设两个字符串实际上都是有效的字符串。那么我们就不需要特别检查了。
我们将通过简单地逐个元素地比较它们来做到这一点。每当我们比较同一索引处的两个元素时,可能会发生以下三种情况之一:
- 两个元素都是
'\0'。字符串是相等的。返回真。
- 元素不同。停止比较并返回 false。
- 元素相等,但
'\0' 不相等。继续比较。
注意,“一个字符串结束”的情况包含在情况2中。如果只有一个字符串结束,那么我们会将'\0'与其他内容进行比较,因此它们会有所不同。
为了使代码非常容易编写,可以先检查长度是否相同。这让它变得更容易一些,因为如果它们的长度不同,那么它们就不同,如果它们的长度相同,你可以从零循环到那个长度。然后,您可以像这样非常简单地编写它:
bool is_equal(char str1[], char str2[])
{
if(strlen(str1) != strlen(str2))
return false;
for(int i=0; i<strlen(str1); i++) {
if(str1[i] != str2[i])
return false;
}
return true;
}
这里与您的代码不同的最重要的一点是,一旦您发现任何差异,您就可以返回 false。上面的代码很清晰,但是效率有点低。一个明显的优化是这样的:
bool is_equal(char str1[], char str2[])
{
int len1 = strlen(str1);
if(len1 != strlen(str2))
return false;
for(int i=0; i<len1; i++) {
if(str1[i] != str2[i])
return false;
}
return true;
}
这消除了循环中不必要的长度检查,但看起来更混乱。实际上,我想我更喜欢这个:
int len1 = strlen(str1);
int len2 = strlen(str1);
if(len1 != len2)
return false;
因为它看起来更干净。但这是一个额外的行和一个额外的变量。但是由于我们可以将长度检查和字符检查结合起来,我们可以完全摆脱它。
那么我们如何在字符检查中加入长度检查呢?嗯,像这样。我想指出,!str[i] 和 str[i] != '\0' 在这种情况下是完全等价的,这是一种非常常见的检查字符串结尾的方法。
bool is_equal(char str1[], char str2[])
{
// Infinite loop, but it does not matter. It will end when it should.
for(int i=0; ; i++) {
// If the strings are different, they are different
if(str1[i] != str2[i])
return false;
// At this stage we know that they are equal for all elements
// checked so far, so if both strings ends here, then they are equal.
if(!str1[i] && !str2[i])
return true;
}
}
这不是我的实现方式,我省略了一些细节。例如,我会使用size_t 而不是int 作为索引变量,使用const 作为指针。它旨在以一种非常简单的方式展示它是如何工作的。如果我实现它,我会做这样的事情:
bool is_equal(const char *str1, const char *str2)
{
while(true) {
if(*str1 != *str2)
return false;
if(!*str1 && !*str2)
return true;
str1++;
str2++;
}
}
如果您想使用索引变量或指针,通常只是个人喜好问题。就个人而言,我认为在这种情况下指针会更清晰一些。我还会考虑在循环之前的开头添加这些行:
assert(str1);
assert(str2);
如果你给它们一个 NULL 指针,它们会导致程序崩溃。
演示:
https://onlinegdb.com/r1XvzLR3I