分析C++字符串

Parsing C++ strings

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

这里有很多关于发布字符串的帖子,但实际上似乎不符合我的目的。

我正在使用std::string和所有标准库C++并且我有一个使用以下协议的文本文件:

TEXT1:TEXT2-TAB-TEXT3:TEXT4 TEXT5

-TAB- t.

我想将所有文本放入字符串中(也可以是一个数组)。文件中的所有行都是这样写的,我尝试使用istringstream但它没有功能,例如:iss >> text1 >> ":" >> text2 >> "t" >> text3 >> ":" >> text4 >> " " >> text5 .

我真的需要使用find等的基本函数进行解析吗?那将是大量的工作(因为我有几个以不同格式编写的文件,我需要为所有这些文件创建一个通用函数),如果我别无选择,我会这样做。

那么......有没有办法通过以下方式解析字符串,在字符串之间使用已知字符?它不是一个特定的分隔符,因为每行都包含几个分隔符(一次是空格,然后是冒号等等)。我想使用C++标准库,而不是任何外部库,如 Boost。

编辑:C++11.

由于您使用的是 C++11 并且您的文本行遵守协议,因此用于模式匹配和信息提取的工具是正则表达式库中的功能。

匹配您的协议的模式可能如下所示...

\w+:\w+-\t-\w+:\w+\

s\w+

。使用默认的 ECMAScript 语法。还有其他一些。

接下来,使用原始字符串文本初始化正则表达式对象...

regex pat{R("\

w+:\w+-\t-\w+:\w+\s\w+")};

所以现在你的代码可以看起来像这样...

#include<regex>
...
regex pat{R("w+:w+-t-w+:w+sw+")};
smatch m;
while (cin >> str) {  // where str is your line of formatted text
    bool match = regex_search(str, m, pat);
    for (int i = 0; i < m.size(); i++) {
        cout << m[i].str() << " "; // to make sure each component was matched
    }   
}

顺便说一下,smatch 的工作方式类似于容器,可以迭代,因此非常方便。

注意:上面的代码不能保证有效,它被用作指南。

由于您有一个固定的字符来标记每个字段的末尾,因此像正则表达式之类的任何东西都接近于矫枉过正。我只是使用std::getline来读取每个字段。

我首先为一行中的字段定义一个结构,然后重载operator>>以读取其中一个结构:

struct line { 
    std::string text1, text2, text3, text4, text5;
    friend std::istream &operator>>(std::istream &is, line &l) {
        std::getline(is, l.text1, ':');
        std::getline(is, l.text2, 't');
        std::getline(is, l.text3, ':');
        std::getline(is, l.text4, ' ');
        std::getline(is, l.text5);
        return is;
    }
};

有了它,您可以阅读如下行:

line x;
std::cin >> x;

。或者,如果你有一个完整的文件,里面有很多这样的行,你可以把它们全部读到一个向量中,比如:

std::ifstream infile("whatever.dat");
std::vector<line> lines {
    std::istream_iterator<line>(lines),
    std::istream_iterator<line>()
};

您可能应该使用 std::getline 读取整行,然后解析该行,例如使用 find 或 find_first_of std::string 的方法查找't'字符。

如果可能,请至少切换到 C++11,因为 C++11 的许多功能将使您能够编写更少的代码。特别是 std::find from <algorithm> 在与匿名 lambda 一起使用时很有帮助。

当然,您应该更正式地定义可接受的输入(也许使用一些 EBNF 符号,至少在注释中)。特别是,您的TEXT1TEXT2中可以出现哪些确切的字符,TEXT3TEXT4TEXT5。用什么编码?(UTF-8 具有多字节字符!

如果输入规范很复杂,您可以考虑使用一些解析器生成器,如 ANTLR 等。