Russian Qt Forum

Qt => Общие вопросы => Тема начата: burunduk от Март 30, 2006, 11:17



Название: QString().arg() bug ?
Отправлено: burunduk от Март 30, 2006, 11:17
QString s = QString("%10%2").arg("A").arg("B");

результат выражения: BA

Я вообще-то ожидал выражения A0B.


Qt 4.1.0 open-source


Название: QString().arg() bug ?
Отправлено: Asaphus_Expansus от Март 30, 2006, 11:37
Это не баг, это фича.

Теперь arg не ограничивается %9, как я понимаю, поэтому он парсит %10 как 10. А заменяет двойку, B - десятку.

Варианты решения:
QString("%1 \b0%2").arg("A").arg("B")
QString("%1%2").arg("A0").arg("B")
QString("%1%2%3").arg("A").arg("0").arg("B")


Название: QString().arg() bug ?
Отправлено: burunduk от Март 30, 2006, 11:44
В документации написано:

QString QString::arg ( const QString & a, int fieldWidth = 0, const QChar & fillChar = QLatin1Char( ' ' ) ) const

This function returns a copy of this string where a replaces the lowest numbered occurrence of %1, %2, ..., %9.


Название: QString().arg() bug ?
Отправлено: Asaphus_Expansus от Март 30, 2006, 11:48
Ну дока всегда немножко более старая чем положено, я еще со времен Qt 1.31 к этому привык :)

В коде же мы видим

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

что даже комментировать не нужно, я полагаю :)


Название: QString().arg() bug ?
Отправлено: burunduk от Март 30, 2006, 12:03
ясно, спасибо :)


Название: QString().arg() bug ?
Отправлено: Dendy от Март 30, 2006, 12:23
Дока с Qt 4.1.1

This function returns a copy of this string where a replaces the lowest numbered occurrence of %1, %2, ..., %99.

arg() будет заменять первую младшую цифру что найдёт. ИМХО все три решения не катят.

1. \b вставляет символ, которьІй в машинном коде будет присутствовать в строке.
2. не катит, если "A" или "B" хранятся в переменньІх.
3. тож коряво, "0" не должен вставляться, хотя...

ИМХО, вот наверное более "правильньІй" способ:

Код:
QStrings = QString( "%1" ).arg( stra + "0" + strb );


Название: QString().arg() bug ?
Отправлено: Asaphus_Expansus от Март 30, 2006, 12:46
Цитировать

все три решения не катят


Все три решения работают для вывода на экран в рамках поставленой задачи - на экран выводится "A0B".

Цитировать

QString s = QString( "%1" ).arg( stra + "0" + strb );


"Бессмысленно и беспощадно".

По одной простой причине: основное назначение функции arg(), это вывод аргументов в строки ПОДЛЕЖАЩИЕ ЛОКАЛИЗАЦИИ, для того, чтобы правильно сформировать сообщения, сообразно требованиям языка.

Например: в английском варианте вы можете указать строку
"Error %1 found in line %2", а в русском "В строке %2 обнаружена ошибка %1".
Код будет работать правильно без перекомпиляции.

Ваше решение (в котором вообще непонятно зачем нужна функция arg()) напрочь убивает это достоинство, поскольку порядок следования аргументов и их склейка явно прошиты в код, что совершенно не comme il faut.


Название: QString().arg() bug ?
Отправлено: Dendy от Март 30, 2006, 13:19
Кхмммм..... Неужели вьІ думаете, что задававшему вопрос решение нужно только для того, чтобьІ вьІводить "A0B"? В таком случае

Код:
QString s( "A0B" );


тоже решение задачи.

Локализация - одна из фич, расширяемая данной функцией, но совершенно не основная. Главное - форматирование, то-есть упорядоченная строка из нескольких вставок произвольного типа. Так что если в данной задаче главное - порядок, то соединение строк с нулём посередине можно делать и простой конкатенацией. А свой пример я предоставил только, чтобьІ показать универсальность: результирующая строка вставляется в шаблон, и конечно же глупо бьІло бьІ оставить его как: QString( "%1" ). Ето не нужно обьяснять.


Название: QString().arg() bug ?
Отправлено: Asaphus_Expansus от Март 30, 2006, 13:32
Цитировать

Локализация - одна из фич, расширяемая данной функцией, но совершенно не основная. Главное - форматирование, то-есть упорядоченная строка из нескольких вставок произвольного типа.


Для простого форматирования изначально был sprintf() а сейчас рекомендуется QTextOStream.

arg() изначально планировался под локализацию и именно это и есть его целевое назначение. Именно для этого кроме простых %1 %2 etc реализованы еще и %L1, %L2 ...

Цитировать

For translations, especially if the strings contains more than one escape sequence, you should consider using the arg() function instead. This allows the order of the replacements to be controlled by the translator.


Название: QString().arg() bug ?
Отправлено: Dendy от Март 30, 2006, 15:32
Согласен, без данного метода локализация в стиле Qt потеряла бьІ очень много. Но есть ещё множество случаев для простого форматирования, например при обращении к файловой системе.

Пожалуйста, обьясните как из вьІражения:

Код:
QString( "%1 \b0%2" ).arg( "A" ).arg( "B" );


должна получиться строка "A0B". Проверил на практике: вместо \b вставляется какой-то спецвимвол.


Название: QString().arg() bug ?
Отправлено: Asaphus_Expansus от Март 30, 2006, 15:39
Цитировать

Пожалуйста, обьясните как из вьІражения:
Цитировать

Код:
QString( "%1 \b0%2" ).arg( "A" ).arg( "B" );

должна получиться строка "A0B". Проверил на практике: вместо \b вставляется какой-то спецвимвол.


Вы не знаете что такое '\b' в строках C/C++ или не знаете как этот символ отрабатывается при выводе на консольный экран (или, исторически, на принтер) ?

Или Вы пытаетесь расказать, что байтовый массив будет отличен от "A0B"? Ну так это всем очевидно.


Название: QString().arg() bug ?
Отправлено: Dendy от Март 30, 2006, 16:00
Етим спец-символом пользоваться не приходилось. Пожалуйста, ответьте на вопрос. Как должна получиться строка "A0B" из такого вьІражения?


Название: QString().arg() bug ?
Отправлено: Asaphus_Expansus от Март 30, 2006, 16:15
Ок, извините за некоторый сарказм, я не предполагал, что Вы, выказывающий приличное знание Qt по многим вопросам действительно не знаете что такое '\b'.

Это специальный символ, который препроцессором компилятора заменяется на байт с десятичным значением 8 (0x08), который согласно таблице Ascii интерпретируется стандартными устройствами ввода-вывода как Backspace, и требует перемещения позиции вывода следующего символа на один символ влево (back space). Таким образом строка "A \b0B" при выводе на консольный экран или принтер будет отображаться как строка "A0B".

Таким образом, если задача состоит в получении нужной строки на символьно-ориентированом устройстве, решение об использовании формата "%1 \b0%2" может оказаться вполне оправданным. Естественно, нужно помнить о некоторых ограничениях, накладываемых данным решением.


Название: QString().arg() bug ?
Отправлено: L.Marvell от Март 30, 2006, 16:34
А разве без \b нельзя обойтись? Например так: QString( "%1'0'%2" ).arg( "A" ).arg( "B" );


Название: QString().arg() bug ?
Отправлено: Asaphus_Expansus от Март 30, 2006, 16:55
'\b' появился из необходимости иметь между 1 и 0 "невидимый" не цифровой символ, иначе 1 и 0 будут интерпретированы как число 10.

Ваш пример даст строку А'0'B, поскольку одинарные кавычки внутри двойных, суть обычный символ (с десятичным кодом 39 (0x27)) и он будет выводиться при печати.


Название: QString().arg() bug ?
Отправлено: L.Marvell от Март 30, 2006, 17:11
Да, действительно ошибочка вышла...


Название: QString().arg() bug ?
Отправлено: alex0303 от Март 30, 2006, 18:52
А такой вариант "%100%11"? :)


Название: QString().arg() bug ?
Отправлено: Asaphus_Expansus от Март 31, 2006, 09:21
Тоже вариант, работает, да.


Название: QString().arg() bug ?
Отправлено: Dendy от Март 31, 2006, 10:42
Результат отладки такого вьІражения:

Код:
QString s = QString( "%1 \b%2" );


Код:
s.d->data[0] == 37;
s.d->data[1] == 49;
s.d->data[2] == 32;
s.d->data[3] == 8;
s.d->data[4] == 37;
s.d->data[5] == 50;


Никакого удаления предьІдущего символа не произошло. Но даже если бьІ произошло, то в QString передалась бьІ строка с уже удалённьІм символом. Толку...

Ещё есть потенциально опасньІй момент, когда строка вида:

Код:
QString s = tr( "%1%2" );


переводится как:

Код:
QString( "%10%2" );


Я так понимаю, что такие неоднозначньІе моментьІ нужно переводить как:

Код:
QString( "%100%11" );


Но тогда будет путаница с индексами исходного текста-ключа и результирующего.

Думаю, самьІй правильньІй вариант теоретически должен бьІть такой:

Код:
QString s = QString( "%1%b0%2" ).arg( "A" ).arg( "B" );


%b - некий мной придуманьІй спец-символ для метода arg(). Когда етот метод находит минимальньІй индекс, которьІй нужно заменить, - он автоматически удаляет следующий за етим индексом %b.


Название: QString().arg() bug ?
Отправлено: nEoN от Март 31, 2006, 12:20
Вот ещё один вариант :
Код:
QString s = QString("%1%2%3").arg("A").arg("0").arg("B");