Решение неоднозначности QString arg() в QT

Существует проблема с использованием QString::arg(), когда строка содержит цифру сразу после маркера места. Из описания функции QString::arg() непонятно, что произойдет в случае такой замены:

QString("String for replacement %1234").arg("blah");

Это приведет к "String for replacement blah234" или "String for replacement blah34"?

Я просмотрел исходный код QT, чтобы ответить на этот вопрос. Кажется, что алгоритм, который ищет маркеры мест, является «жадным», и в приведенном выше примере он будет принимать обе цифры.

Вот источник функции QT, которая используется внутри QString::arg() (QT 4.8.4):

static ArgEscapeData findArgEscapes(const QString &s)
{
const QChar *uc_begin = s.unicode();
const QChar *uc_end = uc_begin + s.length();

ArgEscapeData d;

d.min_escape = INT_MAX;
d.occurrences = 0;
d.escape_len = 0;
d.locale_occurrences = 0;

const QChar *c = uc_begin;
while (c != uc_end) {
    while (c != uc_end && c->unicode() != '%')
        ++c;

    if (c == uc_end)
        break;
    const QChar *escape_start = c;
    if (++c == uc_end)
        break;

    bool locale_arg = false;
    if (c->unicode() == 'L') {
        locale_arg = true;
        if (++c == uc_end)
            break;
    }

    if (c->digitValue() == -1)
        continue;

    int escape = c->digitValue();
    ++c;

    if (c != uc_end && c->digitValue() != -1) {
        escape = (10 * escape) + c->digitValue();
        ++c;
    }

    if (escape > d.min_escape)
        continue;

    if (escape < d.min_escape) {
        d.min_escape = escape;
        d.occurrences = 0;
        d.escape_len = 0;
        d.locale_occurrences = 0;
    }

    ++d.occurrences;
    if (locale_arg)
        ++d.locale_occurrences;
    d.escape_len += c - escape_start;
}
return d;
}

Есть ли лучший способ решить такую ​​двусмысленность, чем всегда использовать двузначные маркеры места?


person Oleg Yakovenko    schedule 24.05.2013    source источник
comment
Это отличное наблюдение, я никогда не думал об этом. Единственное, что я думаю сделать, это QString("String for replacement %1%2").arg("blah").arg(234);, но это довольно уродливо.   -  person Taylor Brandstetter    schedule 24.05.2013


Ответы (3)


Поскольку вы можете использовать только маркеры от %1 до %99 и можете пропускать номера маркеров, вы можете написать:

QString("String for replacement %10234").arg("blah");

вывести String для замены blah234

person Frank    schedule 14.10.2014
comment
И черт возьми, прокомментируйте это, потому что это определенно не будет интуитивно понятным для следующего человека, который посмотрит на код (или для вас через 3 года). По крайней мере, это работает. - person iamtheddrman; 19.12.2014

Состояния справки Qt для arg(const QString & a, int fieldWidth = 0, QChar fillChar = QLatin1Char( ' ' ))

Возвращает копию этой строки с маркером места с наименьшим номером, замененным строкой a, т. е. %1, %2, ..., %99.

...

Номера маркеров мест должны быть в диапазоне от 1 до 99.

Следовательно, то, что вы видите, по определению верно; первые две цифры будут заменены. Если вам нужна «Строка для замены blah234», вы можете определить строку как: -

QString("String for replacement %1%2").arg("blah").arg(234);
person TheDarkKnight    schedule 24.05.2013
comment
Я не говорю, что что-то не так. Я говорю, что цифра после маркера места создает некоторую двусмысленность. Между маркерами места в вашем решении есть дополнительное пространство. Если есть место, такой проблемы нет. - person Oleg Yakovenko; 27.05.2013

У меня такая же проблема, но ответы на заказ не выглядят хорошим способом для меня.

Я разрешил двусмысленность таким образом.

QString myString= QString("ConcatenatedNumbers%0123").arg(66,3,10, QChar('0'));

Строка будет:

ConcatenatedNumbers06623
person Mquinteiro    schedule 10.09.2016