【问题标题】:Compare two character strings in C [closed]比较C中的两个字符串[关闭]
【发布时间】:2020-06-10 10:48:37
【问题描述】:

我的代码有问题吗?我在互联网上找到了很多代码,但它们都很复杂,我编写了我的代码及其在我的测试中的工作。你看到这段代码有什么问题吗?

bool is_equal(char str1[], char str2[])
{
    int i;
    bool isEqual;

    for(i=0; str1[i] != '\0' || str2[i] !='\0'; i++)
    {
        if(str1[i] != str2[i])
            isEqual = false;
        else
            isEqual = true;
    }

    return isEqual;
}

【问题讨论】:

  • 是的,一旦您将isEqual 设置为false,您以后就不想将其更改为true。最好立即返回false ...如果你到达它,最好在循环结束时返回return true;
  • 1) 如果传递字符串"abcd""aXcd",你的代码会返回什么? 2)如果通过"abcd""abc"会怎样?
  • 这段代码有很多个错误。我还想知道你在网上找到的代码有什么“复杂”的地方,因为从根本上说,这是一个简单、成熟的解决方案(别忘了strcmp(a, b) == 0 存在)的简单问题。
  • 你需要学会调试。
  • 与其询问其他人,更好的测试方法是使用单元测试库,并编写一些测试。然后用你能找到的任何消毒剂(记忆、种族……)运行它们。比较所有 """a""aa""aaa""aab""baa" 对应该会发现所有微不足道的错误。

标签: c


【解决方案1】:

好的,到此结束。让我们想想什么是字符串比较。首先,让我们忽略 NULL 指针,并假设两个字符串实际上都是有效的字符串。那么我们就不需要特别检查了。

我们将通过简单地逐个元素地比较它们来做到这一点。每当我们比较同一索引处的两个元素时,可能会发生以下三种情况之一:

  1. 两个元素都是'\0'。字符串是相等的。返回真。
  2. 元素不同。停止比较并返回 false。
  3. 元素相等,但'\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

【讨论】:

  • @Magic 两者都可以。但如果字符串的长度相等,则无需比较终止符。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-04
  • 1970-01-01
相关资源
最近更新 更多