Return 如果不是整数,则两个数字输入错误

Return an error for two inputs of numbers if not an integer

如果用户输入 characters/strings 到 num1、num2 然后改用正确的输入,我试图让程序 return 出错

我在互联网上搜索并找到了 cin.fail() 的解决方案,但它仅适用于第一个数字或根本不起作用

有人建议我通过弄清楚变量的类型然后比较来做到这一点,但我无法弄清楚

如何在没有函数但没有循环的情况下以最简单的方式进行验证?

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

int main () {

    int num1, num2; // two integers
    int choice; // chosen integers
    int ch1 = 0, ch2 = 0,ch3 = 0,ch4 = 0,ch5 = 0; // to keep track of chosen functions
    
    //const for choice of menu
    const int addition = 1,
              substruction = 2,
              multiplication = 3,
              division = 4, 
              modulo = 5,
              numberChange = 6;


    
    //intro
    cout << "This program has been made for arithmetic operations.\n";
    cout << "Please choose two  integers for arithmetic operations\n";
    cin >> num1 >> num2;


    do {
        cout << "Choose number of the operation you want to do\n";
        cout << "1. addition\n";
        cout << "2. subtraction\n";
        cout << "3. multiplication\n";
        cout << "4. division\n";
        cout << "5. modulo\n";
        cout << "6. CHANGE OF NUMBERS\n";
        cout << "To exit menu enter -1!\n";
        cin >> choice;

       

        switch (choice) {
            case 1:
            cout << "Result: " <<num1  << " + " << num2 << " = "<< num1 + num2 << endl;
            ch1++;
            break;
            case 2:
            cout << "Result: " <<num1  << " - " << num2 << " = "<< num1 - num2 << endl;
            ch2++;
            break;
            case 3: 
            cout << "Result: " <<num1  << " * " << num2 << " = "<<num1 * num2 << endl;
            ch3++;
            break;
            case 4:
            cout << "Result: " <<num1  << " / " << num2 << " = "<<num1 / num2 << endl;
            ch4++;
            break;
            case 5:
            cout << "Result: " <<num1  << " % " << num2 << " = "<<num1 % num2 << endl;
            ch5++;
            break;
            case 6:
            cout << "Okay, you can choose different numbers" << endl;
            cin >> num1 >> num2;
            break;
            case -1:

            ofstream myfile ("/Users/margaritakholostova/Desktop/us.txt");
            if (myfile.is_open())
             {
              myfile << "Addition was selected " << ch1 << " times\n";
              myfile << "Subtraction was selected " << ch2 << " times\n";
              myfile << "Multiplication was selected " << ch3 << " times\n";
              myfile << "Division was selected " << ch4 << " times\n";
              myfile << "Modulo was selected " << ch5 << " times\n";
              myfile.close();
            }
            else cout << "Unable to open file";
            return 0; 
            break;
        }

        //return error if input is not integer
        if (cin.fail()) {
            cout << "Error! Please put only integers!" << endl;
            cin.clear();
            cin.ignore(256, '\n');
            cin >> choice;
        }


        // validate the input for right number

        while (choice < addition || choice > numberChange )
        {
            if (choice != -1) {
                cout << "Please choose valid option out of menu (1-5)\n";
                cin >> choice;
            }
            
        }

    } while (choice != -1);        
}

您需要检查 std::cin 的错误状态,然后operator>> 返回的值进行操作。尝试更像这样的东西:

#include <iostream>
#include <fstream>
#include <limits>
using namespace std;

int main () {

    int num1, num2; // two integers
    int choice; // chosen integers
    int ch1 = 0, ch2 = 0, ch3 = 0, ch4 = 0, ch5 = 0; // to keep track of chosen functions
    
    //const for choice of menu
    const int addition = 1,
              substruction = 2,
              multiplication = 3,
              division = 4, 
              modulo = 5,
              numberChange = 6;

    //intro
    cout << "This program has been made for arithmetic operations.\n";
    cout << "Please choose two integers for arithmetic operations\n";

    //return error if input is not integers
    while (!(cin >> num1 >> num2)) {
        cin.clear();
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
        cout << "Error! Please enter only integers!\n";
    }

    do {
        cout << "Choose number of the operation you want to do\n";
        cout << "1. addition\n";
        cout << "2. subtraction\n";
        cout << "3. multiplication\n";
        cout << "4. division\n";
        cout << "5. modulo\n";
        cout << "6. CHANGE OF NUMBERS\n";
        cout << "To exit menu enter -1!\n";

        //return error if input is not integer
        while (!(cin >> choice)) {
            cin.clear();
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
            cout << "Error! Please enter only integers!\n";
        }

        // validate the input for right number
        switch (choice) {
            case 1:
                cout << "Result: " << num1 << " + " << num2 << " = " << num1 + num2 << '\n';
                ch1++;
                break;
            case 2:
                cout << "Result: " << num1 << " - " << num2 << " = " << num1 - num2 << '\n';
                ch2++;
                break;
            case 3: 
                cout << "Result: " << num1 << " * " << num2 << " = " << num1 * num2 << '\n';
                ch3++;
                break;
            case 4:
                cout << "Result: " << num1 << " / " << num2 << " = " << num1 / num2 << '\n';
                ch4++;
                break;
            case 5:
                cout << "Result: " << num1 << " % " << num2 << " = " << num1 % num2 << '\n';
                ch5++;
                break;
            case 6:
                cout << "Okay, you can choose different numbers\n";
                while (!(cin >> num1 >> num2)) {
                    cin.clear();
                    cin.ignore(numeric_limits<streamsize>::max(), '\n');
                    cout << "Error! Please enter only integers!\n";
                }
                break;
            case -1: {
                ofstream myfile ("/Users/margaritakholostova/Desktop/us.txt");
                if (myfile.is_open()) {
                    myfile << "Addition was selected " << ch1 << " times\n";
                    myfile << "Subtraction was selected " << ch2 << " times\n";
                    myfile << "Multiplication was selected " << ch3 << " times\n";
                    myfile << "Division was selected " << ch4 << " times\n";
                    myfile << "Modulo was selected " << ch5 << " times\n";
                    myfile.close();
                }
                else
                    cout << "Unable to open file\n";
                return 0; 
            }

            default:
                cout << "Please choose a valid option from the menu (1-5)\n";
                break;
        }
    }
    while (true);
}

线条

if ( cin.fail() )
{
    cout << "Error! Please put only integers!" << endl;
    cin.clear();
    cin.ignore(256, '\n');
    cin >> choice;
}

将无法正常工作,因为在您执行流故障检查时,您已经使用了

的结果
cin >> num1 >> num2;

cin >> choice;

switch 语句中。

因此,在 switch 语句之前执行这样的检查是有意义的。

另一方面,与其编写在每次输入操作后执行此类检查的代码,不如编写一个单独的函数 get_int_from_user 读取一行输入并尝试将其转换为整数。如果此转换失败,则此函数应自动重新提示用户输入,直到转换成功。这样,您在主代码中所要做的就是调用函数 get_int_from_user,该函数将为您处理大部分输入验证。由于函数 get_int_from_user 保证为 return 一个有效整数,因此您必须在主代码中执行的唯一输入验证是整数是否在所需范围内。这将使您的主要代码更容易编写。

另一个问题是进行范围检查会更有意义

while (choice < addition || choice > numberChange )
{
    if (choice != -1) {
        cout << "Please choose valid option out of menu (1-5)\n";
        cin >> choice;
    }

}

switch 语句中。这可以通过使用 default 标签轻松完成,如果值不匹配任何 case 标签,将执行该标签。

在下面的代码片段中,我提供了我对问题的解决方案。但是请注意,此解决方案使用三个 goto labels. The goto statement should generally be used cautiously, as it is bad programming practice to make excessive use of goto. It is usually better to use a proper for, while or do loop instead. However, using goto to break out of nested loops is generally considered appropriate。在我的解决方案中,无论如何我都需要两个 goto 标签,以便跳出嵌套循环。在这种情况下,我决定引入第三个 goto 标签并摆脱嵌套循环是合适的,因为它使代码更清晰。但是,由于大多数其他程序员可能会认为我的这个决定有争议,所以我在回答的最后提供了一个替代解决方案,其中我从函数 menu 中删除了两个 goto 标签,所以只有函数 get_int_from_user 使用 goto 标签,它严格用于跳出嵌套循环。

这是我的解决方案,它使用三个 goto 标签:

#include <iostream>
#include <string>
#include <stdexcept>
#include <cctype>

int get_int_from_user( const std::string& prompt );

void menu()
{
    int num1, num2;
    int choice;
    int ch1 = 0, ch2 = 0, ch3 = 0, ch4 = 0, ch5 = 0;

    //intro
    std::cout << "This program has been made for arithmetic operations.\n";

new_numbers:
    std::cout << "Please choose two integers for arithmetic operations.\n";

    num1 = get_int_from_user( "Please enter the first number: " );
    num2 = get_int_from_user( "Please enter the second number: " );

menu:
    std::cout <<
        "\n"
        "Choose number of the operation you want to do\n"
        "1. addition\n"
        "2. subtraction\n"
        "3. multiplication\n"
        "4. division\n"
        "5. modulo\n"
        "6. CHANGE OF NUMBERS\n"
        "To exit menu enter -1!\n"
        "\n";

    choice = get_int_from_user( "Please enter your choice: " );

    switch ( choice )
    {
        case 1:
            std::cout << "\nResult: " <<num1  << " + " << num2 << " = " << num1 + num2 << "\n\n";
            ch1++;
            goto menu;

        case 2:
            std::cout << "\nResult: " <<num1  << " - " << num2 << " = "<< num1 - num2 << "\n\n";
            ch2++;
            goto menu;

        case 3: 
            std::cout << "\nResult: " <<num1  << " * " << num2 << " = "<<num1 * num2 << "\n\n";
            ch3++;
            goto menu;

        case 4:
            std::cout << "\nResult: " <<num1  << " / " << num2 << " = "<<num1 / num2 << "\n\n";
            ch4++;
            goto menu;

        case 5:
            std::cout << "\nResult: " <<num1  << " % " << num2 << " = "<<num1 % num2 << "\n\n";
            ch5++;
            goto menu;

        case 6:
            std::cout << "Okay, you can choose different numbers.\n" << '\n';
            goto new_numbers;

        case -1:
            break;

        default:
            std::cout << "Please choose valid option out of menu (1-5)\n";
            goto menu;
    }

    std::cout <<
        "\n" <<
        "Addition was selected " << ch1 << " times\n" <<
        "Subtraction was selected " << ch2 << " times\n" <<
        "Multiplication was selected " << ch3 << " times\n" <<
        "Division was selected " << ch4 << " times\n" <<
        "Modulo was selected " << ch5 << " times\n";
}

int main()
{
    try
    {
        menu();
    }
    catch ( std::runtime_error& e )
    {
        std::cout << "Runtime error: " << e.what() << '\n';
    }
}

int get_int_from_user( const std::string& prompt )
{
    std::string line;
    std::size_t pos;
    int i;

    //repeat forever, until an explicit return statement or an
    //exception is thrown
    for (;;) //equivalent to while(true)
    {
        //prompt user for input
        std::cout << prompt;

        //attempt to read one line of input from user
        if ( !std::getline( std::cin, line ) )
        {
            throw std::runtime_error( "unexpected input error!\n" );
        }

        //attempt to convert string to integer
        try
        {
            i = std::stoi( line, &pos );
        }
        catch ( std::invalid_argument& )
        {
            std::cout << "Unable to convert input to number, try again!\n";
            continue;
        }
        catch ( std::out_of_range& )
        {
            std::cout << "Out of range error, try again!\n";
            continue;
        }

        //The remainder of the line is only allowed to contain
        //whitespace characters. The presence of any other
        //characters should cause the entire input to get rejected.
        //That way, input such as "6sdfj23jlj" will get rejected,
        //but input with trailing whitespace will still be accepted
        //(just like input with leading whitespace is accepted by
        //the function std::stoi).
        for ( ; pos < line.length(); pos++ )
        {
            if ( !std::isspace( static_cast<unsigned char>(line[pos]) ) )
            {
                std::cout << "Invalid character found, try again!\n";

                //we cannot use "continue" here, because that would
                //continue to the next iteration of the innermost
                //loop, but we want to continue to the next iteration
                //of the outer loop
                goto continue_outer_loop;
            }
        }

        //input is valid
        return i;

    continue_outer_loop:
        continue;
    }
}

此程序具有以下行为:

This program has been made for arithmetic operations.
Please choose two integers for arithmetic operations.
Please enter the first number: 3
Please enter the second number: 4

Choose number of the operation you want to do
1. addition
2. subtraction
3. multiplication
4. division
5. modulo
6. CHANGE OF NUMBERS
To exit menu enter -1!

Please enter your choice: 1

Result: 3 + 4 = 7


Choose number of the operation you want to do
1. addition
2. subtraction
3. multiplication
4. division
5. modulo
6. CHANGE OF NUMBERS
To exit menu enter -1!

Please enter your choice: 2

Result: 3 - 4 = -1


Choose number of the operation you want to do
1. addition
2. subtraction
3. multiplication
4. division
5. modulo
6. CHANGE OF NUMBERS
To exit menu enter -1!

Please enter your choice: 3

Result: 3 * 4 = 12


Choose number of the operation you want to do
1. addition
2. subtraction
3. multiplication
4. division
5. modulo
6. CHANGE OF NUMBERS
To exit menu enter -1!

Please enter your choice: 4

Result: 3 / 4 = 0


Choose number of the operation you want to do
1. addition
2. subtraction
3. multiplication
4. division
5. modulo
6. CHANGE OF NUMBERS
To exit menu enter -1!

Please enter your choice: 5

Result: 3 % 4 = 3


Choose number of the operation you want to do
1. addition
2. subtraction
3. multiplication
4. division
5. modulo
6. CHANGE OF NUMBERS
To exit menu enter -1!

Please enter your choice: 6
Okay, you can choose different numbers.

Please choose two integers for arithmetic operations.
Please enter the first number: 5 
Please enter the second number: 7

Choose number of the operation you want to do
1. addition
2. subtraction
3. multiplication
4. division
5. modulo
6. CHANGE OF NUMBERS
To exit menu enter -1!

Please enter your choice: 1

Result: 5 + 7 = 12


Choose number of the operation you want to do
1. addition
2. subtraction
3. multiplication
4. division
5. modulo
6. CHANGE OF NUMBERS
To exit menu enter -1!

Please enter your choice: 2

Result: 5 - 7 = -2


Choose number of the operation you want to do
1. addition
2. subtraction
3. multiplication
4. division
5. modulo
6. CHANGE OF NUMBERS
To exit menu enter -1!

Please enter your choice: 3

Result: 5 * 7 = 35


Choose number of the operation you want to do
1. addition
2. subtraction
3. multiplication
4. division
5. modulo
6. CHANGE OF NUMBERS
To exit menu enter -1!

Please enter your choice: 4

Result: 5 / 7 = 0


Choose number of the operation you want to do
1. addition
2. subtraction
3. multiplication
4. division
5. modulo
6. CHANGE OF NUMBERS
To exit menu enter -1!

Please enter your choice: 5

Result: 5 % 7 = 5


Choose number of the operation you want to do
1. addition
2. subtraction
3. multiplication
4. division
5. modulo
6. CHANGE OF NUMBERS
To exit menu enter -1!

Please enter your choice: -1

Addition was selected 2 times
Subtraction was selected 2 times
Multiplication was selected 2 times
Division was selected 2 times
Modulo was selected 2 times

由于使用函数get_int_from_user,该程序还具有广泛的输入验证:

This program has been made for arithmetic operations.
Please choose two integers for arithmetic operations.
Please enter the first number: abc
Unable to convert input to number, try again!
Please enter the first number: 4abc
Invalid character found, try again!
Please enter the first number: 4
Please enter the second number: 

这是已公布的函数 menu 的替代版本,其中两个 goto 标签都被删除并替换为一个循环和一个附加函数:

void input_two_numbers( int &i1, int &i2 )
{
    i1 = get_int_from_user( "Please enter the first number: " );
    i2 = get_int_from_user( "Please enter the second number: " );
}

void menu()
{
    int num1, num2;
    int choice;
    int ch1 = 0, ch2 = 0, ch3 = 0, ch4 = 0, ch5 = 0;

    //intro
    std::cout << "This program has been made for arithmetic operations.\n";

    std::cout << "Please choose two integers for arithmetic operations.\n";

    input_two_numbers( num1, num2 );

    for (;;) //infinite loop
    {
        std::cout <<
            "\n"
            "Choose number of the operation you want to do\n"
            "1. addition\n"
            "2. subtraction\n"
            "3. multiplication\n"
            "4. division\n"
            "5. modulo\n"
            "6. CHANGE OF NUMBERS\n"
            "To exit menu enter -1!\n"
            "\n";

        choice = get_int_from_user( "Please enter your choice: " );

        switch ( choice )
        {
            case 1:
                std::cout << "\nResult: " <<num1  << " + " << num2 << " = " << num1 + num2 << "\n\n";
                ch1++;
                continue;

            case 2:
                std::cout << "\nResult: " <<num1  << " - " << num2 << " = "<< num1 - num2 << "\n\n";
                ch2++;
                continue;

            case 3: 
                std::cout << "\nResult: " <<num1  << " * " << num2 << " = "<<num1 * num2 << "\n\n";
                ch3++;
                continue;

            case 4:
                std::cout << "\nResult: " <<num1  << " / " << num2 << " = "<<num1 / num2 << "\n\n";
                ch4++;
                continue;

            case 5:
                std::cout << "\nResult: " <<num1  << " % " << num2 << " = "<<num1 % num2 << "\n\n";
                ch5++;
                continue;

            case 6:
                std::cout << "Okay, you can choose different numbers.\n" << '\n';
                input_two_numbers( num1, num2 );
                continue;

            case -1:
                break;

            default:
                std::cout << "Please choose valid option out of menu (1-5)\n";
                continue;
        }

        //break out of infinite loop
        break;
    }

    std::cout <<
         "\n" <<
         "Addition was selected " << ch1 << " times\n" <<
         "Subtraction was selected " << ch2 << " times\n" <<
         "Multiplication was selected " << ch3 << " times\n" <<
         "Division was selected " << ch4 << " times\n" <<
         "Modulo was selected " << ch5 << " times\n";
}

就个人而言,我更喜欢使用三个 goto 标签的版本。在我看来,必须创建一个额外的函数并且还必须复制对该函数的调用使得代码比简单地使用 goto 更难理解。但我相信很多其他程序员会不同意我的看法,因为使用 goto 是很有争议的。