goto не выполняет свою функцию
Пытаюсь применить goto в операторе switch. После введения двух отрицательных чисел, goto должен прыгать к метке в начало, чтобы пользователь ввёл числа заново, пока два числа не будут оба положительными, но goto не делает своей работы.
Код:
#include <iostream>
int calculate(int x, int y, char op)
{
try_again:
std::cout << "Enter a first non-negative number: ";
std::cin >> x;
std::cout << "Enter a second non-negative number: ";
std::cin >> y;
std::cout << "Choose an operator: +, -, *, /: ";
std::cin >> op;
switch(op)
{
case '+':
if((x && y) < 0)
goto try_again;
else
return x + y;
break;
case '-':
if((x && y) < 0)
goto try_again;
else
return x - y;
break;
case '*':
if((x && y) < 0)
goto try_again;
else
return x * y;
break;
case '/':
if((x && y) < 0)
goto try_again;
else
return x / y;
break;
default:
return false;
break;
}
}
int main(void)
{
int x, y;
char op;
std::cout << calculate(x, y, op) << '\n';
}
Ответы (3 шт):
if((x && y) < 0)
Начнем.
(x && y)
&& — логическое "И", значит, x и y переводятся в логические значения (равно нулю — false, не равно нулю — true, и вычислется логическое же значение И для них.
Далее - < — арифметика. true преобразуется в 1, false в 0, и выполняется сравнение. Очевидно, что в любом случае получается ложное значение — ни 1, ни 0 не меньше 0.
Правильно задавать вопрос не "если X и Y меньше 0", а "если X меньше 0 и Y меньше 0". Думаю, теперь вы сможете закодировать условие сами?
оператор && принимает только булевые переменные, и целые числа типа int преобразовывает на другой тип bool, который может принимать значения только ноль или единицу. Ваша запись ((x && y) < 0) переводится компилятором как (((x != 0) && (y != 0)) < 0), а так как результат может быть только 0 или 1, то ответ всегда не будет приниматься.
Не могу удержаться, чтобы не поправить. О том, что ошибка не в операторе goto, уже написали выше. Мои замечания в другом.
А вам обязательно использовать оператор
gotoпо условию задачи, или такового условия изначально нет? Я про то, чтоgoto- безусловно полезный инструмент, и в некоторых редких случаях без него действительно трудно обойтись. Однако всё же если есть возможность без ущерба для читабельности кода и производительности программы не использоватьgoto, следуетgotoне использовать. В вашем случае его легко можно заменить на циклwhile.Конструкция
if/elseи операторbreakв вашем примере совершенно излишни и только загромождают код.
Ввиду выше изложенного, привожу улучшенный и исправленный (но не оптимизированный!) вариант вашей функции calculate(). На другие возможные ошибки я её не проверял, если что.
int calculate(int x, int y, char op)
{
while (true) //вместо try_again:
{
std::cout << "Enter a first non-negative number: ";
std::cin >> x;
std::cout << "Enter a second non-negative number: ";
std::cin >> y;
std::cout << "Choose an operator: +, -, *, /: ";
std::cin >> op;
switch(op)
{
case '+':
if ((x<0) && (y<0))
continue; //вместо goto try_again;
//else тут лишнее!
return x + y;
//break тут лишний!
case '-':
if ((x<0) && (y<0))
continue; //вместо goto try_again;
return x - y;
case '*':
if ((x<0) && (y<0))
continue; //вместо goto try_again;
return x * y;
case '/':
if ((x<0) && (y<0))
continue; //вместо goto try_again;
return x / y;
default:
return false; //Возвращает bool, а тип результата int - не порядок!
//break и тут не нужен!
}
} //while (true)
}
P.S. Заметил ещё один недочёт. У вас функция calculate() возвращает результат вычислений типа int, однако в ветке default у вас возвращается false. Будучи приведённым к типу int у вас возвратится в этом случае 0. Если так и было задумано, то следует тогда написать return 0. Если нет, и для вас важно различать, был ли 0 результатом вычислений или некорректного ввода операции, то придётся изменить функцию. Исправлять не стал - самостоятельно, пожалуйста.
P.P.S. Как справедливо было замечено в комментариях, оператор if можно вообще вынести за switch - тогда код становится ещё лучше. Оптимизация))
int calculate(int x, int y, char op)
{
while (true) //вместо try_again:
{
std::cout << "Enter a first non-negative number: ";
std::cin >> x;
std::cout << "Enter a second non-negative number: ";
std::cin >> y;
std::cout << "Choose an operator: +, -, *, /: ";
std::cin >> op;
if ((x>=0) || (y>=0)) //инвертируем первоначальное условие, чтобы не писать continue
{
switch(op)
{
case '+': return x + y;
case '-': return x - y;
case '*': return x * y;
case '/': return x / y;
default: return 0; //будем пока так считать
}
}
} //while (true)
}