如何在C ++中解析一个特殊的括号字符串

时间:2013-12-13 16:33:09

标签: c++

我有以下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, ',')),但我认为有一种更简单的方法。另外,我不知道如何编写这部分代码(删除字符)。

谢谢,

3 个答案:

答案 0 :(得分:2)

由于您没有说明检查输入语法的有效性的要求,您可以做的最简单的是

  • 替换所有&#39;(&#39;,&#39;)&#39;和&#39;,&#39;与空间。
  • 更换每个&#39;;&#39;使用换行符(这不是绝对必要的,但它很简单)。
  • 使用例如一次读取一行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);
}

您还应添加检索abc值的方法。

<强> 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