Дали 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;

}

Това работи добре, стига потребителят да не въвежда нищо неочаквано. Един от тестовите случаи, тази програма трябва да предаде входове "добавете 125mph Daffy Duck", чийто 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