Обратите внимание, что я полный новичок в C++. Я пытаюсь написать простую программу для банкомата, и мне приходится учитывать все ошибки. Пользователь может использовать только целые числа для ввода, поэтому мне нужно проверить, действительно ли входное значение является целым числом, и моя программа (эта сокращенная) работает по большей части.

Проблема возникает, когда я пытаюсь ввести строковое значение вместо целого числа при выборе операции. Он работает с недопустимыми целыми числами, но со строками он создает бесконечный цикл, пока в конце концов не остановится (если я не добавлю system("cls"), тогда он даже не остановится), когда он должен выводить тот же результат, что и для недопустимого целые числа:

Invalid choice of operation.
Please select an operation:

 1 - Balance inquiry
 7 - Return card

Enter your choice and press return:

Вот мой код:

#include <iostream>
#include <string>
using namespace std;


bool isNumber(string s) //function to determine if input value is int
{
    for (int i = 0; i < s.length(); i++)
        if (isdigit(s[i]) == false)
            return false;
    return true;
}


int ReturnCard() //function to determine whether to continue running or end program
{
    string rtrn;

    cout << "\nDo you wish to continue? \n1 - Yes \n2 - No, return card" << endl;
    cin >> rtrn;
    if (rtrn == "1" and isNumber(rtrn)) { return false; }
    else if (rtrn == "2" and isNumber(rtrn)) { return true; }
    else {cout << "Invalid choice." << endl; ReturnCard(); };
    return 0;
}


int menu() //function for operation choice and execution
{
    int choice;
    do
    {
        cout << "\nPlease select an operation:\n" << endl
            << " 1 - Balance inquiry\n"
            << " 7 - Return card\n"
            << "\nEnter your choice and press return: ";
        int balance = 512;
        cin >> choice;
        if (choice == 1 and isNumber(to_string(choice))) { cout << "Your balance is $" << balance; "\n\n"; }
        else if (choice == 7 and isNumber(to_string(choice))) { cout << "Please wait...\nHave a good day." << endl; return 0; }
        else { cout << "Invalid choice of operation.";  menu(); }
    } while (ReturnCard()==false);
    cout << "Please wait...\nHave a good day." << endl;
    return 0;
}

int main()
{
    string choice;
    cout << "Insert debit card to get started." << endl;
    menu();
    return 0;
}

Я пробовал все возможные решения, которые я знаю, но ничего не работает.

*** Существует другая ошибка, которая заключается в том, что когда я добираюсь до «Вы хотите продолжить?» часть и введите любое недопустимое значение, а затем введите 2 (что должно завершить программу), после того, как он снова спросит, он выводит результат для 1 (продолжить работу - меню и т. д.). Я уже написал об этом своему учителю по электронной почте, и это не мой главный вопрос, но я был бы признателен за любую помощь.

Спасибо!

2
Witch Hazel 4 Фев 2022 в 13:12
isNumber кажется излишним, вы называете его "1" или "2".
 – 
Jarod42
4 Фев 2022 в 13:17
Каково содержание строки? Вы можете распечатать это с помощью cout << rtrn;
 – 
vll
4 Фев 2022 в 13:18
Вы пропустили return ReturnCard(); для своего рекурсивного вызова.
 – 
Jarod42
4 Фев 2022 в 13:20
Тип choiceint. Это всегда не что иное, как целое число, поэтому нет смысла проверять. По сути, есть два способа определить, что ввод является целым числом: 1) чтение успешно (if (cin >> choice) ...); и 2) Чтение строки и успешное преобразование ее в целое число.
 – 
molbdnilo
4 Фев 2022 в 13:26
При каких условиях вы ожидаете, что isNumber(to_string(choice)) будет ложным? Вы уже определили, что choice равно 1 или 7, и это, вероятно, числа.
 – 
molbdnilo
4 Фев 2022 в 13:28

1 ответ

Всегда полезно сохранять консольный ввод в строковой переменной, а не в другой. тип, напр. int или double. Это позволяет избежать проблем с ошибками ввода, например. если символы вместо цифр задаются пользователем программы. После этого строковая переменная может быть проанализирована для дальнейших действий.
Поэтому я изменил тип choice с int на string и принял нисходящий код к нему.

Пожалуйста, попробуйте следующую программу и рассмотрите мои адаптации, которые пишется как комментарий, начинающийся с тега //CKE:. Спасибо.

#include <iostream>
#include <string>
using namespace std;


bool isNumber(const string& s) //function to determine if input value is int
{
    for (size_t i = 0; i < s.length(); i++) //CKE: keep same variable type, e.g. unsigned
        if (isdigit(s[i]) == false)
            return false;
    return true;
}


bool ReturnCard() //function to determine whether to continue running or end program
{
    string rtrn;

    cout << "\nDo you wish to continue? \n1 - Yes \n2 - No, return card" << endl;
    cin >> rtrn;
    if (rtrn == "1" and isNumber(rtrn)) { return false; }
    if (rtrn == "2" and isNumber(rtrn)) { return true; } //CKE: remove redundant else
    cout << "Invalid choice." << endl; ReturnCard(); //CKE: remove redundant else + semicolon
    return false;
}


int menu() //function for operation choice and execution
{
    string choice; //CKE: change variable type here from int to string
    do
    {
        cout << "\nPlease select an operation:\n" << endl
            << " 1 - Balance inquiry\n"
            << " 7 - Return card\n"
            << "\nEnter your choice and press return: ";
        int balance = 512;
        cin >> choice;
        if (choice == "1" and isNumber(choice)) { cout << "Your balance is $" << balance << "\n\n"; } //CKE: semicolon replaced by output stream operator
        else if (choice == "7" and isNumber(choice)) { cout << "Please wait...\nHave a good day." << endl; return 0; }
        else { cout << "Invalid choice of operation."; } //CKE: remove recursion here as it isn't required
    } while (!ReturnCard()); //CKE: negate result of ReturnCard function
    cout << "Please wait...\nHave a good day." << endl;
    return 0;
}

int main()
{
    string choice;
    cout << "Insert debit card to get started." << endl;
    menu();
    return 0;
}
0
CKE 4 Фев 2022 в 15:11