QString заменяет только первое вхождение

Есть ли простой способ заменить только первое вхождение некоторой подстроки другой подстрокой в ​​QString? Он может быть в любом положении.


person user3136871    schedule 09.01.2014    source источник
comment
Я думаю, что вы должны сделать это в 2 шага. Найдите индекс с помощью IndexOf, а затем используйте replace(index,lenoftexttoreplace, newval)   -  person drescherjm    schedule 09.01.2014
comment
qt-project.org/doc/qt-4.8/qstring.html# заменить   -  person John Dibling    schedule 09.01.2014


Ответы (4)


Вы можете попробовать это:

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);

Результирующая строка будет:

что на веревке

person vahancho    schedule 09.01.2014
comment
Результирующая строка должна быть: this в строке - person SketchBookGames; 22.08.2014
comment
Это не работает, если вы пытаетесь сопоставить QRegularExpression, поскольку оно не имеет size(). - person Anon; 12.12.2015
comment
@Akiva, у QRegExp есть matchedLength(), а у QRegularExpressionMatch есть capturedLength() - в чем проблема? - person Toby Speight; 05.07.2016
comment
Однако обратные ссылки @TobySpeight в newString (например, \1) не работают. - person Sascha; 25.01.2018
comment
@Akiva, вы можете использовать методы pos и cap регулярного выражения, чтобы получить положение текста и размер текста. Точно так же, как я объяснил в stackoverflow.com/questions/34612750/ - person kato2; 13.12.2019

Не существует удобного метода для операции, которую вы хотите иметь. Однако вы можете использовать следующие два метода для создания пользовательской операции:

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

Возвращает позицию индекса первого вхождения строки str в этой строке, выполняя поиск вперед от позиции индекса. Возвращает -1, если строка не найдена.

Если cs равно Qt::CaseSensitive (по умолчанию), поиск чувствителен к регистру; в противном случае поиск нечувствителен к регистру.

а также

QString и QString::replace(int position, int n, const QString & после)

Заменяет 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" 
person lpapp    schedule 09.01.2014

Это почти так, как это делает 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);
        }
    }
}
person kcrossen    schedule 04.01.2017

person    schedule
comment
Хотя этот код может помочь решить проблему, предоставление дополнительного контекста относительно того, почему и/или как он отвечает на вопрос, значительно повысит его ценность в долгосрочной перспективе. Пожалуйста, отредактируйте свой ответ, чтобы добавить некоторые пояснения. - person Toby Speight; 05.07.2016