2015-02-11 92 views
0

我從C++ Primer Plus書中學習,最近我從書中完成了這個練習。我遇到了一個問題:當用戶輸入沒有任何符號時,然後在下一個條目中顯示任何這些功能,他必須再次輸入,因爲如果不是,它仍然會顯示「錯誤的選擇」和「下一個選擇:」每時每刻。你能告訴我這段代碼有什麼問題嗎?我應該添加什麼? 在此先感謝。C++ Primer Plus第6章練習2輸入理解

 /*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 choice\n"; 
      } 

      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 Report\n" 
     "a. display by name   b. display by title\n" 
     "c. display by bopname  d. display by preference\n" 
     "q. quit\n" 
     "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; 
     } 
    } 

回答

0

我認爲問題就出在這裏:

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

如果確實有性格,第一get將乾淨的換行,第二個將執行另一讀。

如果沒有字符開頭,那麼第一個get將消耗實際輸入,並且ch以換行符結束。


解決方案是:如果您不確定輸入是否有效,請不要將輸入視爲有效。特別是,您期待輸入兩個字符:除換行符之外的任何字符,後跟換行符。

有兩種比較簡單的方法來解決你的問題:

  • 不要使用字符:只需std::string工作和對待空字符串爲無效。
  • 檢查第一個字符是否是換行符,並且不要然後跳過一個附加字符。

更先進的解決方案將是與功能實驗更多。你可以包裝輸入返回optional<char>?或者更好,optional<Choice>,其中Choiceenum class

或者你也許可以創建一個自動循環的函數,每次提示輸入正確的輸入,並將它與主程序邏輯分開?

+0

我acutally不明白std :: string方法,因爲如果我使用std :: string,那麼我不能在交換機中使用它。 – 2015-02-11 10:56:22

+0

@JerzyTuszyński不幸的是C++不允許這樣做,但是'if .. else if ...'鏈是(在這種情況下)等價於此。你可以存儲一個'(字符串,一個要運行的函數)'對的映射。或者做下面的建議** ildjarn **。 – 2015-02-11 10:57:34

+0

@JerzyTuszyński:或者,您可以驗證它的長度爲1,然後使用'str [0]'作爲'switch'。 – ildjarn 2015-02-11 10:57:35