简体   繁体   中英

How to limit user input in C++ for strings & characters?

I'm trying to create a small restaurant program in which I'll be practicing everything I learned in C++ so far. However I jumped into a small issue. At the beginning of the program, I prompt the user whether they want to enter the program, or leave it by choosing Y or N. If the input is anything other than that the program will tell the user is invalid.

The issue is lets say the user input one invalid character a. The invalid output will be displayed normally and everything seems perfect. But if the user inputs two characters, or more, the invalid output case will be printed as many as the characters input by the user. Sample below:

Output image

#include <iostream>

int main()
{
    char ContinueAnswer;
    std::string Employee {"Lara"};
    std::cout << "\n\t\t\t---------------------------------------"
              << "\n\t\t\t|                                     |"    
              << "\n\t\t\t|            Welcome to OP            |"
              << "\n\t\t\t|Home to the best fast food in Orlando|"
              << "\n\t\t\t|                                     |"
              << "\n\t\t\t--------------------------------------|" << std::endl;

do
{
    std::cout << "\n\t\t\t    Would you like to enter? (Y/N)"
              << "\n\t\t\t                  "; std::cin >> ContinueAnswer;
    if(ContinueAnswer == 'y' || ContinueAnswer == 'Y')
    {
        system("cls");
        std::cout << "\n\t\t\t              My name is " << Employee << "."
                  << "\n\t\t\tI will assist you as we go through the menu." << std::endl;
    }
    else if(ContinueAnswer == 'n' || ContinueAnswer == 'N')
    {
        std::cout << "\t\t\t\tGoodbye and come again!" << std::endl;
        return 0;
    }
    else
        std::cout << "\n\t\t\t\t  Invalid Response" << std::endl;
}
while(ContinueAnswer != 'y' && ContinueAnswer != 'Y')

Thank you for taking time to read and for anyone who answers:)

You could simply make the user input a string :

std::string ContinueAnswer;

and compare like this:

if(ContinueAnswer == "y" || ContinueAnswer == "Y")

which will handle multi-character inputs.

If you want to handle spaces in the input as well, change the:

std::cin >> ContinueAnswer;

to:

std::getline(std::cin, ContinueAnswer);

Before addressing your question I need to point out that you should always verify that the input was successful before doing anything with it. Processing variables which were not set due to the inout failing is a rather common source of errors. For example:

if (std::cin >> ContinueAnswer) {
    // do something with successfully read data
}
else {
    // deal with the input failing, e.g., bail out
}

I assume you consider everything on the same line to be invalid if nine of the expected characters was read. You could read a line into an std::string . However, that could be abused to provide an extremely long line of input which would eventually crash your program. Also, reading data into a std::string just to throw it away seems ill-advised. I'd recommend ignoring all characters up to and including a newline which could be done using (you need to include <limits> for this approach):

std::cin.ignore(std::numeric_limits<std::streamsize>::max(), ‘\n’);

The first argument is a special value indicating that there may be an arbitrary amount of character before the newline. In practice you could probably use a value like 1000 and it would be fine but it can be gamed. Of course, in a real application a dedicated limit may be used to prevent an adversary to keep the program busy for long. I tend to assume my programs are under attack to make sure I deal with unusual cases.

A quick refactor produces this:

#include <iostream>
#include <cstring>
#include <stdio.h>

int main()
{
        char ContinueAnswer[256];
        std::string Employee {"Lara"};
        std::cout << "\n\t\t\t---------------------------------------"
              << "\n\t\t\t|                                     |"
              << "\n\t\t\t|            Welcome to OP            |"
              << "\n\t\t\t|Home to the best fast food in Orlando|"
              << "\n\t\t\t|                                     |"
              << "\n\t\t\t--------------------------------------|" << std::endl;

        do
        {
            std::cout << "\n\t\t\t    Would you like to enter? (Y/N)"
                      << "\n\t\t\t                  "; std::cin.getline(ContinueAnswer,sizeof(ContinueAnswer));
            if(strcmp(ContinueAnswer, "Y") == 0 || strcmp(ContinueAnswer, "y") == 0)
            {
                system("cls");
                std::cout << "\n\t\t\t              My name is " << Employee << "."
                          << "\n\t\t\tI will assist you as we go through the menu." << std::endl;
            }
            else if(strcmp(ContinueAnswer, "N") == 0 || strcmp(ContinueAnswer, "n") == 0)
            {
                std::cout << "\t\t\t\tGoodbye and come again!" << std::endl;
                return 0;
            }
            else
                std::cout << "\n\t\t\t\t  Invalid Response" << std::endl; 
        }       
        while(true);
}

The cin.getline will get all characters until a delimiter. Then, you can check for equivalence using strcmp and reject anything other than what you want. Lastly, it seems like you are wanting this to be in an infinite loop, so don't worry about checking the input at the end and just loop back.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM