如何在Qt中分割QString并保留分隔符?

4

我有一个QString: "{x, c | 0x01}",我想将它分割成以下7个标记:

{
x
,
c
|
0x01
}

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

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


1
我在这个分离中没有找到任何逻辑,是什么特征将它们分开的? - eyllanesc
我认为你最好的选择是遍历字符串并根据你的特定需求定义条件。 - Abhishek Agarwal
@eyllanesc 我想用分隔符字符:“{”,“}”,“,”,“|”来拆分它。 - ricky
如果您需要一般性的解释,我建议您熟悉分词器或词法扫描器。如果您需要更完整的框架,还有DSL语言解析器(领域特定语言),可惜Qt没有开箱即用的支持,但您可以查看C++ Boost库作为例子。 - xander
3个回答

1
基本上,您需要迭代字符串,检查是否找到了分隔符,并将分隔符添加到列表中。如果未找到分隔符,则会将新的“单词”添加到列表中,并且在下一个分隔符被找到之前,字符将被添加到该单词中。请看以下示例:
 //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()方法? - ricky
你说得对,使用str.insert()是相当愚蠢的。看看我的新代码,它使用StringBuilder来连接临时字符串。 - travisjayday
我不明白,如果您已经有令牌,为什么首先要使用临时字符串,然后再拆分它呢?为什么不能直接将令牌添加到“QStringList”中呢?! - xander
再次编辑我的代码。你觉得怎么样?看起来更好了,不是吗 ;) - travisjayday
1
已经好多了,我想你可以把它留作 OP 的一个例子,不必完美。:) 顺便说一下,你可以像这样访问 QList 中的最后一个元素:out.last().append(c);(应该比 out[(out.length()-1)] 更好用和更好看吧)。 - xander

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("");,因为第一个元素将是垃圾""


-1

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

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

需要做的是使用前瞻查找每个分隔符之前的零字符字符串:(?=[\\{\\},|]),并查找分隔符之后的零字符字符串(?<=[\\{\\},|])

将它们结合起来得到:

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

以下代码将会输出所需结果:("{", "x", ",", "c", "|", "0x01", "}")


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接