如何阅读可能以字符串或数字开头的行
How do I read in lines that may begin with string or number?
我必须从以下格式的文件中读取输入:
12 + 56
9 divided by -3
45 minus 15
Min of 2 and 1
Max of 3 and 5
34 plus 33
我必须以这种格式输出到另一个文件:
12 + 56 is 68
9 divided by -3 is -3
45 minus 15 is 30
Min of 2 and 1 is 1
Max of 3 and 5 is 5
34 plus 33 is 67
我曾用这种方式接近它,但在某一点上被卡住了。我把每一行都读入一个字符串,但我如何访问字符串中的操作数,因为它们在不同的字符串中处于不同的位置?
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
using namespace std;
int compute(string s) {
//Not sure how to do this
return 0;
}
int main() {
ifstream in;
ofstream out;
string s1 = "Input.txt";
string s2 = "CalculationResults.txt";
string s;
int operand1, operand2, result;
in.open(s1);
out.open(s2);
if (in) {
while (getline(in, s)) {
result = compute(s);
out << s << " is " << result << endl;
}
in.close();
out.close();
} else {
cout << "nCouldn't find the input filenn";
}
system("pause");
return 0;
}
我认为最简单的方法是读取一个字符串,直到第一个空格,将其与您的命令进行比较,如果它不匹配,则将其转换为数字:
if (in1 >> firstthing) {
out << firstthing << " ";
if (firstthing == "Min") {
result = compute_min(in1, out); //reads in " of " and then the numbers. Also writes.
} else if (firstthing == "Max") {
result = compute_max(in1, out); //reads in " of " and then the numbers. Also writes.
} else {
int first_operand = atoi(firstthing.c_str());
//reads in an operator, then the second operand. Also writes.
result = compute_expression(in1, out, first_operand);
}
out << " is " << result << endl;
}
各种功能体相对简单:
int compute_min(std::istream& in1, std::ofstream& out) {
std::string ofstring;
int first_operand;
std::string andstring;
int second_operand;
in1 >> ofstring >> first_operand >> andstring >> second_operand;
out << ofstring << first_operand << andstring << second_operand;
return std::min(first_operand, second_operand);
}
int compute_expression(std::istream& in1, std::ofstream& out, int first_operand) {
std::string operation;
int second_operand;
in1 >> operation >> second_operand;
out << operation << second_operand;
if (operation=="+" || operation=="plus")
return first_operand + second_operand;
else if
//more
else
throw std::runtime_error("Invalid operation "+operation);
}
我受邀采用了不可避免的Boost Spirit方法。
这是中心部分:
auto value_ = qi::create_parser<V>();
start = eval;
eval = no_case [
as_string [ raw [ value_[_a=_1] >> ('+' | lit("plus")) >> value_[_b=_1] ] ] [ std::cout << _1 << " is " << (_a+_b) << "n" ]
| as_string [ raw [ value_[_a=_1] >> ('-' | lit("minus")) >> value_[_b=_1] ] ] [ std::cout << _1 << " is " << (_a-_b) << "n" ]
| as_string [ raw [ value_[_a=_1] >> ('/' | lit("divided") >> "by") >> value_[_b=_1] ] ] [ std::cout << _1 << " is " << (_a/_b) << "n"]
| as_string [ raw [ value_[_a=_1] >> ('*' | lit("multiplied") >> "by") >> value_[_b=_1] ] ] [ std::cout << _1 << " is " << (_a*_b) << "n" ]
| as_string [ raw [ lit("min") >> "of" >> value_[_a=_1] >> "and" >> value_[_b=_1] ] ] [ std::cout << _1 << " is " << min_(_a,_b) << "n" ]
| as_string [ raw [ lit("max") >> "of" >> value_[_a=_1] >> "and" >> value_[_b=_1] ] ] [ std::cout << _1 << " is " << max_(_a,_b) << "n" ]
]
;
请注意,语法对于值类型是通用的,这意味着您可以使用double
,如果您愿意,甚至可以使用cpp_dec_float
。即使是std::complex<T>
也可能起作用。
源迭代器也是如此。以下是显示如何将其与直接std::cin
流迭代器一起使用的驱动程序:
在Coliru上直播
int main() {
using It = boost::spirit::istream_iterator;
It f(std::cin >> std::noskipws), l;
bool ok = qi::phrase_parse(f, l, verbiage<It>() % qi::eol, qi::blank);
std::cout << "Success: " << std::boolalpha << ok << "; Remaining: '" << std::string(f,l) << "'n";
}
打印
12 + 56 is 68
9 divided by -3 is -3
45 minus 15 is 30
Min of 2 and 1 is 1
Max of 3 and 5 is 5
34 plus 33 is 67
Success: true; Remaining: '
'
完整演示
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/phoenix/phoenix.hpp>
namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;
template <typename It, typename V = long, typename Skipper = qi::blank_type>
struct verbiage : qi::grammar<It, Skipper> {
verbiage() : verbiage::base_type(start) {
using namespace qi;
auto value_ = qi::create_parser<V>();
start = eval;
eval = no_case [
as_string [ raw [ value_[_a=_1] >> ('+' | lit("plus")) >> value_[_b=_1] ] ] [ std::cout << _1 << " is " << (_a+_b) << "n" ]
| as_string [ raw [ value_[_a=_1] >> ('-' | lit("minus")) >> value_[_b=_1] ] ] [ std::cout << _1 << " is " << (_a-_b) << "n" ]
| as_string [ raw [ value_[_a=_1] >> ('/' | lit("divided") >> "by") >> value_[_b=_1] ] ] [ std::cout << _1 << " is " << (_a/_b) << "n"]
| as_string [ raw [ value_[_a=_1] >> ('*' | lit("multiplied") >> "by") >> value_[_b=_1] ] ] [ std::cout << _1 << " is " << (_a*_b) << "n" ]
| as_string [ raw [ lit("min") >> "of" >> value_[_a=_1] >> "and" >> value_[_b=_1] ] ] [ std::cout << _1 << " is " << min_(_a,_b) << "n" ]
| as_string [ raw [ lit("max") >> "of" >> value_[_a=_1] >> "and" >> value_[_b=_1] ] ] [ std::cout << _1 << " is " << max_(_a,_b) << "n" ]
]
;
}
private:
struct min_f {
using result_type = V;
template <typename A, typename B> V operator()(A a, B b) const { return std::min(a,b); }
};
struct max_f {
using result_type = V;
template <typename A, typename B> V operator()(A a, B b) const { return std::max(a,b); }
};
phx::function<min_f> min_;
phx::function<max_f> max_;
qi::rule<It, Skipper, qi::locals<V,V> > eval;
qi::rule<It, Skipper> start;
};
int main() {
using It = boost::spirit::istream_iterator;
It f(std::cin >> std::noskipws), l;
bool ok = qi::phrase_parse(f, l, verbiage<It>() % qi::eol, qi::blank);
std::cout << "Success: " << std::boolalpha << ok << "; Remaining: '" << std::string(f,l) << "'n";
}
您要查找的似乎是类似std::strtok
的内容。在您的行中读取后,可以使用std::strtok将其解析为字符串向量。这里有一个链接,指向描述该功能的页面,并附有一个使用示例。一旦您有了一个令牌向量,您就可以循环遍历它们,并分别检查每个单独的元素。
相关文章:
- 比较并显示使用最小值(a,b)和最大值(a、b)升序排列的4个数字
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- 检查输入是否不是整数或数字
- 如何(从固定列表中)选择一个数字序列,该序列将与目标数字相加
- 如何用数字处理log(0)
- 最高有效数字侧的第N位
- 如何获取一个数字的前3位
- 查找最接近的大于当前数字的数字的索引
- 找到两对数字,使它们的乘积的绝对差最小化
- 我想做一个彼此不同但重复出现的数字
- 将数字转换为字母(例如:123 转换为一二三)
- C++如何计算用户输入的数字中的偶数位数
- 开头C++:使用 if else,n--, 数字
- 是否可以在 c++ 中创建以数字开头的类名
- C++从文件中读取不同类型的数据,直到有一个以数字开头的字符串
- C++ 在数字开头添加小数点的任意方法
- 在以 8 开头的任何数字之前选择 "a" 或 "an"
- 如何阅读可能以字符串或数字开头的行
- 测试字符串是否以数字开头
- 如何在 ofn.lpstrFilter 中用数字开始文件格式名称?它不允许在开头写 3?