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 шт):

Автор решения: Harry
if((x && y) <  0)

Начнем.

(x && y)

&& — логическое "И", значит, x и y переводятся в логические значения (равно нулю — false, не равно нулю — true, и вычислется логическое же значение И для них.

Далее - < — арифметика. true преобразуется в 1, false в 0, и выполняется сравнение. Очевидно, что в любом случае получается ложное значение — ни 1, ни 0 не меньше 0.

Правильно задавать вопрос не "если X и Y меньше 0", а "если X меньше 0 и Y меньше 0". Думаю, теперь вы сможете закодировать условие сами?

→ Ссылка
Автор решения: AlexGlebe

оператор && принимает только булевые переменные, и целые числа типа int преобразовывает на другой тип bool, который может принимать значения только ноль или единицу. Ваша запись ((x && y) < 0) переводится компилятором как (((x != 0) && (y != 0)) < 0), а так как результат может быть только 0 или 1, то ответ всегда не будет приниматься.

→ Ссылка
Автор решения: LShadow77

Не могу удержаться, чтобы не поправить. О том, что ошибка не в операторе goto, уже написали выше. Мои замечания в другом.

  1. А вам обязательно использовать оператор goto по условию задачи, или такового условия изначально нет? Я про то, что goto - безусловно полезный инструмент, и в некоторых редких случаях без него действительно трудно обойтись. Однако всё же если есть возможность без ущерба для читабельности кода и производительности программы не использовать goto, следует goto не использовать. В вашем случае его легко можно заменить на цикл while.

  2. Конструкция 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)
}
→ Ссылка