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') ;        
}

在第二次输入之后,这变成了无限循环(尽管即使在第二次输入之后也应该清除流,对吗?),另外,例如,如果我输入“帮助”两次,第一个有效,但第二个无效吨

我能做些什么来尽可能多地正确获取用户输入?

编辑:当用户输入命令之一时(如果其他...),将创建一个对象并运行构造函数。在“帮助”的情况下,构造函数会显示带有解释的命令列表。在我的情况下,这只适用于一次。当我输入“帮助”时,构造函数可以工作,但是当我再次输入“帮助”时,它会显示无限多的“错误命令”(我的 if else 中的其他条件)。那是因为我猜是流,但我认为 cin.ignore(...) 应该清除并且代码应该可以工作。希望这个解释就足够了:)

提前致谢:)

4

1 回答 1

3

我注意到b没有在循环中定义。除非它是全局的并且所有命令类都将它重置,否则它永远不会被设置回 0...这意味着 first"Help"将永远是"Help". 更糟糕的是,最终你会写过去你的数组。

由于b几乎完全是cmd单词的索引和计数,因此它可能应该在相同的范围内定义。这两个问题都可以通过b = 0;在填充循环之前添加来解决cmd。(但是,如果您不在b循环之外使用,那么您真的应该在内部定义它。)

但实际上,您最好使用std::getline一次将整行读取为 a std::string,然后使用istringstream' 提取运算符(而不是get())将单个单词提取到向量中。(char input[MAX];这就是你在 C 中所做的。C++ 内置了可动态调整大小的容器,因此数组中没有太多意义。它总是太大或太小。)

手表:

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 回答