【问题标题】:Splitting strings separated by \r\n into array of strings [C/C++]将由 \r\n 分隔的字符串拆分为字符串数组 [C/C++]
【发布时间】:2014-11-30 02:45:48
【问题描述】:

我的字符串包含例如"FirstWord\r\nSecondWord\r\nThird Word\n\r"等等…… 我想使用vector <string> 将其拆分为字符串数组,这样我会得到:

FileName[0] == "FirstWord";
FileName[1] == "SecondWord"; 
FileName[2] == "Third Word";

另外,请注意第三个字符串中的空格。

这是我目前得到的:

string text = Files; // Files var contains the huge string of lines separated by \r\n
vector<string> FileName; // (optionaly) Here I want to store the result without \r\n

regex rx("[^\\s]+\r\n");
sregex_iterator FormatedFileList(text.begin(), text.end(), rx), rxend;

while(FormatedFileList != rxend)
{
    FileName.push_back(FormatedFileList->str().c_str());
    ++FormatedFileList;
}

它有效,但是当涉及到第三个字符串 "Third Word\r\n" 时,它只给我"Word\r\n"

谁能向我解释正则表达式是如何工作的?我有点困惑。

【问题讨论】:

    标签: c++ arrays regex split line-breaks


    【解决方案1】:

    \s 匹配所有空格,包括常规空格、制表符和其他一些空格。你只想排除\r\n,所以你的正则表达式应该是

    regex rx("[^\r\n]+\r\n");
    

    编辑:这不适合评论,也不会详尽——正则表达式是一个相当复杂的话题,但我会尽力给出粗略的解释。如果您了解正式语言,所有这些确实更有意义,所以我鼓励您阅读它,网上有无数的正则表达式教程更详细,您也应该阅读。好的。

    您的代码使用sregex_iterator 遍历字符串text 中正则表达式rx 匹配的所有位置,然后将它们转换为字符串并保存。那么,什么是正则表达式?

    正则表达式是将模式匹配应用于字符串的一种方式。这可以从简单的子字符串搜索到......嗯,再到复杂的子字符串搜索,真的。例如,您可以搜索"oo",后跟任何字符,后跟"a",然后在"foobar" 和@987654333 中找到它,而不是仅仅在字符串"foobar" 中查找"oba" 的实例@。

    为了启用这种模式搜索,您必须有一种方法来指定您要查找的模式,其中一种方法是正则表达式。细节因实现而异,但通常它通过定义匹配特殊事物的特殊字符或修改模式其他部分的行为来工作。这听起来令人困惑,所以让我们考虑几个例子:

    • 句点. 匹配任何单个字符
    • Kleene 星 * 后面的某事与该某事的零个或多个实例匹配
    • 后跟 + 的内容将匹配该内容的一个或多个实例
    • 方括号[]括起一组字符;然后整个内容匹配这些字符中的任何一个。
    • 插入符号 ^ 反转括号表达式的选择

    仍然令人困惑。所以让我们把它放在一起:

    oo.a
    

    是使用. 的正则表达式。这将匹配“oo.a”、“ooba”、“oona”、“oo|a”以及其他任何两个 o 后跟一个字符后跟一个 a 的内容。它不会匹配“ooa”、“oba”或“废话”。

    a*
    

    将匹配 ""、"a"、"aa"、"aaa" 以及任何其他仅由 a 组成但不包含其他任何内容的序列。

    [fgh]oobar
    

    将匹配“foobar”、“goobar”和“hoobar”中的任何一个,仅此而已。

    [^fgh]oobar
    

    将匹配“aoobar”、“boobar”、“coobar”等,但不匹配“foobar”、“goobar”和“hoobar”。

    [^fgh]+oobar
    

    将匹配“aoobar”、“aboobar”、“abcoobar”,但不匹配“oobar”、“foobar”、“agoobar”和“abhoobar”。

    在你的情况下,

    [^\r\n]+\r\n
    

    将匹配一个或多个既不是\r 也不是\n 后跟\r\n 的字符的任何实例。然后,您遍历所有这些匹配项并保存 text 的匹配部分。

    这是我认为我可以合理地到达这里的深度。这个兔子洞非常深,这意味着你可以用正则表达式做一些非常酷的事情,但你不应该期望在一两天内掌握它们。其中大部分内容与我刚刚概述的内容一致,但是以真正的程序员的方式,大多数正则表达式实现超出了常规语言和表达式的数学范围,并引入了有用但令人费解的东西。龙在前头,但旅途是值得的。

    【讨论】:

    • 谢谢!它有效:) 我真的不明白正则表达式,请你解释一下,[^\r\n]+\r\n 的真正含义是什么?
    • 这意味着匹配除回车或换行“一次或多次”外的任何内容,然后是回车然后换行。
    • 伙计,你是天才!这是我读过的关于正则表达式的最好的介绍!非常感谢!
    【解决方案2】:

    一个简单的替代方法是使用 Boost 中的 split_regex。例如。 split_regex(out, input, boost::regex("(\r\n)+")) 其中 out 是字符串向量, input 是输入字符串。下面贴一个完整的例子:

    #include <vector>
    #include <iostream>
    #include <boost/algorithm/string/regex.hpp>
    #include <boost/regex.hpp>
    
    using std::endl;
    using std::cout;
    using std::string;
    using std::vector;
    using boost::algorithm::split_regex;
    
    int main()
    {
        vector<string> out;
        string input = "aabcdabc\r\n\r\ndhhh\r\ndabcpqrshhsshabc";
        split_regex(out, input, boost::regex("(\r\n)+"));
        for (auto &x : out) {
            std::cout << "Split: " << x << std::endl;
        }
        return 0;
    }
    

    【讨论】:

      【解决方案3】:

      regex rx("[^\\s]+\r\n");,似乎您正在尝试匹配字符串而不是拆分它。这个[^\\s] 否定字符类意味着匹配任何字符,但不匹配空格(水平空格或换行符)。在第三行,有一个水平空间,因此您的正则表达式匹配水平空间旁边的文本。在多行模式下,. 将匹配任何字符,但不匹配换行符。你可以使用regex rx(".+\r\n"); 代替regex rx("[^\\s]+\r\n");

      【讨论】:

        【解决方案4】:

        这也是一种方法:

        char * pch = strtok((LPSTR)Files.c_str(), "\r\n");
        while(pch != NULL)
        {
            FileName.push_back(pch);
            pch = strtok(NULL, "\r\n");
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-06-27
          • 2017-06-27
          • 1970-01-01
          • 1970-01-01
          • 2022-01-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多