【问题标题】:How to split QString and keep the separator in Qt?如何拆分 QString 并在 Qt 中保留分隔符?
【发布时间】:2017-07-25 03:11:24
【问题描述】:

我有一个 QString:“{x, c | 0x01}”,我想将其拆分为 7 个标记,如下所示:

{
x
,
c
|
0x01
}

在 Qt 中最好的方法是什么?

我尝试使用QString::split(QRegExp("[\\{\\},|]")),但它在结果中保留分隔符。

【问题讨论】:

  • 我没有发现分离的逻辑,分离的特点是什么?
  • 我认为您最好的选择是遍历字符串并根据您的特定要求定义条件
  • @eyllanesc 我想用 deliminator char 分割它:'{', '}', ',', '|'
  • 如果您想要一个一般性的解释,我建议您熟悉分词器或词法扫描器。如果您需要更完整的框架,还有 DSL 语言解析器(领域特定语言),遗憾的是 Qt 没有开箱即用的支持,但您可以查看 c++ boost 库。

标签: qt qstring qregexp


【解决方案1】:

也许这个解决方案可以为您服务:

int main(void) {
    QString str { "{x, c | 0x01}" };
    QRegExp separators { "[\\{\\},|]" };

    QStringList list;
    str.replace( " ", "" );

    int mem = 0;
    for(int i = 0; i<str.size(); ++i) {
        if(i == str.indexOf(separators, i)) {
            if(mem) list.append(str.mid(mem, i-mem)); // append str before separator
            list.append(str.mid(i, 1));               // append separator
            mem = i+1;
        }
    }

    qDebug() << list;

    return 0;
}

输出:("{", "x", ",", "c", "|", "0x01", "}")

您可以消除if(mem),然后在for 循环之后使用list.pop_front();list.removeAll("");,因为第一个元素将是垃圾""

【讨论】:

    【解决方案2】:


    基本上,您遍历字符串,检查是否找到分隔符,然后将分隔符添加到列表中。如果没有找到分隔符,则将一个新的“单词”添加到列表中,直到找到下一个分隔符,才会将字符添加到单词中。看看:

     //input string
    QString str = "{x, c | 0x01}";
    QList<QString> out;
    
    //flag used to keep track of whether we're adding a mullti-char word, or just a deliminator
    bool insideWord = false;
    
    //remove whitespaces
    str = str.simplified();
    str = str.replace(" ", "");
    
    //iterate through string, check for delims, populate out list
    for (int i = 0; i < str.length(); i++)
    {
        QChar c = str.at(i);    //get char at current index
        if (c == '{' || c == '}' || c == ',' || c == '|')
        {
            //append deliminator
            out.append(c);
            insideWord = false;
        }
        else
        {
            //append new word to qlist...
            if (!insideWord)
            {
                out.append(c);
                insideWord = true;
            }
            //but if word already started
            else
            {
                //add 'c' to the word in last index of the qlist
                out.last().append(c);
            }
        }
    }
    
    //output as requested by OP
    qDebug() << "String is" << out;
    

    【讨论】:

    • 感谢您的回答。实际上,我使用的方法与您的方法非常相似。但我想知道是否有更好的方法通过避免调用 str.insert() 方法来提高性能?
    • 你是对的,使用 str.insert() 是很愚蠢的。看看我的新代码,它使用 StringBuilder 连接到一个临时字符串。
    • 我不明白,如果您可以简单地将令牌直接添加到QStringList,为什么您首先使用临时字符串并稍后再次拆分它(因为您已经有了令牌!)!?
    • 再次编辑我的代码。你怎么看?看起来更好,不是吗;)
    • 已经更好了,我想您可以将其作为 OP 的示例,我猜它不一定是完美的。 :) 顺便说一句,您可以像 out.last().append(c); 一样访问对 QList 中最后一个元素的引用(应该可以工作并且看起来比 out[(out.length()-1)] 更好)。
    【解决方案3】:

    这可以在单个正则表达式中完成,但必须使用前瞻和后瞻。

    问题中指定的表达式 ([\\{\\},|]) 将匹配一个 1 字符的长字符串,该字符串由 {},| 中的任意字符组成。 QString.split 然后将删除该 1 个字符的长字符串。

    需要的是使用前瞻:(?=[\\{\\},|]) 在每个分隔符之前立即找到零字符串,并在分隔符 (?&lt;=[\\{\\},|]) 之后立即找到零字符串。

    结合这些给出:

    QString::split(QRegularExpression("(?=[\\{\\},|])|(?<=[\\{\\},|])"))
    

    这将提供所需的输出:("{", "x", ",", "c", "|", "0x01", "}")

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-16
      • 2011-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-26
      相关资源
      最近更新 更多