首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在c++中以不同方式处理多个输入命令的正确方法是什么?

在c++中以不同方式处理多个输入命令的正确方法是什么?
EN

Stack Overflow用户
提问于 2013-07-21 09:06:48
回答 5查看 638关注 0票数 6

我有一个程序,接受来自用户的命令,它将处理不同的命令不同。例如:

代码语言:javascript
复制
ADD_STUDENT ALEX 5.11 175
ADD_TEACHER MERY 5.4  120 70000
PRINT MERY 
REMOVE ALEX
PRINT TEACHER SALARY
PRINTALL 

因此,我需要检查每一行,看看输入是由什么组成的。

以下是我的代码,但我想我误解了iss<<的工作方式。有人能给我一个建议吗?告诉我为什么我的代码不能像我预期的那样工作?

代码语言:javascript
复制
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...
}

我的想法是,如果所有参数都已填充,iss>> first >>second >> third将返回true,如果参数不足,则返回false。但显然我错了。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2013-07-21 09:15:38

如下所示:

代码语言:javascript
复制
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 ...
票数 7
EN

Stack Overflow用户

发布于 2013-07-22 04:32:26

你的问题被巧妙地低估了。这总是促使我使用Boost Spirit提供一个夸张的示例实现。

备注:请不要把这个作为你的家庭作业交上去。

使用以下示例输入查看:

代码语言:javascript
复制
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

完整代码:

更新当包含如图所示的make_visitor.hpp时,您可以更优雅地编写访问者代码:

代码语言:javascript
复制
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);
};

请参阅改编的示例

代码语言:javascript
复制
#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";
    }
}

输出:

代码语言:javascript
复制
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
票数 10
EN

Stack Overflow用户

发布于 2013-07-21 09:27:28

您的问题是使用>>操作符从流中读取和清除令牌。

代码语言:javascript
复制
if(iss >> command >> name >> height >> weight)

这个(上图)尝试从流中读取4个令牌,每次成功读取时,它都会从流中清除读取的数据。

代码语言:javascript
复制
else if(iss >> command >> name >> height >> weight >> salary)

当你达到这一点(上面)时,这意味着一些令牌无法被读取并转换为适当的类型,但是很可能至少命令令牌已经从流中剥离。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17768152

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档