效率& C ++ For循环的可读性比较两个C风格的字符串

时间:2015-10-09 21:05:18

标签: c++ for-loop c-strings

所以我创建了自己的函数来比较两个C字符串:

bool list::compareString(const char array1[], const char array2[])
{
    unsigned char count;
    for (count = 0; array1[count] != '\0' && array2[count] != '\0' && (array1[count] == array2[count] || array1[count + 32] == array2[count] || array1[count] == array2[count+32]); count++);
    if (array1[count] == '\0' && array2[count] == '\0')
        return true;
    else
        return false;
}

我的for循环的参数非常长,因为它将计数带到至少一个字符串的末尾,并比较每个数组中的每个char,以便它们的情况赢得'重要的是(将大写char添加32将char转换为小写的对应方式。)

现在,我猜测这是比较两个C字符串的最有效方法,但由于它的长度,for循环难以阅读。我被告知的是尽可能使用for循环而不是while循环,因为for循环在其起始参数中具有起始,结束和递增条件,但为此,这似乎可能不适用

我要问的是,我应该如何格式化这个循环,是否有更有效的方法呢?

4 个答案:

答案 0 :(得分:5)

您可以直接在指针上操作,而不是使用count索引到数组,而不是直接对指针进行操作:

bool list::compareString(const char* array1, const char* array2)
{
    while (*array1 != '\0' || *array2 != '\0')
        if (*array1++ != *array2++) return false; // not the same character

    return true;
}

对于不区分大小写的比较,请将if条件替换为:

        if (tolower(*array1++) != tolower(*array2++)) return false;

这可以安全地将字符转换为小写。

while循环检查字符串是否终止。它继续,而其中一个字符串尚未终止。如果只有1个字符串终止,则下一行 - if语句将意识到字符不匹配(因为只有1个字符是'\0',并返回false。

如果字符串在任何时候都不同,则if语句返回false。

if语句也会对指针进行后递增,以便它在while循环的下一次迭代中测试下一个字符。

如果两个字符串相等,并且在某个时刻同时终止,则while条件将变为false。在这种情况下,return true语句将执行。

如果你想自己编写tolower函数,你需要检查字符是大写字母,而不是不同类型的字符(例如,一些符号)。

这将是:

inline char tolower(char ch)
{
    return (ch >= 'A' && ch <= 'Z' ? (ch + 'a' - 'A') : ch);
}

答案 1 :(得分:3)

我猜你在这里尝试进行不区分大小写的比较。如果您只需要最快的版本,请使用库函数:strcasecmpstricmpstrcmpi(名称取决于您的平台)。

如果您需要了解如何操作(我的意思是,您的问题是出于学习目的吗?),请从可读版本开始,如下所示:

for (index = 0; ; ++index)
{
    if (array1[index] == '\0' && array2[index] == '\0')
        return true; // end of string reached

    if (tolower(array1[index]) != tolower(array2[index]))
        return false; // different characters discovered
}

然后衡量其表现。如果它足够好,那就完成了。如果没有,请调查原因(通过查看编译器生成的机器代码)。优化的第一步可能用手工制作的代码替换tolower库函数(忽略非英文字符 - 这是你想要做的吗?):< / p>

int tolower(int c)
{
    if (c >= 'A' && c <= 'Z')
        return c + 'a' - 'A';
}

请注意,我仍然保持代码可读。可读代码可以很快,因为编译器将对其进行优化。

答案 2 :(得分:0)

array1 [count + 32] == array2 [count] 如果数组的长度小于32,则可能导致OutOfRangeException。 您可以使用strcmp比较两个字符串

答案 3 :(得分:0)

您的代码存在一些问题。

我在这里做的是将你的一些逻辑移到for循环的主体中。将所有内容塞入for循环表达式会大大降低可读性,而不会给您带来任何我能想到的性能提升。代码最终变得混乱。保持循环的条件以测试增量并将实际任务放在正文中。

我还指出你根本没有为角色添加32。您将其添加到数组的索引中会使您面临超出范围的风险。您需要在索引处测试值,而不是索引本身。

使用unsigned char为数组建立索引不会给您带来任何好处,只能减少您可以比较的字符串的最大长度。使用int。

您可以重新构建代码,使其如下所示:

bool list::compareString(const char array1[], const char array2[])
{
    // Iterate over the strings until we find the string termination character
    for (int count = 0; array1[count] != '\0' && array2[count] != '\0'; count++) {

      // Note 0x20 is hexadecimal 32. We're comparing two letters for
      // equality in a case insensitive way.
      if ( (array1[count] | 0x20) != (array2[count] | 0x20) ) {
          // Return false if the letters aren't equal
          return false;
      }
    }
    // We made it to the end of the loop. Strings are equal.
    return true;
}

至于效率,在我看来,你正试图减少:

  1. 您用于存储数据的变量的大小 存储器
  2. 解决方案中各行代码的数量
  3. 这些都不值得你花时间。效率是指执行任务需要多少步骤(不是代码行,请注意你)以及这些步骤随着输入变大而如何缩放。例如,比较两部小说的内容是否比两个单字串要慢多少?

    我希望有帮助:)