奇怪的结果与C字符串

问题描述:

我期待“匹配!”当n2的尾部与n1尾部相同时,否则“不匹配!”。 “匹配!”的示例:n1 = 123456n2 = 3456奇怪的结果与C字符串

问题出在我输入时,例如n1 = "45"n2 = "645"。它不应该匹配,但输出是“匹配!”。

bool different_tail = false; 

char n1[11], n2[11]; 

cin >> n1 >> n2; 

for(int i = strlen(n1)-strlen(n2); i < strlen(n1); i++){ 
    if(i < 0 || n1[i] != n2[i-(strlen(n1)-strlen(n2))]){ 
    different_tail = true; 
    break; 
    } 
} 

if(different_tail) 
    cout << "does not match!" << endl; 
else 
    cout << "match!" << endl; 

我不想用其他方法来解决问题(比如strcmp等),我想了解发生了什么。

+11

这听起来像你可能需要学习如何使用调试器来逐步执行代码。使用一个好的调试器,您可以逐行执行您的程序,并查看它与您期望的偏离的位置。如果你打算做任何编程,这是一个重要的工具。进一步阅读:** [如何调试小程序](http://ericlippert.com/2014/03/05/how-to-debug-small-programs/)** – NathanOliver

+0

Nathan,strlen(n1)-strlen( n2)是-1,'for'没有执行......我不知道为什么。而且我无法调试其他任何东西来了解这一点。 – WithoutNameZin

会发生什么情况是,随着n145n2645,循环变量i将在-1开始,即是负数。

但是,strlen会生成一个无符号值(类型为size_t的值)。比较带符号和无符号值(如在表达式i < strlen(n1)中进行的操作)时,有符号值将转换为无符号值。由于它是负值,这会导致下溢,所以i是一个非常大的值 - 大于strlen(n1)

你可以观察到与例如同样的效果。

int i = -1; 
size_t x = 5; 
if (i < x) { 
    cout << "yes\n"; 
} else { 
    cout << "no\n"; 
} 

该程序打印no

您可以通过铸造strlen的返回值避免你的问题,即改变你的循环条件

i < static_cast<int>(strlen(n1)) 

This question(和附带的答案)提供这个话题更深入的讨论。

+0

哦,我知道了。对我来说非常奇怪。非常感谢! – WithoutNameZin

看这个行:

for(int i = strlen(n1)-strlen(n2); i < strlen(n1); i++){

i这里是一个intstrlen(n1)size_t(无符号整型)。在有符号和无符号类型之间执行“小于”运算符会将所有操作数转换为无符号类型,在这种情况下,unsigned(i)将变成一个非常大的整数,因此永远不会执行for循环。

顺便说一句,在for循环中使用strlen并不是一个好习惯,因为strlen是一个昂贵的函数,并且将在每次迭代中调用。您可以将strlen结果存储在变量中,然后使用该变量。

+0

谢谢,我不知道! – WithoutNameZin