Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

what is the correct way to handle multiple input command differently in c++?

Tags:

c++

I have a program that take commands from user and it will process different commands differently. For example:

ADD_STUDENT ALEX 5.11 175
ADD_TEACHER MERY 5.4  120 70000
PRINT MERY 
REMOVE ALEX
PRINT TEACHER SALARY
PRINTALL 

therefore, I need to examine each line and see what is the input consists of.

Here is my code, but I think I misunderstand the way iss<< work. Can someone give me a suggestion? And tell me how why my code didn't work as I expected?

string line;
while(getline(cin, line))
{
  //some initialization of string, float variable
  std::istringstream iss(line);
  if(iss >> command >> name >> height >> weight)
   ..examine the command is correct(ADD_STUDENT) and then do something..
  else if(iss >> command >> name >> height >> weight >> salary)
   ..examine the command is correct(ADD_TEACHER) and then do something...
  else if(iss >> command >> name)
   ..examine the command is correct(REMOVE) and then do somethin...
}

My thought is that the iss>> first >>second >> third will return true if all arguments are filled and false if not enough arguments. But apparently I am wrong.

like image 549
user1701840 Avatar asked Jul 21 '13 01:07

user1701840


People also ask

How can the input command be used to accept multiple variables?

Answer: In C++/C user can take multiple inputs in one line using scanf but in Python user can take multiple values or inputs in one line by two methods.

How do you take multiple integer inputs in one line in Python?

Using split() method : This function helps in getting a multiple inputs from user. It breaks the given input by the specified separator. If a separator is not provided then any white space is a separator. Generally, user use a split() method to split a Python string but one can use it in taking multiple input.

How do you add multiple inputs to a list in Python?

Using split() method This function helps in getting multiple inputs from users. It breaks the given input by the specified separator. If a separator is not provided then any white space is a separator. Generally, users use a split() method to split a Python string but one can use it for taking multiple inputs.


2 Answers

Your problem was deliciously underspecified. This always prompts me to supply an overblown example implementation using Boost Spirit.

Note: just don't hand this in as your homework assignment, please.

See it Live on Coliru with the following sample input:

ADD_STUDENT ALEX 5.11 175
ADD_STUDENT PUFF 6 7
ADD_STUDENT MAGIC 7 8
ADD_STUDENT DRAGON 8 9
ADD_TEACHER MERY 5.4  120 70000
PRINT MERY 
ADD_TEACHER DUPLO 5.4  120 140000
PRINTALL  10
REMOVE ALEX
PRINT  TEACHER SALARY
PRINT  MERY PUFF MAGIC DRAGON
REMOVE MERY PUFF MAGIC DRAGON
PRINT  TEACHER SALARY

Full code:


Update When including make_visitor.hpp as shown here you can write the visitor code more elegantly:

auto print_salary = [&] () 
{ 
    for(auto& p : names) 
        boost::apply_visitor(make_visitor(
                    [](Teacher const& v) { std::cout << "Teacher salary: " << v.salary << "\n"; },
                    [](Student const& v) {}), 
                p.second);
};

See adapted example Live on Coliru


#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>

namespace qi = boost::spirit::qi;
namespace phx= boost::phoenix;

struct Person
{
    std::string name;
    double height, weight;
    friend std::ostream& operator<<(std::ostream& os, Person const& s) {
        return os << "Person { name:" << s.name << ", height:" << s.height << ", weight:" << s.weight << " }";
    }
};

struct Student : Person
{
    Student() = default;
    Student(std::string n, double h, double w) : Person {n,h,w} {}
};

struct Teacher : Person
{
    Teacher() = default;
    Teacher(std::string n, double h, double w, double s) : Person {n,h,w}, salary(s) {}
    double salary;
};

int main()
{
    std::stringstream ss;
    ss << std::cin.rdbuf();

    std::map<std::string, boost::variant<Student, Teacher> > names;

    using namespace qi;
    auto add_student  = phx::ref(names)[_1] = phx::construct<Student>(_1, _2, _3);
    auto add_teacher  = phx::ref(names)[_1] = phx::construct<Teacher>(_1, _2, _3, _4);
    auto remove       = phx::erase(phx::ref(names), _1);
    auto print_all    = [&] (int i) { for(auto& p : names) { std::cout << p.second << "\n"; if (--i==0) break; } };
    auto print_salary = [&] () 
    { 
        struct _ : boost::static_visitor<> {
            void operator()(Teacher const& v) const { std::cout << "Teacher salary: " << v.salary << "\n"; }
            void operator()(Student const& v) const { }
        } v_;
        for(auto& p : names) boost::apply_visitor(v_, p.second);
    };

    auto name_ = as_string[lexeme[+graph]];

    if (phrase_parse(begin(ss.str()), end(ss.str()), 
                (
                     ("ADD_STUDENT" >> name_ >> double_ >> double_)            [ add_student ]
                   | ("ADD_TEACHER" >> name_ >> double_ >> double_ >> double_) [ add_teacher ]
                   | (eps >> "PRINT" >> "TEACHER" >> "SALARY")                 [ print_salary ]
                   | ("PRINTALL" >> int_)      [ phx::bind(print_all, _1) ]
                   | ("PRINT"  >> +name_       [ std::cout << phx::ref(names)[_1] << std::endl ])
                   | ("REMOVE" >> +name_       [ remove ])
                ) % +eol,
                qi::blank))
    {
        std::cout << "Success";
    }
    else
    {
        std::cout << "Parse failure";
    }
}

Output:

Person { name:MERY, height:5.4, weight:120 }
Person { name:ALEX, height:5.11, weight:175 }
Person { name:DRAGON, height:8, weight:9 }
Person { name:DUPLO, height:5.4, weight:120 }
Person { name:MAGIC, height:7, weight:8 }
Person { name:MERY, height:5.4, weight:120 }
Person { name:PUFF, height:6, weight:7 }
Teacher salary: 140000
Teacher salary: 70000
Person { name:MERY, height:5.4, weight:120 }
Person { name:PUFF, height:6, weight:7 }
Person { name:MAGIC, height:7, weight:8 }
Person { name:DRAGON, height:8, weight:9 }
Teacher salary: 140000
Success
like image 142
sehe Avatar answered Oct 22 '22 00:10

sehe


Do it like so:

iss >> command;
if (!iss)
    cout << "error: can not read command\n";
else if (command == "ADD_STUDENT")  
    iss >> name >> height >> weight;
else if (command == "ADD_TEACHER")  
    iss >> name >> height >> weight >> salary;
else if ...
like image 31
Leonid Volnitsky Avatar answered Oct 21 '22 23:10

Leonid Volnitsky