Структура проекта. Основные типы. QT: работаем со списком строк QStringList и стандартными контейнерами Tulip Сравнение строк qt

Преобразование числа в строку

QString & QString::setNum(int n, int base = 10)

Sets the string to the printed value of n in the specified base, and returns a reference to the string.

The base is 10 by default and must be between 2 and 36. For bases other than 10, n is treated as an unsigned integer.

QString str;

str.setNum(1234); // str == "1234"

The formatting always uses QLocale::C, i.e., English/UnitedStates. To get a localized string representation of a number, use QLocale::toString() with the appropriate locale.


Преобразование строки в целое число

int QString::toInt(bool * ok = 0, int base = 10) const

Returns the string converted to an int using base base, which is 10 by default and must be between 2 and 36, or 0. Returns 0 if the conversion fails.

If base is 0, the C language convention is used: If the string begins with "0x", base 16 is used; if the string begins with "0", base 8 is used; otherwise, base 10 is used.

The string conversion will always happen in the "C" locale. For locale dependent conversion use QLocale::toInt()

Example:

QString str = "FF";

bool ok;

int hex = str.toInt(&ok, 16); // hex == 255, ok == true

int dec = str.toInt(&ok, 10); // dec == 0, ok == false

Преобразование строки в вещественное число

float QString::toFloat(bool * ok = 0) const

Returns the string converted to a float value.

If a conversion error occurs, *ok is set to false; otherwise *ok is set to true. Returns 0.0 if the conversion fails.

The string conversion will always happen in the "C" locale. For locale dependent conversion use QLocale::toFloat()

Example:

QString str1 = "1234.56";

str1.toFloat(); // returns 1234.56

bool ok;

QString str2 = "R2D2";

str2.toFloat(&ok); // returns 0.0, sets ok to false

Преобразование строки в вещественное число двойной точности

double QString::toDouble(bool * ok = 0) const

Returns the string converted to a double value. Returns 0.0 if the conversion fails.

If a conversion error occurs, *ok is set to false; otherwise *ok is set to true.

QString str = "1234.56";

double val = str.toDouble(); // val == 1234.56

Various string formats for floating point numbers can be converted to double values:

bool ok;

double d;

d = QString("1234.56e-02").toDouble(&ok); // ok == true, d == 12.3456

The string conversion will always happen in the "C" locale. For locale dependent conversion use QLocale::toDouble()

d = QString("1234,56").toDouble(&ok); // ok == false

d = QString("1234.56").toDouble(&ok); // ok == true, d == 1234.56

For historic reasons, this function does not handle thousands group separators. If you need to convert such numbers, use QLocale::toDouble().

d = QString("1,234,567.89").toDouble(&ok); // ok == false

d = QString("1234567.89").toDouble(&ok); // ok == true

Число с ведущими нулями

Вот как можно создать строку с числом с ведущими нулями:

int temp = 1;

QString::number(temp).rightJustified(8, "0")

Для демонстрации того, что работа с другими контейнерами может быть организована аналогично, изменим только наполнение метода doFile() . В показанном ниже коде вводимые пользователем строки вида "ключ:значение", где "ключ" – целое число, а "значение" – строка, записываются в мультихэш (ассоциативный массив, в котором одному ключу может соответствовать несколько значений).

Полученный мультихэш выводится в консоль отладки. В реальной задаче после его формирования можно выполнять любые требуемые действия с данными, например, получить список всех значений, соответствующих ключу "0", мы можем так:

QList lst=hash.values(0);

Пример пользовательского ввода для формирования хэша:

1:345 1 2 3:44 1:567 1:789 string

И вывод в отладочной консоли QT для него:

Element: "1" Element: "1:345" Element: "1:567" Element: "1:789" Element: "2" Element: "3:44" Element: "string" Key= 0 Value= "1" Key= 1 Value= "2" Key= 1 Value= "789" Key= 1 Value= "567" Key= 1 Value= "345" Key= 2 Value= "string" Key= 3 Value= "44"

Вот изменённый метод doFile() , также длинным комментарием пояснено первое регулярное выражение:)

Void Widget::doFile(void) { QString String = this->textEdit->toPlainText(); QStringList list = String.split("\n"); list.removeDuplicates(); //Убрали дублирующие друг друга строки list.sort(Qt::CaseInsensitive);//Отсортировали с игнорированием регистра букв QRegExp regExp("^(?!\\s*$).+"); //^ (?! \\s * $) .+ //нач негативная разделитель ноль кон любой символ // проверка или более хотя бы один //Получается: //"если в строке есть хоть один символ - не надо разделителей слева от него" list = list.filter(regExp); //убрали строки только из разделителей list.replaceInStrings(QRegularExpression("\\s+")," "); //убрали лишние разделители между словами list.replaceInStrings(QRegularExpression("^\\s+|\\s+$"),""); //убрали лишние разделители в начале или конце строк //Пользовательская часть виджета QMultiHash hash; //Ключ - число, значения - строки QStringList::iterator it = list.begin(); int key=0; //Ключ для элементов, которым его не дал пользователь for (;it!=list.end();++it) { //Пройти по списку элементов "ключ:значение" QStringList item = (*it).split(":",QString::SkipEmptyParts); //разбить элемент по разделителю ":" if (item.size()<2) hash.insertMulti(key++,item.at(0)); else hash.insertMulti(item.at(0).toInt(),item.at(1)); //Добавили в хэш ключ (наш или заданный пользователем) и значение qDebug() << "Element: " << (*it); } //Вывести в консоль отладки мультихэш QMultiHash::iterator i = hash.begin(); for (;i!=hash.end();++i) qDebug() << "Key=" << i.key() << "Value=" << i.value(); //конец пользовательской части this->textEdit->clear(); this->textEdit->append(list.join("\n")); }

Символьные строки

Основной способ представления символьных строк в С++ заключается в применении массива символов char, завершаемого нулевым байтом ("\0"). Следующие четыре функции демонстрируют работу таких строк:

01 void hello1()

03 const char str = {

04 "H", "e", "l", "l", "o", " ", "w", "o", "r" "l", "d", "\0"

08 void hello2()

10 const char str = "Hello world!";

13 void hello3()

17 void hello4()

19 const char *str = "Hello world!";

В первой функции строка объявляется как массив и инициализируется посимвольно. Обратите внимание на символ в конце "\0", обозначающий конец строки. Вторая функция имеет аналогичное определение массива, но на этот раз для инициализации массива используется строковый литерал. В С++ строковые литералы - это просто массивы символов const char, завершающиеся символом "\0", который не указывается в литерале. В третьей функции строковый литерал используется непосредственно без придания ему имени. После перевода на инструкции машинного языка она будет идентична первым двум функциям.

Четвертая функция немного отличается, поскольку создает не только массив (без имени), но и переменную-указатель с именем str, в которой хранится адрес первого элемента массива. Несмотря на это, семантика данной функции идентична семантике предыдущих трех функций, и оптимизирующий компилятор удалит лишнюю переменную str.

Функции, принимающие в качестве аргументов строки С++, обычно объявляют их как char * или const char *. Ниже приводится короткая программа, иллюстрирующая оба подхода:

03 using namespace std;

04 void makeUppercase(char *str)

06 for (int i = 0; str[i] != "\0"; ++i)

07 str[i] = toupper(str[i]);

09 void writeLine(const char *str)

13 int main(int argc, char *argv)

15 for (int i = 1; i

16 makeUppercase(argv[i]);

17 writeLine(argv[i]);

В С++ тип char обычно занимает 8 бит. Это значит, что в массиве символов char легко можно хранить строки в кодировке ASCII, ISO 8859-1 (Latin-1) и в других 8-битовых кодировках, но нельзя хранить произвольные символы Unicode, если не прибегать к многобайтовым последовательностям. Qt предоставляет мощный класс QString, который хранит строки Unicode в виде последовательностей 16-битовых символов QChar и при их реализации использует оптимизацию неявного совмещения данных («копирование при записи»). Более подробно строки QString рассматриваются в главе 11 («Классы-контейнеры») и в главе 17 («Интернационализация»).

Занимался я сегодня написанием некоторого демонстрационно-тестового приложения с использованием Qt . Приложение это должно выполнять роль GUI-обертки над объектами некой специализированной библиотеки, которую я написал в boost для некоторой прикладной области.

Работа выполняется в Linux. Дистрибутив Ubuntu 11.10. Локаль - UTF-8.

И вот возникла у меня проблема. Средствами boost::system::error_code , в ядре моей библиотеки формировалось некоторое локализованное сообщение (т.е. на русском языке), которое мне понадобилось отобразить средствами Qt в экземпляре класса QTextEdit .

Вообще, надо бы давно запретить использование национальных языков в системных сообщениях. Однако, видимо, это кому-то кажется недемократичным, поэтому программисты ежедневно тысячами подрываются на этих проблемах и мы постоянно в готовых приложениях сталкиваемся с кракозябрами там, где могли бы прочитать нормальный английский текст. Ведь в чем проблема? Домохозяйки не удосуживаются читать даже сообщения прикладного уровня, и представить домохозяйку, которая поймет, что надо делать прочитав системное сообщение из сетевой подсистемы ядра типа "Адрес уже используется" на родном языке, мне кажется невероятным. А раз это не для домохозяйки, то зачем усложнять жизнь специалистам, которые все поголовно умеют читать по английски? К этому еще можно добавить проблему некорректных переводов. Понятно, вопрос риторический. Однако, хочется высказаться.

На самом деле проблемы я не понял и был крайне удивлен, когда преобразовав полученное сообщение из std::string в QString и выведя его потом в окно редактора я увидел кракозябры. Действительно. В чем может быть проблема? Если бы я, не дай бог, работал под Windows, то удивляться бы было не чему. Давно не интересовался как там дела сейчас, но во времена Windows XP меня веселило три одновременно используемые кодовые страницы в русских версиях операционной системы. Вот уж действительно, не операционная система а система заплаток. Но откуда могла взяться проблема в Linux? Если в ней, в используемой мной сборке, используется одна кодовая страница UTF-8 во всех подсистемах ядра и пользовательского пространства.

Проблема решется просто. Приведу ниже максимально подробный вариант решения с комментариями.

QTextCodec *codec = QTextCodec::codecForName("UTF8"); if (codec) { std::string str = boost_lib->getLastError(); // Get string from a boost library QByteArray ba(str.c_str()); // Convert to QByteArray QString msg = codec->toUnicode(ba); // Qt magic !!! m_pteLog->append(msg); // Append msg to a QTextEdit object }

В общем, заплатку я нашел, но в проблеме разбираться не стал. Видимо, по умолчанию, текст получаемый в Qt из строковых однобайтовых типов воспринимаются в кодировке Latin1, поэтому и возникала, в моем случае, неприятная неправильная перекодировка.

В заключении этой короткой заметки я бы хотел выразить надежду, что если кто-нибудь из читателей знает подробности затрагиваемого здесь механизма трансляции кодов символов, то пусть он его объяснит в комментариях или письмом мне, а я сделаю дополнение.