2016-01-13 3 views
0

Я ожидаю, что «матч!» когда хвост n2 совпадает с хвостом n1, в противном случае «не совпадают!». Пример «матч!»: n1 = 123456 и n2 = 3456.Странный результат с строками C

Проблема в том, что я ввожу, например, n1 = "45" и n2 = "645". Он не должен совпадать, но результат «match!».

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 (n1) -strlen n2) равно -1, а «for» не выполняется ... Я не знаю, почему. И я не могу отлаживать ничто другое, чтобы знать об этом. – WithoutNameZin

ответ

3

Что происходит, что с n1 быть 45 и n2 быть 645, переменная 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

0

Посмотрите на этой линии:

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

здесь i является int тогда strlen(n1) является size_t (целое число без знака типа). Выполнение оператора «меньше» между типом signed и unsigned будет преобразовывать все операнды в неподписанные типы, в этом случае unsigned(i) становится очень большим целым числом, поэтому цикл for никогда не выполняется.

Кстати, это неправдоподобно использовать strlen для цикла, поскольку strlen является дорогостоящей функцией и будет называться на каждой итерации. Вы можете сохранить strlen результат в переменной и вместо этого использовать переменную.

+0

Спасибо, я этого не знал! – WithoutNameZin

Смежные вопросы