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

How to parse a special parenthetical string in C++

本文关键字:一个 字符串 C++      更新时间:2023-10-16

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

谢谢,

由于您没有声明检查输入语法有效性的要求,因此最简单的方法是

  • 将每个"(",")"answers","替换为空格
  • 替换每个";"使用换行符(这不是绝对必要的,但很简单)
  • 使用例如std::getline一次读取一行,将其放在istringstream中,然后一次从流中读取一个数字

我的想法是,通过代码接受简单的数字行,你可以通过打字或类似的方式来尝试。并且还支持其他格式。

祝你好运。


PS:这是而不是正则表达式的作业。;-)

首先,让我们从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的值的方法。

这是一个演示

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
相关文章: