【问题标题】:How to split these strings into an array如何将这些字符串拆分为数组
【发布时间】:2010-11-30 20:26:55
【问题描述】:

我正在寻找一种将以下文本行拆分为数组的方法。

这是一些文字\r\n“这里是另一行”\r\n还有另一行

这样得到的数组是:

这里有一些文字

\r\n

"

这是另一行

"

\r\n

还有一行

注意这里基本上有两个分隔符,"\r\n
我需要在 C++ 中执行此操作,将来可能会有额外的分隔符。
有什么想法吗?

提前致谢。

编辑:不,这不是家庭作业。

这是我目前所拥有的:

const RWCString crLF = "\r\n";
const RWCString doubleQuote = "\"";


    RWTValOrderedVector<RWCString> Split(const RWCString &value, const RWCString &specialContent)
    {
        RWTValOrderedVector<RWCString> result;
    
        unsigned index = 0;
    
        RWCString str = value;
    
        while ( ( index = str.index( specialContent, 0, RWCString::ignoreCase ) ) != RW_NPOS )
        {
            RWCString line = str(0, index);
    
            result.append(line);
            result.append(specialContent);
    
            str = str(index, str.length() - index);
            str = str(specialContent.length(), str.length() - specialContent.length());
        }
    
        if (str.length() > 0)
        {
            result.append(str);
        }
    
        return result;
    }
    
        void replaceSpecialContents(const RWCString &value)
        {
        
            RWTValOrderedVector<RWCString> allStrings;
        
            RWTValOrderedVector<RWCString> crLFStrings = Split(value, crLF);
        
            for (unsigned i=0; i<crLFStrings.entries(); i++)
            {
            RWTValOrderedVector<RWCString> dqStrings = Split(crLFStrings[i], doubleQuote);
        
                if (dqStrings.entries() == 1)
                {
                    allStrings.append(crLFStrings[i]);
                }
                else
                {
                    for (unsigned j=0; j<dqStrings.entries(); j++)
                    {
                        allStrings.append(dqStrings[j]);
                    }
                }
            }
    
    }

【问题讨论】:

  • 您已经尝试过哪些方法?
  • 基本上,您希望将其拆分为令牌(尽管令牌通常不是整行)。为了标记输入,您需要一个词法分析器。
  • 小心“\r\n”。在某些平台上,这是行终止序列。因此,如果您以文本模式(默认)打开文件,这两个字符将被转换为单个 '\n' 字符(在某些平台上)。另请注意:相反,“\n”字符在写入文件(以文本模式打开)时会转换为行终止序列。
  • RWTValOrderedVector: 只是想知道,什么是无序向量?
  • @ybungalobill - RWTValVector&lt;T&gt; 遗憾的是,它对方法有限制。例如,没有append,因为该类假定向量生命周期的长度恒定。有一个reshape,所以如果你为它工作,你可以做一个追加。

标签: c++ split


【解决方案1】:

这是一种适用于 C 和 C++ 的方法:

//String to tokenize:
char str[] = "let's get some tokens!";

//A set of delimiters:
char delims[] = " ";

//List of tokens:
char *tok1 = NULL,
     *tok2 = NULL,
     *tok3 = NULL;

//Tokenize the string:
tok1 = strtok(str, delims);
tok2 = strtok(NULL, delims); //after you get the first token
tok3 = strtok(NULL, delims); //supply "NULL" as first strtok parameter

您可以通过多种方式对此进行修改。您可以将所有“strtok(NULL, delims)”调用放在一个循环中以使其更加灵活,您可以使用 .c_str() 等与 C++ 字符串交互。

【讨论】:

  • 谢谢,我已经试过了,但它不包括令牌
【解决方案2】:

getline 有一个可选的分隔符,因此您可以使用stringstream 轻松完成此操作。缺点是(我相信)它一次只能使用一个分隔符。

【讨论】:

    【解决方案3】:

    将问题一分为二:

    1. 我有一个指向子字符串的指针。如何找到下一个子串?
    2. 我有一个指向子字符串的指针。如何将它作为下一个元素添加到数组中?

    现在,解决1和2。如果有问题,再问。

    【讨论】:

      【解决方案4】:

      您可以使用string::find_first_ofstring::substr。请注意检查“空”字符串; find_first_of 会找到chars,所以\r\n 都会被生成的算法分开。

      或者,遍历整个字符串,并在遇到另一个分隔符时复制前一部分。

      【讨论】:

        【解决方案5】:

        一个非常简单的方法是只使用 flex:
        只需几行代码,您就可以为 C++ 应用程序构建一个非常简单的词法分析器。

        注意:

        我注意到你应该小心使用'\r\n'。如果您以文本模式(默认)打开文件,则标准流读取会将标准行终止序列转换为“\n”。在某些平台上,行尾终止序列是 '\r\n',因此如果您从文件中读取流,您可能只会看到一个 '\n' 字符。

        split.lex

        %option c++
        %option noyywrap
        %%
        \"           return 1;
        \r\n         return 2;
        [^"\r\n]*    return 3;
        %%
        

        main.cpp

        #include "FlexLexer.h"
        
        int main()
        {
            yyFlexLexer     lexer(&std::cin, &std::cout);
            int             token;
        
            while((token = lexer.yylex()) != 0)
            {
                std::string  tok(lexer.YYText(), lexer.YYText() + lexer.YYLeng());
                std::cout << "Token: " << token << "(" << tok << ")\n";
            }
        }
        

        构建

        % flex split.lex
        % g++ main.cpp lex.yy.cc
        

        运行(在准备好的文件上)

        % cat testfile | ./a.exe
        Token: 3(Here is some text)
        Token: 2(
        )
        Token: 1(")
        Token: 3(here is another line)
        Token: 1(")
        Token: 2(
        )
        Token: 3(And another line)
        

        【讨论】:

          【解决方案6】:

          基于您正在使用的 Rogue Wave SourcePro API,您可以使用 RWTRegex 将字符串拆分为标记:

          RWTValOrderedVector<RWCString> tokenize(const RWCString& str)
          {
              RWTRegex<char> re("\\r\\n|\"|([^\"\\r]|\\r[^\\n])*|\\r$");
          
              RWTRegex<char>::iterator it(re, str);
          
              RWTValOrderedVector<RWCString> result;
              for (; it != RWTRegex<char>::iterator(); ++it) {
                  result.append(it->subString(str));
              }
              return result;
          }
          

          有关 RWTRegex 的详细信息,请参阅http://www.roguewave.com/Portals/0/products/sourcepro/docs/12.0/html/sourceproref/classRWTRegex.html

          【讨论】:

            【解决方案7】:

            这是一种使用 TR1 正则表达式功能的方法。

            std::string text("Here is some text\r\n\"here is another line\"\r\nAnd another line");
            std::vector<std::string> vec;
            
            std::regex rx("[\\w ]+|\\r\\n|\"");
            std::sregex_iterator rxi(text.begin(), text.end(), rx), rxend;
            
            for (; rxi != rxend; ++rxi)
            {
                vec.push_back(rxi->str());
            }
            

            在我的测试中,这会在您的示例中使用 7 个子字符串填充向量。我不是专家,所以可能有比我使用的更正确的正则表达式。

            【讨论】:

              【解决方案8】:

              strtok 将用 NULL 替换您的标记。这就是它不包含令牌的原因。

              man strtok 了解更多信息。我也在玩 strtok 和 strtok_r 因为我有以下传入的 char 数组

              你好~Milktea~这是我的留言\r\n留言~我有一块好表~卡地亚\r\n

              我将首先去掉 ~(波浪号),然后是 \r\n,反之亦然。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2015-07-18
                • 1970-01-01
                • 2016-04-01
                • 1970-01-01
                • 2014-10-17
                • 2012-02-22
                相关资源
                最近更新 更多