比较两个 C 风格字符串的 C++ For 循环的效率和可读性
Efficiency & Readabilty of a C++ For Loop that Compares two C-style Strings
所以我创建了自己的函数来比较两个 C 字符串:
bool list::compareString(const char array1[], const char array2[])
{
unsigned char count;
for (count = 0; array1[count] != '[=10=]' && array2[count] != '[=10=]' && (array1[count] == array2[count] || array1[count + 32] == array2[count] || array1[count] == array2[count+32]); count++);
if (array1[count] == '[=10=]' && array2[count] == '[=10=]')
return true;
else
return false;
}
我的 for 循环的参数很长,因为它将计数带到至少一个字符串的末尾,并比较每个数组中的每个 char
,以便它们的大小写不会'无关紧要(将 32 添加到大写字母 char
会将 char
变成对应的小写字母)。
现在,我猜这是比较两个 C 字符串的最有效方法,但是 for 循环由于其长度而难以阅读。有人告诉我的是尽可能使用 for 循环而不是 while 循环,因为 for 循环在其起始参数中具有开始、结束和递增条件,但为此,这似乎不适用。
我想问的是,我应该如何格式化这个循环,有没有更有效的方法来做到这一点?
array1[count + 32] == array2[count]
如果数组的长度小于 32,则可能导致 OutOfRangeException。
您可以使用 strcmp 比较两个字符串
您可以直接对指针进行操作,而不是用 count
索引到您不知道其大小的数组中:
bool list::compareString(const char* array1, const char* array2)
{
while (*array1 != '[=10=]' || *array2 != '[=10=]')
if (*array1++ != *array2++) return false; // not the same character
return true;
}
对于不区分大小写的比较,将 if 条件替换为:
if (tolower(*array1++) != tolower(*array2++)) return false;
这会将字符安全地转换为小写。
while 循环检查字符串是否终止。它会在其中一个字符串尚未终止时继续。如果只有 1 个字符串终止,则下一行 - if 语句将意识到字符不匹配(因为只有 1 个字符是 '[=14=]'
,而 returns false.
如果字符串在任何一点不同,则 if 语句 returns false。
if 语句还 post 递增指针,以便它在 while 循环的下一次迭代中测试下一个字符。
如果两个字符串相等,并且同时终止,那么在某个时候,while 条件会变为假。在这种情况下,将执行 return true
语句。
如果您想自己编写tolower
函数,您需要检查字符是否为大写字母,而不是其他类型的字符(例如,数字符号)。
这将是:
inline char tolower(char ch)
{
return (ch >= 'A' && ch <= 'Z' ? (ch + 'a' - 'A') : ch);
}
您的代码有一些问题。
我在这里要做的是将您的一些逻辑移动到 for 循环的主体中。将所有内容都塞进 for 循环表达式会大大降低可读性,而不会给我带来我能想到的任何性能提升。代码最终变得混乱。将循环的条件保留为测试增量并将实际任务放在主体中。
我还要指出,您根本没有向该字符添加 32。您将它添加到数组的索引中,使您面临 运行 越界的风险。您需要测试索引处的值,而不是索引本身。
使用 unsigned char 索引数组没有任何好处,只会减少可以比较的字符串的最大长度。使用一个整数。
您可以重组代码,使其看起来像这样:
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] != '[=10=]' && array2[count] != '[=10=]'; 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;
}
至于效率,在我看来你正在尝试减少:
- 您用来存储数据的变量的大小
内存
- 您的解决方案中单独的代码行数
这些都不值得你花时间。效率是关于执行一项任务需要多少步骤(不是代码行,请注意),以及这些步骤如何随着输入变大而扩展。比如比较两部小说的内容是否相等,比比较两个单字串要慢多少?
希望对您有所帮助:)
我猜你想在这里进行不区分大小写的比较。如果您只需要最快的版本,请使用库函数:strcasecmp
或 stricmp
或 strcmpi
(名称取决于您的平台)。
如果您需要了解如何操作(我的意思是,您的问题是出于学习目的吗?),请从 可读 版本开始,如下所示:
for (index = 0; ; ++index)
{
if (array1[index] == '[=10=]' && array2[index] == '[=10=]')
return true; // end of string reached
if (tolower(array1[index]) != tolower(array2[index]))
return false; // different characters discovered
}
然后测量它的性能。如果足够好,完成。如果不是,调查原因(通过查看编译器生成的机器代码)。优化的第一步 可能 是用一段手工编写的代码替换 tolower
库函数(忽略非英文字符 - 这是你想做的吗? ):
int tolower(int c)
{
if (c >= 'A' && c <= 'Z')
return c + 'a' - 'A';
}
请注意,我仍然保持代码的可读性。可读代码可以很快,因为编译器会对其进行优化。
所以我创建了自己的函数来比较两个 C 字符串:
bool list::compareString(const char array1[], const char array2[])
{
unsigned char count;
for (count = 0; array1[count] != '[=10=]' && array2[count] != '[=10=]' && (array1[count] == array2[count] || array1[count + 32] == array2[count] || array1[count] == array2[count+32]); count++);
if (array1[count] == '[=10=]' && array2[count] == '[=10=]')
return true;
else
return false;
}
我的 for 循环的参数很长,因为它将计数带到至少一个字符串的末尾,并比较每个数组中的每个 char
,以便它们的大小写不会'无关紧要(将 32 添加到大写字母 char
会将 char
变成对应的小写字母)。
现在,我猜这是比较两个 C 字符串的最有效方法,但是 for 循环由于其长度而难以阅读。有人告诉我的是尽可能使用 for 循环而不是 while 循环,因为 for 循环在其起始参数中具有开始、结束和递增条件,但为此,这似乎不适用。
我想问的是,我应该如何格式化这个循环,有没有更有效的方法来做到这一点?
array1[count + 32] == array2[count] 如果数组的长度小于 32,则可能导致 OutOfRangeException。 您可以使用 strcmp 比较两个字符串
您可以直接对指针进行操作,而不是用 count
索引到您不知道其大小的数组中:
bool list::compareString(const char* array1, const char* array2)
{
while (*array1 != '[=10=]' || *array2 != '[=10=]')
if (*array1++ != *array2++) return false; // not the same character
return true;
}
对于不区分大小写的比较,将 if 条件替换为:
if (tolower(*array1++) != tolower(*array2++)) return false;
这会将字符安全地转换为小写。
while 循环检查字符串是否终止。它会在其中一个字符串尚未终止时继续。如果只有 1 个字符串终止,则下一行 - if 语句将意识到字符不匹配(因为只有 1 个字符是 '[=14=]'
,而 returns false.
如果字符串在任何一点不同,则 if 语句 returns false。
if 语句还 post 递增指针,以便它在 while 循环的下一次迭代中测试下一个字符。
如果两个字符串相等,并且同时终止,那么在某个时候,while 条件会变为假。在这种情况下,将执行 return true
语句。
如果您想自己编写tolower
函数,您需要检查字符是否为大写字母,而不是其他类型的字符(例如,数字符号)。
这将是:
inline char tolower(char ch)
{
return (ch >= 'A' && ch <= 'Z' ? (ch + 'a' - 'A') : ch);
}
您的代码有一些问题。
我在这里要做的是将您的一些逻辑移动到 for 循环的主体中。将所有内容都塞进 for 循环表达式会大大降低可读性,而不会给我带来我能想到的任何性能提升。代码最终变得混乱。将循环的条件保留为测试增量并将实际任务放在主体中。
我还要指出,您根本没有向该字符添加 32。您将它添加到数组的索引中,使您面临 运行 越界的风险。您需要测试索引处的值,而不是索引本身。
使用 unsigned char 索引数组没有任何好处,只会减少可以比较的字符串的最大长度。使用一个整数。
您可以重组代码,使其看起来像这样:
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] != '[=10=]' && array2[count] != '[=10=]'; 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;
}
至于效率,在我看来你正在尝试减少:
- 您用来存储数据的变量的大小 内存
- 您的解决方案中单独的代码行数
这些都不值得你花时间。效率是关于执行一项任务需要多少步骤(不是代码行,请注意),以及这些步骤如何随着输入变大而扩展。比如比较两部小说的内容是否相等,比比较两个单字串要慢多少?
希望对您有所帮助:)
我猜你想在这里进行不区分大小写的比较。如果您只需要最快的版本,请使用库函数:strcasecmp
或 stricmp
或 strcmpi
(名称取决于您的平台)。
如果您需要了解如何操作(我的意思是,您的问题是出于学习目的吗?),请从 可读 版本开始,如下所示:
for (index = 0; ; ++index)
{
if (array1[index] == '[=10=]' && array2[index] == '[=10=]')
return true; // end of string reached
if (tolower(array1[index]) != tolower(array2[index]))
return false; // different characters discovered
}
然后测量它的性能。如果足够好,完成。如果不是,调查原因(通过查看编译器生成的机器代码)。优化的第一步 可能 是用一段手工编写的代码替换 tolower
库函数(忽略非英文字符 - 这是你想做的吗? ):
int tolower(int c)
{
if (c >= 'A' && c <= 'Z')
return c + 'a' - 'A';
}
请注意,我仍然保持代码的可读性。可读代码可以很快,因为编译器会对其进行优化。