Функции для работы со строками в qt. Qt: преобразование строки в число и числа в строку

Занимался я сегодня написанием некоторого демонстрационно-тестового приложения с использованием 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, поэтому и возникала, в моем случае, неприятная неправильная перекодировка.

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

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

В Qt для работы со строками есть мощный и специализированный класс - QString . Он имеет поддержку Unicode, возможность преобразования текста между разными кодировками и в обычные строки С и std::string . А также он имеет хорошее быстродействие и богатый набор инструментов для работы. Поддержка Unicode позволяет работать с текстом на любом языке мира, что очень важно при локализации графического интерфейса программы.

Рассмотрим методы работы с текстовыми строками в Qt . Перед началом работы с текстом в Qt нужно подключить файл описания QString :

#include

Как и почти для всех классов Qt , название класса совпадает с названием файла описания класса, который необходимо подключить с помощью директивы #include .

Существует большое количество разных способов добавления строк и символов к существующей строке:

QString lMainStr = " string "; // lMainStr == " string " lMainStr += " "; // lMainStr == " string " (lMainStr += " is ") += " "; // lMainStr == " string is " QString lHelperStr1 (" composed "); lMainStr += lHelperStr1; // lMainStr == " string is composed" QString lHelperStr2 = + " " +QString(" from ") + " "; lMainStr.append (lHelperStr2); // lMainStr == " string is composited from " lMainStr.push_back (" fragments "); // lMainStr == " string is composited from fragments " lMainStr.prepend (" This "); // lMainStr == "This string is composited from fragments " lMainStr.insert (lMainStr.length (), "."); // lMainStr == "This string is composited from fragments." lMainStr += QString(2, "."); // lMainStr == "This string is composited from fragments..." lMainStr= lMainStr.rightJustified (lMainStr.length () + 8, " "); // lMainStr=="This string is composited from fragments..."

Также есть возможность выделения части строки либо разделения её на части:

QString lQuote= "This is sentence one. This is sentence two. "; //Новая строка из пяти символов QString lFragment1 = lQuote.left (5); // lFragment1 == "This " qDebug () << " lFragment1 is: " << lFragment1; //Первое предложение: Все символы до первой точки QString lSentence= lQuote.section (".", 0, 0); qDebug () << " lSentenceis: " << lSentence; // lsentence == "This is sentence one" //Список слов в строке QStringList lWordsList = lSentence.split (" ", QString::SkipEmptyParts); qDebug () << lWordsList; // lWordsList == (" This ", " is ", " sentence ", "one ", "This " , // " is ", " sentence ", " two ")

Для проверки на пустую строку используют метод isEmpty() . Его не следует путать с методом isNull() , который возвращает значение true только для ещё не инициализированной строки. Например:

QString().isNull (); // true (нулевая строка) QString().isEmpty (); // true (нулевая строка тоже пустая) QString("").isNull (); // false (пустая строка не является нулевой) QString("").isEmpty (); // true QString("abc").isNull (); // false QString("abc").isEmpty (); // false

QString имеет инструменты для преобразования из std::string и наоборот. Например:

QString lQtstringInitial = " I am a standard STL string. "; std::string lStdstring = lQtstringInitial.toStdString (); QString lQtString = QString::fromStdString (lStdString);

Также QString имеет средства для работы с числовой информацией:

//преобразование целого числа в строку int x = 16; QString lXStr = QString::number (x); // x = 7; lXStr = 7 //преобразование строки в целое число int y = lXStr.toInt (); //преобразование дробного числа в строку double teta = 12099.10012021210102109991; QString lTetaStr = QString::number (teta); // lTetaStr == 12099.1 lTetaStr.setNum (teta); // lTetaStr == 12099.1 //вывод с 4-мя знаками после запятой lTetaStr = QString::number (teta, "f", 4); // lTetaStr == 12099.1001 //форматирование с использованием символа "e" lTetaStr = QString::number (teta, "e"); // lTetaStr == 1.209910e+04 //Запись числа в строку в разных системах счисления lXStr = QString("int %1 is %L2 in decimal system, %L3 in binary system, and % L4 in hexadecimal") .arg(x) .arg(x, 0, 10) .arg(x, 0, 2) .arg(x, 0, 16);

Для работы со списком строк в Qt предусмотрен специализированный тип QStringList. QStringList относят к контейнерным классам 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")

Класс QString предназначен для хранения и обработки строк (текста).

Самый простой способ инициализации объекта записывается как

QString str = "Hello";

QString str("Hello");

Для QString можно использовать операторы "+" и "+=". Это одни из примеров реализации принципа полиморфизма, т.е. одни и те же операторы (функции) могут обрабатывать данные разных типов. Такая возможность значительно упрощает работу для пользователя.

str += " World!";

Кроме того, имеется функция QString::append(), которая идентична по своему действию оператору "+=":

str.append(" World!");

Еще один способ "сборки" строки из других строк и чисел, а также ещё один пример полиморфизма – использование функции arg() за счёт использования управляющих символов:

str = "%1 %2 (%3s-%4s)";

str.arg("permissive").arg("society").arg(1950).arg(1970);

В этом примере символы "%1" будут заменены словом "permissive", "%2" – "society", "%3" – "1950" и "%4" – "1970". В результате получится строка "permissive society (1950s-1970s)". Класс имеет несколько перегруженных функций arg() для обработки различных типов данных. Некоторые из них имеют дополнительные параметры, управляющие длиной выходной строки, базой системы счисления и точностью представления чисел.

QString позволяет преобразовывать числа в их строковое представление, с помощью статической функции QString::number():

str = QString::number(59.6);

или с помощью QString::setNum():

str.setNum(59.6);

Обратное преобразование может быть выполнено функциями toInt(), toDouble() и т.д., например:

double d = str.toDouble(&ok);

Эти функции могут принимать необязательный аргумент типа bool, в котором возвращается признак успеха преобразования. Если преобразование не может быть выполнено, они возвращают 0.

Зачастую возникает ситуация, когда необходимо извлечь часть строки. Функция mid() возвращает подстроку заданной длины, начиная с заданной позиции в исходной строке. Например, следующий код выводит строку "pays":

QString str = "polluter pays principle";

qDebug() << str.mid(9, 4);

Если опустить второй аргумент (или передать в качестве второго аргумента число -1), функция вернет подстроку, начиная с заданной позиции и до конца исходной строки. Например, следующий код выведет строку "pays principle":

qDebug() << str.mid(9);

Дополнительно имеются функции left() и right(). Они обе принимают количество символов n и возвращают первые или последние n символов исходной строки, соответственно. Например, следующий код выведет строку "polluter principle":

qDebug() << str.left(8).ascii() << str.right(9) << endl;

Если нужно выполнить проверку – начинается ли или заканчивается ли строка определенной комбинацией символов, для этих целей существуют функции startsWith() и endsWith():

if (uri.startsWith("http:") && uri.endsWith(".png"))

Для строк определён оператор сравнения строк "==". Он чувствителен к регистру символов. Для выполнения регистронезависимого сравнения, можно воспользоваться функциями upper() или lower(), например:

if (fileName.lower() == "readme.txt")

Для замены одной подстроки в строке другой подстрокой, используйте функцию replace():

QString str = "a sunny day";

str.replace(2, 5, "cloudy");

в результате получится строка "a cloudy day". То же самое действие может выполнено с помощью функций remove() и insert():

str.remove(2, 5);

str.insert(2, "cloudy");

В первой строке удаляется пять символов, начиная со 2-й позиции, в результате получается строка "a day" (с двумя пробелами), затем, во второую позицию вставляется слово "cloudy". Существуют перегруженные версии функции replace(), которые заменяют все вхождения первого аргумента на второй. Например, чтобы заменить все символы "&" в строке на "&":

str.replace("&", "&");

Очень часто возникает необходимость выбросить из начала и конца строки все лишние пробельные символы (такие как: пробелы, символы табуляции, символы перевода строки). Для этой цели существует функция stripWhiteSpace():

QString str = " BOB \t THE \nDOG \n";

qDebug() << str.stripWhiteSpace();

Статьи по теме: