我有以下line
字符串:
(1,2,3); (3,4,5);(6,7,8); (9,10,11);
我想从第一个元组中提取数字1,2和3;来自第二个的3,4和5,依此类推。
到目前为止我所做的是使用此代码我提取由“;”分隔的字符串:
stringstream ss(line);
string tuple;
vector<string> tuples_vec;
while (getline(ss, tuple, ';'))
tuples_vec.push_back(tuple);
好的,我想我会在tuples_vec
中有以下内容:
(1,2,3)
(3,4,5)
(6,7,8)
(9,10,11)
现在,如何从中提取数字?请注意,可能存在可变数量的空白。
我认为这个部分的想法可能是删除字符直到第一个'('和向后直到第一个')。然后,用“1,2,3”我认为我可以做while(getline(ss, number, ','))
,但我认为有一种更简单的方法。另外,我不知道如何编写这部分代码(删除字符)。
谢谢,
答案 0 :(得分:2)
由于您没有说明检查输入语法的有效性的要求,您可以做的最简单的是
std::getline
,将其放在istringstream
中,然后从流中一次读取一个数字。我想到这一点的方法是,如果代码接受简单的数字行,你可以通过键入它来尝试它。并且还支持其他格式。
祝你好运。PS:这是不正则表达式的作业。 ; - )
答案 1 :(得分:2)
首先,让我们从Line
类开始:
class Line
{
int a, b, c;
};
我们需要重载提取器,以便可以解析格式化的字符串:
template<class charT>
friend basic_istream<charT>& operator>>(basic_istream<charT>& is, Line& line)
{
return is >> line.a >> line.b >> line.c;
}
但是为了使提取工作,流需要“忽略”重要数据周围的字符。我们需要将流解析为'('
,','
,')'
和';'
作为空格字符。
该流使用表查找char
类型的对象。我们也可以制作自己的桌子:
class line_parser : public std::ctype<char>
{
public:
static mask* make_table()
{
static std::vector<mask> v(classic_table(),
classic_table() + table_size);
int table[10] = {0x20, 0x0c, 0x0a, 0x0d, 0x09,
0x0b, '(', ',', ')', ';'};
// ^^^^^^^^^^^^^^^^^^
for (int i : table)
v[i] |= space;
return &v[0];
}
explicit line_parser(int refs = 0) : ctype(make_table(), false, refs) { }
};
这是派生类方面。我们可以像这样将这个方面灌输到流上:
stringstream ss(line);
ss.imbue(locale(ss.getloc(), new line_parser));
但说实话,这有点乏味。用户不仅必须将新的区域设置添加到流中,而且如果以后想要使用先前的格式设置,它们还必须为原始区域设置提供补偿。为了促进这一点,我们必须找到一些封装此功能的方法。我们将创建一个为我们做这个的操纵器:
template<class Line>
class line_extractor
{
public:
line_extractor(Line& other)
: line(other)
{ }
private:
Line& line;
template<class charT>
void do_input(basic_istream<charT>& is) const
{
// imbue the new locale
locale loc = is.imbue(locale(is.getloc(), new line_parser));
is >> line;
is.imbue(loc); // imbue the original locale
}
template<class charT>
friend basic_istream<charT>& operator>>(basic_istream<charT>& is,
const line_extractor& le)
{
le.do_input(is);
return is;
}
};
然后减少代码,从函数返回:
template<class Line>
line_extractor<Line> get_line(Line& l)
{
return line_extractor<Line>(l);
}
现在我们完成了。输入可以简单地完成:
stringstream ss(line);
vector<Line> v;
for (Line line; ss >> get_line(line); )
{
v.push_back(line);
}
您还应添加检索a
,b
和c
值的方法。
<强> Here is a demo. 强>
答案 2 :(得分:1)
std::string str; // input data
std::stringstream ss;
int x, y, z;
char fake;
ss << str;
ss >> fake >> x >> fake >> y >> fake >> z >> fake;
x, y, z; // output data