0

これはあまりにも有名な質問ですが、答えが見つからないようです

私はこのようなものを持っています:

 while (true) {

        std::cout << "\nCommand> ";
        std::cin.get(input, MAX, '\n');

        std::string cmdtemp = input;

        std::string token;
        std::istringstream issc(cmdtemp);

        std::string cmd[MAX];
        while ( getline(issc, token, ' ') )
        {
            cmd[b] = token;
            b++;
        }


        if (cmd[0] == "help") {
            Help cmd(cmd);
            std::cin.ignore(100, '\n') ;

        }
        else if (cmd[0] == "modify")
            Command* cmd = new Modify;
std::cin.ignore(100, '\n') ;
        else if (cmd[0] == "convert")
            Command* cmd = new Convert;
std::cin.ignore(100, '\n') ;
        else if (cmd[0] == "show")
            Command* cmd = new Show;
std::cin.ignore(100, '\n') ;
        else if (cmd[0] == "getrates") 
            Command* cmd = new Getrates;
std::cin.ignore(100, '\n') ;
        else {
            std::cout << "Wrong command. Type help for Help.";
std::cin.ignore(100, '\n') ;        
}

2回目の入力後、これが無限ループになって(2回目の入力でもストリームはクリアされるはずなのに)、また、例えば「help」を2回入力すると、1回目は効くが2回目は効かない』 t

ユーザー入力を何度でも正しく取得するにはどうすればよいですか?

編集: ユーザーがコマンドの 1 つを入力すると (そうでない場合)、オブジェクトが作成され、コンストラクターが実行されます。「ヘルプ」の場合、コンストラクターは説明付きのコマンドリストを表示します。私の場合、これは一度だけ機能します。「help」と入力すると、コンストラクターは機能しますが、もう一度「help」と入力すると、無限に多くの「間違ったコマンド」(if else の else 条件) が表示されます。それは私が推測するストリームのためですが、私は cin.ignore(...) がクリアされ、コードが機能するはずです。この説明で十分だと思います:)

前もって感謝します:)

4

1 に答える 1

3

bループ内で定義されていないことに気付きました。それがグローバルであり、すべてのコマンド クラスがそれをリセットしない限り、決して 0 に戻されることはありません...つまり、最初"Help"は常に"Help". さらに悪いことに、最終的には配列を超えて書き込むことになります。

bはほぼ完全に単語のインデックスとカウントであるためcmd、おそらく同じスコープで定義する必要があります。b = 0;どちらの問題も、ループがいっぱいになる直前に追加することで、ある程度修正できますcmdb(ただし、ループの外側で使用しない場合は、実際には内側で定義する必要があります。)

std::getlineしかし実際には、行全体を として一度に読み取り、の抽出演算子 ( ではなく) をstd::string使用して個々の単語をベクトルに抽出する方がよいでしょう。(これは C で行うことです。C++ には動的にサイズ変更可能なコンテナーが組み込まれているため、配列にはあまり意味がありません。常に大きすぎたり小さすぎたりします。)istringstreamget()char input[MAX];

時計:

while (true) {
    std::cout << "Command>> " << std::flush;
    std::string line;
    std::getline(std::cin, line);

    std::istringstream tokenizer (line);
    std::vector<std::string> cmd;

    // this basically just does `tokenizer >>` and sticks the string into cmd
    // til the stream runs out.
    typedef std::istream_iterator<std::string> words;
    std::copy(words(tokenizer), words(), std::back_inserter(cmd));

    if (cmd.empty()) continue;

    // do stuff with `cmd`, which is a vector of words.  For example:
    if (cmd[0] == "quit") break;
    for (std::string word : cmd) {
         std::cout << word << '\n';
    }
}

オーバーランするバッファがなく、行サイズに人為的な制限がないことに注意してください。

于 2013-06-03T19:19:01.897 に答える