如何在 do/while 循环中验证不同变量类型的多个输入?

问题描述 投票:0回答:1

一切都很好,但有一个主要问题。当验证用户输入以检查用户是否输入了正确的值(即字符串的字符,整数的数字)时,代码只能检测用户何时错误地输入了字符串,而不能检测到整数。这意味着只要用户输入年龄整数,代码就不会验证输入。

这是我的代码。

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

string firstName, secondName, homeTown;
int age;

int main() {
    do {
        cout << "Please enter your full name, hometown and age (e.g. John Doe London 25).\n\n";
        cin >> firstName >> secondName >> homeTown >> age;
        if (cin.fail()) {
            cout << "\nInvalid input!\n\n";
            cin.clear();
            cin.ignore();
        }
        else {
            break;
        }
    } while (1);
    cout << "\nYour Name is: " << firstName << " " << secondName << "\n" << "Your Hometown is: " << homeTown << "\n" << "Your Age is: " << age << "\n";
    return 0;
}

以下是当所有内容输入正确时它如何输出的示例:

Please enter your full name, hometown and age (e.g. John Doe London 25).

John Doe London 25

Your Name is: John Doe
Your Hometown is: London
Your Age is: 25

这里是当只有整数输入错误时如何输出的示例:

Please enter your full name, hometown and age (e.g. John Doe London 25).

1 1 1 a

Invalid input!

Please enter your full name, hometown and age (e.g. John Doe London 25).

这里是主要问题,只要正确输入整数,无论字符串如何输入,我得到的输出都是:

Please enter your full name, hometown and age (e.g. John Doe London 25).

1 1 1 1

Your Name is: 1 1
Your Hometown is: 1
Your Age is: 1

总而言之,我到底如何使用 if 语句验证整数和多个字符串?

c++ validation input user-input
1个回答
0
投票

我到底如何使用 if 语句验证整数和多个字符串?

当您需要验证用户所做的输入时,通常最好一次输入一个。这样,您可以在输入时检查每一项,并在其中一项无效时要求用户重试。

我通常为我希望用户输入的每个输入调用专用函数。例如,函数

get_int
显示提示,并不断循环,直到用户输入有效数字。条目必须位于
min
max
之间,否则用户必须重试!

int get_int(
    std::string const& prompt,
    int const min,
    int const max)
{
    for (;;) {
        std::cout << prompt;
        if (int n{}; !(std::cin >> n)) {
            std::cout << "Invalid entry. Please reenter.\n\n";
            std::cin.clear();
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        }
        else if (n < min || n > max) {
            std::cout << "Invalid entry. Please reenter.\n"
                << "Entries must be between " << min << " and " << max << ".\n\n";
        }
        else {
            // The call to `ignore` ensures that this function "plays nice" 
            // with `std::getline`.
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
            return n;
        }
    }
}

这是一个非常相似的输入字符串的函数。它使用

std::getline
,允许字符串条目包含空格。这样,您就不必分别输入名字和姓氏(除非您愿意)。条目不得为空。

std::string get_non_empty_string(std::string const& prompt)
{
    for (;;) {
        std::cout << prompt;
        if (std::string s{}; !(std::getline(std::cin, s))) {
            throw std::runtime_error{ "get_non_empty_string: `std::getline` failed" };
        }
        else if (s.empty()) {
            std::cout << "Invalid entry. Please reenter.\n"
                << "Entries cannot be blank.\n\n";
        }
        else {
            return s;
        }
    }
}

完整的程序

使用上面的两个函数可以让你简化函数

main
。请注意,我已经省略了
using namespace std;
。大多数专业人士都远离它。我还消除了全局变量。它们在像这个这样的小程序中可能没问题,但在较大的程序中可能会很糟糕,因为错误可能很难追踪。

// main.cpp
#include <iostream>
#include <limits>
#include <stdexcept>
#include <string>

//==================================================================
// get_int
//==================================================================
int get_int(
    std::string const& prompt,
    int const min,
    int const max)
{
    for (;;) {
        std::cout << prompt;
        if (int n{}; !(std::cin >> n)) {
            std::cout << "Invalid entry. Please reenter.\n\n";
            std::cin.clear();
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        }
        else if (n < min || n > max) {
            std::cout << "Invalid entry. Please reenter.\n"
                << "Entries must be between " << min << " and " << max << ".\n\n";
        }
        else {
            // The call to `ignore` ensures that this function "plays nice" 
            // with `std::getline`.
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
            return n;
        }
    }
}
//==================================================================
// get_non_empty_string
//==================================================================
std::string get_non_empty_string(std::string const& prompt)
{
    for (;;) {
        std::cout << prompt;
        if (std::string s{}; !(std::getline(std::cin, s))) {
            throw std::runtime_error{ "get_non_empty_string: `std::getline` failed" };
        }
        else if (s.empty()) {
            std::cout << "Invalid entry. Please reenter.\n"
                << "Entries cannot be blank.\n\n";
        }
        else {
            return s;
        }
    }
}
//==================================================================
// main
//==================================================================
int main() {
    std::cout << "Please tell us about yourself.\n\n";
    std::string full_name = get_non_empty_string("Full name: ");
    std::string hometown = get_non_empty_string("Hometown: ");
    int age = get_int("Age: ", 0, 125);
    std::cout 
        << "\nYour Name is: " << full_name<< "\n" 
        << "Your Hometown is: " << hometown << "\n" 
        << "Your Age is: " << age << "\n";
    return 0;
}
// end file: main.cpp

样本输出

第一次运行时没有出现错误。

Please tell us about yourself.

Full name: Joe Dokes
Hometown: London
Age: 25

Your Name is: Joe Dokes
Your Hometown is: London
Your Age is: 25

第二次,错误比比皆是。此运行显示输入全名而不是单独的名字和姓氏的问题。无法检测到姓氏是否被省略。

Please tell us about yourself.

Full name:
Invalid entry. Please reenter.
Entries cannot be blank.

Full name: Joe
Hometown:
Invalid entry. Please reenter.
Entries cannot be blank.

Hometown: London, England
Age: 1000
Invalid entry. Please reenter.
Entries must be between 0 and 125.

Age: 25

Your Name is: Joe
Your Hometown is: London, England
Your Age is: 25
© www.soinside.com 2019 - 2024. All rights reserved.