C++初级读本+第6章练习2输入理解

C++ Primer Plus Chapter 6 Exercise 2 Enter understanding

本文关键字:输入 练习 6章 初级读本 C++      更新时间:2023-10-16

我正在学习C++Primer Plus这本书,最近我在书中做了这个练习。我有一个问题:当用户在没有任何符号的情况下点击回车键时,在下一个显示这些功能的条目中,他必须再次点击回车键,因为如果没有,它仍然会一直显示"错误的选择"answers"下一个选择:"。你能告诉我这个代码出了什么问题吗?我应该添加什么?提前谢谢。

        /*When you join the Benevolent Order of Programmers, you can be known at BOP
    meetings by your real name, your job title, or your secret BOP name.Write a program
    that can list members by real name, by job title, by secret name, or by a member’s
    preference. Base the program on the following structure:
    // Benevolent Order of Programmers name structure
    struct bop {
    char fullname[strsize]; // real name
    char title[strsize]; // job title
    char bopname[strsize]; // secret BOP name
    int preference; // 0 = fullname, 1 = title, 2 = bopname
    };
    In the program, create a small array of such structures and initialize it to suitable
    values. Have the program run a loop that lets the user select from different alternatives:
    a. display by name b. display by title
    c. display by bopname d. display by preference
    q. quit
    302 Chapter 6 Branching Statements and Logical Operators
    Note that “display by preference” does not mean display the preference member; it
    means display the member corresponding to the preference number. For instance, if
    preference is 1, choice d would display the programmer’s job title.A sample run
    may look something like the following:
    Benevolent Order of Programmers Report
    a. display by name b. display by title
    c. display by bopname d. display by preference
    q. quit
    Enter your choice: a
    Wimp Macho
    Raki Rhodes
    Celia Laiter
    Hoppy Hipman
    Pat Hand
    Next choice: d
    Wimp Macho
    Junior Programmer
    MIPS
    Analyst Trainee
    LOOPY
    Next choice: q
    Bye!*/

解决方案:

    #include <iostream>
    void text();
    void name();
    void title();
    void secret();
    void prefr();
    const int strSize = 23;
    const int People = 4;
    char ch;
    struct bop {
    char fullname[strSize]; // real name
    char title[strSize];    // job title
    char bopname[strSize];  //secret BOP name
    int preference;         // 0 = fullname, 1 = title, 2 = bopname
    };
    bop people[People]  //array of 4 structures
        {
            {"Tony Hawk", "Junior Programmer", "Novice",2},  //first member
            {"Bill Gates", "Founder of Microsoft", "Billionaire",1},    //second member
            {"Pop Leather", "Graphic Designer", "Fast and Furious",2},  //third member
            {"Steve Jobs", "Apple Leader", "Undead Dragon",0}   //fourth member
        };

    int main()
    {
        text();    //call a text function
        std::cin.get(ch);    //get a character
        int i=0;
        while(ch!='q')
        {
            switch(ch)
            {
                case 'a':
                    name();
                    break;
                case 'b':
                    title();
                    break;
                case 'c':
                    secret();
                    break;
                case 'd':
                    prefr();
                    break;
                default: std::cout << "Wrong choicen";
            }
            std::cout << "Next choice: n";
            std::cin.get();
            std::cin.get(ch);
        }
        std::cout<<"Bye!";
        return 0;
    }
    void text()
    {
        std::cout<<"Benevolent Order of Programmers Reportn"
        "a. display by name         b. display by titlen"
        "c. display by bopname      d. display by preferencen"
        "q. quitn"
        "Enter your choice:";
    }   
    void name()
    {
        for(int i=0;i<People;i++)
        std::cout<<people[i].fullname<<std::endl;
    }
    void title()
    {
        for(int i=0;i<People;i++)
        std::cout<<people[i].title<<std::endl;
    }
    void secret()
    {
        for(int i=0;i<People;i++)
            std::cout<<people[i].bopname<<std::endl;
    }
    void prefr()
    {
        for(int i=0;i<People;i++)
        {
            if(people[i].preference==0)
                std::cout<<people[i].fullname<<std::endl;
            else if(people[i].preference==1)
                std::cout<<people[i].title<<std::endl;
            else if(people[i].preference==2)
                std::cout<<people[i].bopname<<std::endl;
        }
    }

我认为问题出在这里:

std::cin.get();
std::cin.get(ch);

如果确实有一个字符,第一个get将清除换行符,第二个将执行另一次读取。

如果一开始没有字符,那么第一个get将使用实际输入,而ch将作为换行符结束。


解决方法是:如果您不确定输入是否有效,就不要将其视为有效。特别是,您需要输入两个字符:除了换行符后面跟着换行符之外的任何字符。

有两种相当简单的方法可以解决您的问题:

  • 不要使用字符:只需处理std::string并将空字符串视为无效
  • 检查第一个字符是否为换行符,然后不要跳过其他字符

一个更先进的解决方案是对功能进行更多的实验。你能包装输入以返回optional<char>吗?或者更好的是optional<Choice>,其中Choiceenum class

或者,您可以创建一个自动循环的函数,每次都提示正确的输入,并将其与主程序逻辑分离?