我有一个程序从用户接收命令,它将以不同的方式处理不同的命令.例如:
ADD_STUDENT ALEX 5.11 175
ADD_TEACHER MERY 5.4 120 70000
PRINT MERY
REMOVE ALEX
PRINT TEACHER SALARY
PRINTALL
Run Code Online (Sandbox Code Playgroud)
因此,我需要检查每一行,看看输入是由什么组成的.
这是我的代码,但我想我误解了"工作方式".有人可以给我一个建议吗?并告诉我为什么我的代码不能像我预期的那样工作?
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...
}
Run Code Online (Sandbox Code Playgroud)
我的想法是,如果所有参数都被填充,则iss >> first >> second >> third将返回true,如果参数不足则返回false.但显然我错了.
seh*_*ehe 10
你的问题很糟糕.这总是促使我使用Boost Spirit提供夸大的示例实现.
注意:请不要把它作为你的家庭作业.
通过以下示例输入查看Live on Coliru:
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
Run Code Online (Sandbox Code Playgroud)
完整代码:
更新当包含make_visitor.hpp如此处所示时,您可以更优雅地编写访问者代码:
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);
};
Run Code Online (Sandbox Code Playgroud)
请参阅改编的示例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";
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
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
Run Code Online (Sandbox Code Playgroud)
这样做:
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 ...
Run Code Online (Sandbox Code Playgroud)
您的问题是使用>>运算符从流中读取并清除令牌.
if(iss >> command >> name >> height >> weight)
Run Code Online (Sandbox Code Playgroud)
这(上图)尝试从流中读取4个令牌,并且对于每次成功读取,它都会清除流中的读取数据.
else if(iss >> command >> name >> height >> weight >> salary)
Run Code Online (Sandbox Code Playgroud)
当你到达这个(上面)时,这意味着无法读取某些令牌并将其转换为适当的类型,但是可能至少已经从流中剥离了命令令牌.
| 归档时间: |
|
| 查看次数: |
474 次 |
| 最近记录: |