仅替换第一次出现的QString

10

在QString中,有没有一种简单的方法只替换第一个子字符串为另一个子字符串?它可以出现在任何位置。


1
我认为你需要分两步来完成。首先使用IndexOf方法找到索引,然后再使用replace方法(index,lenoftexttoreplace, "newval")来替换文本。 - drescherjm
1
http://qt-project.org/doc/qt-4.8/qstring.html#replace - John Dibling
4个回答

23

你可以尝试这个:

QString str("this is a string"); // The initial string.
QString subStr("is"); // String to replace.
QString newStr("at"); // Replacement string.

str.replace(str.indexOf(subStr), subStr.size(), newStr);

最终的字符串将会是:

that at a string


这是一个字符串。 - SketchBookGames
1
如果您尝试匹配QRegularExpression,则此方法无法正常工作,因为它没有"size()"。 - Anon
@Akiva,QRegExpmatchedLength()函数,而QRegularExpressionMatchcapturedLength()函数 - 有什么问题吗? - Toby Speight
@TobySpeight,newString 中的反向引用(如\1)无效。 - Sascha
1
@Akiva,您可以使用正则表达式的pos和cap方法来获取文本位置和文本大小。就像我在https://stackoverflow.com/questions/34612750/qstring-remove-first-occurance-of-regular-expression/59314385#59314385中所解释的那样。 - kato2

3

对于您想要的操作,没有方便的方法。但是,您可以使用以下两种方法构建自定义操作:

int QString::indexOf(const QString & str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const

返回此字符串中字符串str的第一个出现位置的索引位置,从索引位置from向前搜索。如果未找到str,则返回-1。

如果cs为Qt :: CaseSensitive(默认值),则搜索区分大小写;否则,搜索不区分大小写。

QString & QString::replace(int position, int n, const QString & after)

用字符串after替换从索引位置position开始的n个字符,并返回对此字符串的引用。

注意:如果指定的位置索引在字符串内部,但position + n超出了字符串范围,则n将被调整以停止在字符串的末尾。

现在,将所有这些付诸实践,您可以编写如下内容:

main.cpp

#include <QString>
#include <QDebug>

int main()
{
    QString initialString = QLatin1String("foo bar baz");
    QString fooString = QLatin1String("foo");
    initialString.replace(initialString.indexOf(fooString),
                          fooString.size(), QLatin1String("stuff"));
    qDebug() << initialString;
    return 0;
}

main.pro

TEMPLATE = app                                         
TARGET = main                                              
QT = core                                              
SOURCES += main.cpp

构建和运行

qmake && make && ./main

输出

"stuff bar baz" 

0
这基本上就是 QString::replace(QRegularExpression, ...) 的实现方式。由于替换模式中可能包含字面反斜杠,因此需要以不同的方式捕获它们。请注意,实际的替换是从右到左进行的,以保留向左的偏移量有效性。虽然可以更紧凑地编写代码,但以这种形式调试更容易。
QRegularExpression regex = QRegularExpression(regex_pattern);

if (regex.isValid() and
    (regex_pattern.length() > 0)) {
    QRegularExpressionMatchIterator regex_iterator =
                                      regex.globalMatch(target_text, Apply_Target_Offset,
                                                        QRegularExpression::PartialPreferCompleteMatch);
    if (regex_iterator.hasNext()) {
        // At least one found
        QRegularExpressionMatch match = regex_iterator.next();
        if (match.hasMatch() and (not match.hasPartialMatch())) {
            // This is the first match, and it's complete
            int match_begin = match.capturedStart();
            int match_end = match.capturedEnd();
            int match_length = match.capturedLength();

            QStringList captured;
            const int capture_groups_count = regex.captureCount() + 1;
            for (int capture_group_idx = 0; capture_group_idx < capture_groups_count; ++capture_group_idx) {
                captured.append(match.captured(capture_group_idx));
            }

            QString replace_pattern = Apply_Replace_Pattern->toPlainText();
            QString replace_text = replace_pattern;
            QList<QRegularExpressionMatch> replace_pattern_match_list;
            QRegularExpression replace_pattern_regex = QRegularExpression("(?:\\\\\\\\)+|(?:\\\\(\\d+))");
            if (replace_pattern_regex.isValid()) {
                QRegularExpressionMatchIterator replace_pattern_regex_iterator =
                                                  replace_pattern_regex.globalMatch(replace_pattern);
                while (replace_pattern_regex_iterator.hasNext()) {
                    QRegularExpressionMatch replace_pattern_match = replace_pattern_regex_iterator.next();
                    bool no_error;
                    replace_pattern_match.captured().right(1).toInt(&no_error);
                    // Only accept backreferences w/ numbers
                    if (no_error) replace_pattern_match_list.append(replace_pattern_match);
                }

                while (replace_pattern_match_list.count() > 0) {
                    QRegularExpressionMatch replace_pattern_match = replace_pattern_match_list.takeLast();
                    int cap_idx = replace_pattern_match.captured(1).toInt();
                    if (cap_idx < captured.count()) {
                        replace_text.replace(replace_pattern_match.capturedStart(),
                                             (replace_pattern_match.capturedEnd() -
                                              replace_pattern_match.capturedStart()),
                                             captured[cap_idx]);
                    }
                }

                // Render '\' characters properly
                replace_text.replace("\\\\", "\\");
            }

            target_text.replace(match_begin, (match_end - match_begin), replace_text);
        }
    }
}

-1
//------------------------------------------------------------------
QString & replace_first(QString &io_haystack, const QString & sub_str, const QString & new_str)
{
  io_haystack.replace(io_haystack.indexOf(sub_str), sub_str.size(), new_str);
  return io_haystack;
} // replace_first
//------------------------------------------------------------------
QString & replace_first(QString &io_haystack, const QRegularExpression & sub_regx, const QString & new_str)
{
  QRegularExpressionMatch match;
  match = sub_regx.match(io_haystack);
  if (match.hasMatch()) {
    QString sub_str = match.captured(0);
    io_haystack.replace(io_haystack.indexOf(sub_str), sub_str.size(), new_str);
  }
  return io_haystack;
} // replace_first

虽然这段代码可能有助于解决问题,但是提供关于为什么和/或如何回答问题的额外背景信息将显着提高其长期价值。请编辑您的答案以添加一些解释。 - Toby Speight

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