2013-06-03 4 views
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') ;   
} 

После второго входа, это становится бесконечный цикл (хотя поток должен быть очищен даже после второго ввода, я прав?), также, если я, например, дважды вхожу в «помощь», первый работает, а второй не

Что я могу сделать, чтобы получить пользователя правильно ввести столько раз, сколько пожелаете?

EDIT: Когда пользователь вводит одну из команд (если еще ...), объект создается и запускается конструктор. В случае «help» конструктор отображает список команд с пояснениями. Это работает только один раз в моем случае. Когда я вхожу в «help», конструктор работает, но когда я снова вхожу в «help», он отображает бесконечно много «неправильной команды» (иначе условие в my if else). Это из-за потока, я думаю, но я, хотя cin.ignore (...) должен очистить и код должен работать. Надеюсь, что это объяснение достаточно :)

Заранее спасибо :)

+0

Какое поведение вы хотите? Ваш код не ясен, и ваши объяснения не помогают. Какое поведение вы хотите, точнее, более четко определить «ввод правильно» и «столько раз» ... Просто мысль, «хотя (правда)» без «перерыва» - это почти всегда плохая идея. – ChrisCM

+0

Возможно, вы хотели использовать 'while (issc >> token)'? Это будет читать все строки на входе, разделенные любым пробелом. Я полагаю, что ваша проблема со второй командой заключается в том, что вы нажимаете enter на клавиатуре, но ваш код ожидает найти пространство в качестве разделителя команд. – jcxz

ответ

3

Я заметил, что b не определен внутри цикла. Если это не глобальный, и все классы команд сбросят его, он никогда не будет возвращаться к 0 ... это означает, что первый "Help" всегда будет "Help". Хуже того, в конце концов вы собираетесь писать мимо своего массива.

С b - это почти полностью индекс в cmd и количество слов, вероятно, оно должно быть определено в том же объеме. Обе проблемы могут быть отменены путем добавления b = 0; непосредственно перед циклом, который заполняет cmd. (Если вы не используете b вне цикла, хотя, вы должны действительно быть определяющим его внутри.)

Но на самом деле, вы, вероятно, лучше использовать std::getline читать всю строку сразу, как 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'; 
    } 
} 

Обратите внимание, что для переполнения буфера нет никакого искусственного ограничения на размер строки.

+0

Большое спасибо, это сработало ... Думаю, я снова прочитаю векторный материал, так как это важно в C++, поскольку я вижу его везде ... – khajvah

+0

@khajvah: Да. Векторы очень важны, если вы просто не хотите использовать компилятор C++ для компиляции кода C. :) – cHao

Смежные вопросы