Является ли cin правильной функцией для использования в этом сценарии?

Вот небольшой фрагмент моего кода:

int read_prompt() {
string prompt,fname,lname,input;
int id;
cout << "customers> ";

cin >> prompt;

if (prompt.compare("add") == 0) {
    cin >> id;
    cin >> fname;
    cin >> lname;
    NewCustomer(id,fname,lname);
} else if (prompt.compare("print")==0) {
    print_array();
} else if (prompt.compare("remove")==0) {
    cin >> id;
    RemoveCustomer(id);
} else if (prompt.compare("quit")==0) {
    return 0;
} else {
    cout << "Error!" << endl;
}
read_prompt();
return 0;

}

Это работает нормально, пока пользователь не вводит ничего неожиданного. В одном из тестовых случаев эта программа должна передать входные данные «добавить Даффи Дака со скоростью 125 миль в час», где id будет равен 125, fname равно mph, а lname равно Daffy. После того, как эта функция получает все три переменные, она снова вызывает себя и повторно запрашивает пользователя, который затем вводит Duck, какая «Ошибка!» получает вывод, очевидно.

Как мне поймать эту ошибку, когда пользователь вводит ее? Является ли cin лучшей функцией для использования в этом отношении? Я искал getline(), но я немного не уверен, как это реализовать.


person dmarzio    schedule 15.02.2013    source источник
comment
Почему бы не создать управляемую с помощью меню программу, которая позволяет пользователю выбирать нужную функцию путем ввода одного числа, а затем использовать switch. Вы избежите многих ошибок и кода проверки.   -  person ChiefTwoPencils    schedule 16.02.2013
comment
cin не является функцией; это объект. Таким образом, у него есть функции-члены, и есть бесплатные функции, которые могут его использовать. Многие из них являются экстракторами, то есть перегрузками operator>>.   -  person Pete Becker    schedule 16.02.2013


Ответы (1)


Если бы это был я,

  • Я бы прочитал всю строку сразу и разбил бы ее на токены, разделенные пробелами, используя std::istringstream.
  • Я бы избежал отвода любой ценой.
  • Я мог бы добавить более строгую проверку ошибок.

Так:

#include <vector>
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <sstream>
#include <stdexcept>

typedef std::vector<std::string> Args;

std::istream& operator>>(std::istream& is, Args& args) {
    std::string s;
    if(std::getline(is, s)) {
        std::istringstream iss(s);
        args.clear();
        while( iss >> s )
            args.push_back(s);
    }
    return is;
}

void NewCustomer(int, std::string, std::string) {
    std::cout << __func__ << "\n";
}
void RemoveCustomer(int) {
    std::cout << __func__ << "\n";
}
void print_array() {
    std::cout << __func__ << "\n";
}
int read_prompt() {
    Args args;
    while(std::cout << "customers> " && std::cin >> args) {
        try {
            if(args.at(0) == "add") {
                NewCustomer(
                    boost::lexical_cast<int>(args.at(1)),
                    args.at(2),
                    args.at(3));
            } else if (args.at(0) == "print") {
                print_array();
            } else if (args.at(0) == "remove") {
                RemoveCustomer(boost::lexical_cast<int>(args.at(1)));
            } else if (args.at(0) == "quit") {
                return 0;
            } else {
                throw 1;
            }
        } catch(boost::bad_lexical_cast&) {
            std::cout << "Error!\n";
        } catch(std::out_of_range&) {
            std::cout << "Error!\n";
        } catch(int) {
            std::cout << "Error!\n";
        }
    }
}

int main () {
    read_prompt();
}
person Robᵩ    schedule 15.02.2013