Теперь давайте рассмотрим из чего состоит проект Qt. В общем, проект Qt имеет такую структуру:
Ключевую роль имеет файл проекта с расширением .pro. Он содержит списки файлов: исходных кодов, файлов ресурсов, файлов локализации, форм, других файлов, которые входят в проект, а также файлов подпроектов, если проект состоит из нескольких частей. Этот файл также содержит некоторые настройки программы.
Теперь рассмотрим создание своего проектного файла. Создадим новую папку, где будет размещаться проект (например: custom_project). Создайте файл (это будет файл проекта) введите его имя с расширением .pro (например: custom_project.pro). Наш файл пока что пустой, но его уже можно открыть в Qt Creator (воспользуйтесь главным меню: File->Open File or Project...).
Создать пустой проект можно с помощью мастера построения проектов. Для этого надо воспользоваться главным меню File->New File or Project... либо комбинацией клавиш Ctrl+Shift+N. В окне мастера нужно выбрать раздел Other Project (Другой проект) и тип проекта — Empty Qt Project.
После того, как мы открыли проект, Qt Creator предлагает выбрать комплект для его компиляции. В разделе Projects (Проекты) выберем комплект по умолчанию и нажмём Configure Project. В дереве проекта выберем и откроем файл проекта. Теперь настало время исследовать синтаксис проектных файлов Qt.
Проектный файл обычно содержит несколько настроек в виде специальных переменных, каждая из которых играет свою особую роль. Среди большого количества настроек, которые задают в .pro-файле:
Откройте проектный файл и добавьте к нему содержимое. Обратите внимание: символ # можно использовать для обозначения комментариев.
# Указываем тип проекта TEMPLATE = app # app - Application, прикладная программа # Используемые модули Qt QT -= gui # Удаляем из списка модуль gui # это означает отказ от использования графического интрефейса, # то есть - консольную программу CONFIG += console # Конфигурируем создание консольного проекта # (нужно только для консольных проектов в Windows, в Linux и Mac OS X не выполняет никаких действий) CONFIG -= app_bundle # Предотвращает создание Application bundle в Mac OS X # (нужно только для консольных проектов в Mac OS X) TARGET = custom_project # Название исполняемого файла
Теперь нам осталось добавить в проект файл с текстом программы. Для этого мы снова можем воспользоваться мастером. В категории Files and Classes (Файлы и классы) выберем раздел C++ и выберем тип файла "C++ Source File" (Файл исходных текстов C++). Поскольку это будет главный файл программы, то дадим ему привычное для этого случая название: main.cpp. Текст программы является обычным:
int main ( int lArg c, char * lArgv [ ] )
{
return 0;
}
После создания main.cpp, вновь откроем файл проекта и обратим внимание на несколько дополнительных строк:
SOURCES += \ main.cpp
Переменная SOURCES хранит список .cpp файлов. В табл. 12.1 мы предоставляем список переменных, которые часто участвуют в описании проекта:
| Переменная | Описание | Пример |
|---|---|---|
CONFIG |
Разнообразные настройки конфигурации проекта (например: режим отладки, вывод предупреждений, компиляция динамической библиотеки и т.п.). | CONFIG += dll plugin \ warn_on release |
DEFINES |
Макроопределения в проекте. Работает так же, как директива препроцессора #define. | DEFINES += DEBUG_OUTPUT \ CUSTOM_DEFINE |
DESTDIR |
Путь к папке, где будет создан исполняемый файл. | DESTDIR = ./bin |
INCLUDEPATH |
Путь к папкам с заголовочными файлами | INCLUDEPATH += ./includes \ ./my_header_files |
FORMS |
Файлы форм Qt Designer. |
FORMS += mainwindow.ui |
HEADERS |
Заголовочные файлы программы *.h. |
HEADERS += mainwindow.h |
LIBS |
Пути к динамическим библиотекам и статическим библиотекам, которые используются в программе. | LIBS += -L./libs \ -L./my_libs \ -lmycustomlib |
QT |
Модули Qt, которые используются в программе. |
QT += core gui widgets \ network sql xml |
RESOURCES |
Файл ресурсов. | RESOURCES = resources.qrc |
SOURCES |
Исходные тексты программы *.cpp. |
SOURCES += main.cpp \ mainwindow.cpp |
TARGET |
Название исполняемого файла или динамической библиотеки. | TARGET = MyFirstProject |
TEMPLATE |
Тип проекта (приложение, библиотека, составленный из подпроектов ...) | TEMPLATE = lib |
Компиляция проекта проходит в два этапа. Сначала выполняется предварительная обработка проекта с помощью программы qmake. Этот инструмент Qt несёт ответственность за весь процесс компиляции проекта. Он читает содержание проектного файла и генерирует необходимые промежуточные файлы (дополнительные файлы с исходным кодом и make-файлы для компиляции). Это необходимо для того, чтобы превратить все особые расширения Qt, которые были использованы в программе, в код на языке C++ и использовать дополнительные настройки для проекта, описанные в pro-файле. После этого проект готов к обработке компилятором. Вторым этапом является непосредственно процесс компиляции. Все эти действия выполняются автоматически в среде Qt Creator.
(рис 12.1) Процесс компиляции проекта
После успешной компиляции мы получаем исполняемый файл программы. Откройте папку проекта. Она будет содержать исполняемый файл и все промежуточные файлы, сгенерированные в процессе.
Таким образом, процессом построения проекта руководит .pro-файл. При наличии исходных текстов программы и при отсутствии .pro-файла, его можно сгенерировать. Для этого из командной строки необходимо перейти в папку, которая содержит исходные тексты программы и вызвать qmake с параметром --project. Этим приёмом удобно воспользоваться, чтобы сгенерировать файл проекта и использовать оболочку QtCreator для работы над программой (даже для обычных программ на C++ без Qt).
Раздел "Projects" (Проекты) содержит набор необходимых настроек для процесса компиляции и для настройки среды запуска проекта. Одной из таких настроек есть опция Shadow Build, которая позволяет включить режим при котором для промежуточных файлов, make-файлов и продуктов компиляции создаётся отдельная папка вне папки с исходным кодом проекта (настройки размещения для неё — в поле Build directory). Это позволяет построить и хранить одновременно несколько вариантов построенного проекта для различных инструментариев. Также это сохраняет папку с исходным кодом от засорения файлами, созданными в процессе построения проекта. При выключенном Shadow build промежуточные файлы и папка с построенной программой сохраняются в папке, которая содержит файл проекта.
Конечно, созданные промежуточные файлы не являются непосредственной частью проекта. Они были сгенерированы, и будут перезаписываться при необходимости во время компиляции. Поэтому не стоит добавлять их к pro-файлу или делать любые изменения в них. Также не стоит их добавлять в систему контроля версий, если её используют при разработке.
Иногда сгенерированные файлы вместе с объектными и make-файлами бывает необходимо удалить. Это необходимо делать перед тем как заархивировать проект для сохранения, поскольку сгенерированные файлы занимают довольно много места на диске по сравнению с объёмом исходного кода. Порой могут возникать проблемы с компиляцией, когда после значительных изменений в структуре программы промежуточные файлы не были достаточно хорошо заново сгенерированы. В таких случаях возникает необходимость очистить проект. Для этого выберите в главном меню Build->Clean Project (Сборка->Очистить проект). Это позволит удалить сгенерированные файлы, кроме скомпилированного исполняемого файла и make-файлов.
Для того, чтобы очистить проект полностью, необходимо изменить некоторые настройки. Откройте раздел Projects (Проекты) и в разделе Clean Steps (Этапы очистки) нажмите кнопку Details (Подробнее) и измените параметр Make arguments (Аргументы make) с clean на distclean (рис. 12.2).
(рис 12.2) Настройки очистки проекта
Снова очистите проект — все сгенерованные файлы, включительно с исполняемым файлом и make-файлами, будут удалены.
Несмотря на то, что Qt почти всегда рассматривают как инструментарий для создания программ с графическим интерфейсом, его также можно использовать и в таких программах, которые работают как фоновые процессы, а также в консольных проектах. Для нескольких следующих примеров мы будем использовать последний созданный нами в предыдущем разделе проект.
В таком консольном проекте можно использовать почти все привычные для Qt средства и классы. В следующих нескольких примерах мы рассмотрим работу с некоторыми важными типами Qt именно на примере консольного проекта. А пока что ограничимся только обзором средства, которое позволяет выводить в консоль сообщения и разнообразную информацию для отладки в процессе работы программы.
Для вывода информации в консольном проекте можно использовать все привычные средства стандартной библиотеки C++. Но в Qt для этого есть удобный инструмент — функция qDebug(). Рассмотрим пример её использования:
#include <QDebug>
//Собственный тип данных — структура для комплексных чисел
struct complex
{
double re;
double im;
};
//Определение потокового оператора для поддержки вывода собственного типа
//complex с помощью qDebug()
QDebug operator<<(QDebug dbg, const complex c )
{
dbg.nospace ( ) << " ( " << c.re << " + i * " << c.im << " ) ";
return dbg.space ( );
}
int main ( int lArg c, char * lArgv [ ] )
{
//Вывод разнообразных типов данных
qDebug ( ) << " Hello, " << " this is debug output ";
qDebug ( ) << " Integer values : " << 1 << 10 << 100;
qDebug ( ) <<" Doubles and floats : "<<.1 << .123 << 0.112345;
qDebug ( ) << " Characters : " << " c " << " \ t " << " $ " << " \ n " << " newline ";
qDebug ( ) << " Booleans : " << true << false;
qDebug ( ) << " Pointers : " << lArgv;
qDebug ( ) << " and much more...";
//Вывод собственного типа данных
complex c;
c.re = 0.2;
c.im = 1.5;
qDebug ( ) << " including custom types : " << c;
return 0;
}
После выполнения программы в консоли увидим текст:
Hello, this is debug output Integer values: 1 10 100 Doubles and floats: 0.1 0.123 0.112345 Characters: c $ newline Booleans: true false Pointers: 0x3278fc8 and much more... including custom types: (0.2 + i*1.5)
Кроме qDebug() существуют другие функции для вывода сообщений разного уровня. Описание и примеры этих функций рассмотрим в табл. 12.2.
| Функция | Описание | Особенности | Пример |
|---|---|---|---|
qDebug() |
Вывод сообщений для отладки, разнообразной информации при работе программы. | Сообщения могут быть выключены с помощью специального макроопределения QT_NO_DEBUG_OUTPUT например, в файле проекта:
DEFINES += QT_NO_DEBUG_OUTPUT |
int error_num = 59; std::string error_string ( "uknown error" ); qDebug ( " result : % d , description : % s " , error_num, error_string . c_str ( ) ); __________________ #include <QDebug> ... qDebug ( )<<" result : "" << error_num <<" , description : " << error_string.c_str ( ); |
qWarning() |
Вывод сообщений при работе программы. | Сообщения могут быть выключены с помощью специального макроопределения QT_NO_WARNING_OUTPUT
например, в файле проекта:
DEFINES += QT_NO_WARNING_OUTPUT |
qWarning ( " warning : % d , description : % s " , error_num, error_string .c_str ( ) ); __________________ #include <QDebug> ... qWarning ( )<<" warning : " <<error_num <<" , description : " << error_string.c_str ( ); |
qCritical() |
Вывод сообщений о критических ошибках. | qCritical ( " critical error : % d, description :% s " , error_num, error_string .c_str ( ) ); __________________ #include <QDebug> ... qCritical ( )<<" critical error : " <<error_num <<", description : " << error_string.c_str ( ); |
|
qFatal() |
Вывод сообщений о фатальных для программы ошибках | После вывода сообщения происходит аварийное завершение работы программы | qFatal ( " fatal error : % d , description :% s " , error_num, error_string .c_str ( ) ); |
Обычные строки С довольно просты в использовании, но работать с ними не очень удобно в ряде случаев. Один из них, это поддержка выбора кодировок для текста. Ведь, как известно, существует много разных стандартов кодирования символов текста, которые отличаются поддержкой разного диапазона кодируемых символов.
В Qt для работы со строками есть мощный и специализированный класс — QString. Он имеет поддержку Unicode, возможность преобразования текста между разными кодировками и в обычные строки С и std::string. А также он имеет хорошее быстродействие и богатый набор инструментов для работы. Поддержка Unicode позволяет работать с текстом на любом языке мира, что очень важно при локализации графического интерфейса программы.
Рассмотрим методы работы с текстовыми строками в Qt. Перед началом работы с текстом в Qt нужно подключить файл описания QString:
#include <QString>
Как и почти для всех классов 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. Подробнее классы-контейнеры мы рассмотрим в следующем параграфе.
Список строк QStringList, который мы рассматривали, является представителем семейства контейнерных классов Qt, которые являются аналогом контейнеров STL. Но в то же время они имеют свои собственные различия в реализации и возможностях. Мы же будем в дальнейшем использовать в наших примерах исключительно контейнеры Qt.
Простейшим контейнерным классом является QList. QList — список общего назначения. Для добавления элементов в начало и в конец списка используют методы prepend() и append(). Также можно добавить несколько элементов за раз используя потоковые операторы. Например:
#include <QList>
...
QList<QString> lList;
QString lStr1 ( " string 1 " );
QString lStr2 ( " string 2 " );
lList << lStr1 << lStr2; //Добавляем несколько элементов за раз
lList.prepend ( lStr1 ); //Добавляем элемент в начало (повторно)
lList.append ( " string 3 " ); //Добавляем в конец списка
lList << " string 4 "; //То же, что и lList.append (" string 4 ");
Последние две строки возможны за счёт неявного преобразования char* в QString. Класс QStringList, которого мы коснулись в примерах предыдущего раздела посвящённого текстовым строкам, наследует от QList<QString> и реализует ряд дополнительных методов для работы со строками в списке.
Для доступа к элементам используют метод at(), который принимает индекс элемента в списке в качестве аргумента. Количество элементов в списке возвращают методы size() и count().
qDebug ( ) << lList.first ( ); qDebug ( ) << lList.last ( ); if ( lList.size ( ) >3) qDebug ( ) << lList.at ( 3 );
Также стоит отметить два других важных разновидности контейнеров: хэш (QHash) и словарь (QMap). Хэш — контейнер, в котором элементы добавляют парами (ключ-значение). Значение в хэше находят по ключу, а для поиска используют хэш-функцию, которая преобразует ключ в значение. В словаре элементы также добавляют парами ключ-значение, но значение сортируют по ключу. Для доступа к значению, используют метод value(), который принимает два параметра: ключ и значение по умолчанию, которое метод вернёт, если значение не будет найдено. Например:
#include <QMap> ... QMap<QString, QString> lSurnameByName; lSurnameByName.insert ( " Bill ", " Hunter " ); lSurnameByName.insert ( " Marry ", " Lee " ); //Поиск значения по ключу qDebug ( ) << " Bill " << lSurnameByName.value ( " Bill " ); qDebug ( ) << " Marry " << lSurnameByName.value ( " Marry ", " Doe " ); //Прибавляем другое значение с уже существующим ключом lSurnameByName.insert ( " Marry ", " Hunter " ); qDebug ( ) << " Marry " << lSurnameByName.value ( " Marry " ); //Ключи не существуют — вывод значений по умолчанию qDebug ( ) << " James " << lSurnameByName.value ( " James " ); qDebug ( ) << " John " << lSurnameByName.value ( " John ", " Doe " );
После выполнения получим вывод:
Bill "Hunter" Marry "Lee" Marry "Hunter" James "" John "Doe"
Обратите внимание: после того, как мы добавили ещё одно значение с тем же ключом (Marry), предыдущее значение было перезаписано новым значением. Для того, чтобы добавить несколько значений с одним и тем же ключом можно воспользоваться методом insertMulti().
#include <QHash> ... QHash<QString, QString> lClassificationHash; //Добавляем несколько значений с одинаковыми ключами lClassificationHash.insertMulti ( " fruits ", " apple " ); lClassificationHash.insertMulti ( " fruits ", " orange " ); lClassificationHash.insertMulti ( " vegetables ", " potato " ); lClassificationHash.insertMulti ( " vegetables ", " cabbage " ); lClassificationHash.insertMulti ( " vegetables ", " tomato " ); qDebug ( )<< lClassificationHash.value ( " fruits " ); //Вывод одного значения с ключом qDebug ( )<< lClassificationHash.values ( " fruits " ); //Вывод значений с ключом qDebug ( )<< lClassificationHash.values ( " vegetables " );
Получим следующий вывод в консоль:
"orange"
("orange", "apple")
("tomato", "cabbage", "potato")
Для итерации по списку можно воспользоваться макросом foreach. Также можно воспользоваться итератором в стиле Java. Например:
QList<int> lList; //Создаём список целых чисел
lList.append ( 3 ); //Добавляем элементы
lList.append ( 6 );
lList.append ( 9 );
QListIterator <int> lIt ( lList ); //Создаём итератор для списка
while ( lIt.hasNext ( ) ) //Пока следующий элемент существует
{
qDebug ( ) << lIt.next ( ); //...вывести следующий элемент
}
Другой пример — итерация в обратном направлении. На этот раз используем хеш.
QHash<QString, int> lNumberByName;
lNumberByName.insert ( " twelve ", 12 );
lNumberByName.insert ( " thirty three ", 33 );
lNumberByName.insert ( " one hundred an twenty five ", 125 );
QHash It erator<QString, int> lHashIterator ( lNumberByName );
lHashIterator.toBack ( ); //Перейти к концу контейнера — итератор указывает после
//последнего элемента
while ( lHashIterator.hasPrevious ( ) )
{
lHashIterator.previous ( ); //Переходим к предыдущемму элементу
//Выводим ключ и значение
qDebug ( ) << lHashIterator.key ( )<< " - " << lHashIterator.value ( );
}
Следующий пример — с итератором в стиле STL.
QHash<QString, int >::const_iterator lStlLikeIterator;
for ( lStlLikeIterator = lNumberByName.begin ( );
lStlLikeIterator != lNumberByName.end ( );
lStlLikeIterator ++)
{
qDebug ( ) << lStlLikeIterator.key ( )<< " - "
//Тоже самое, что и * lStlLikeIterator
<< lStlLikeIterator.value ( );
}
| Переменная | Описание особенностей |
|---|---|
QList |
Список общего назначения для использования в большинстве ситуаций, которые возникают при разработке. Имеет оптимальное быстродействие в большинстве случаев. |
QLinkedList |
Реализует связный список в Qt. Отсутствует операция доступа по индексу элемента (такая как at(int pos)). |
QVector |
Реализует вектор элементов в Qt. |
QStack |
Реализует стек. Стек размещает элементы по принципу LIFO (Last In, First Out) — элемент, добавленный первым будет последним элементом в стеке. |
QQueue |
Реализует очередь. Очередь размещает элементы по принципу FIFO (First In, First Out) — элемент, добавленный первым, будет первым элементом в очереди |
QSet |
Множество элементов. Гарантирует, что все элементы будут уникальными. |
QMap |
Контейнерный класс для словаря. Элементы добавляют парами: ключ-значение. Словарь всегда сортирует элементы по ключу. Позволяет найти элемент по ключу. |
QMultiMap |
Контейнерный класс словаря создан для удобной работы с тем, чтобы каждому ключу соответствовало несколько значений. Метод insert() не заменяет значение ключа, если ключ уже существует, а добавляет новую пару ключ-значение. |
QHash |
Контейнерный класс для хеша. Элементы добавляют парами: ключ — значение. Элементы хранятся в хеше в произвольном порядке. Позволяет выполнять очень быстрый поиск элемента по ключу. |
QMultiHash |
Контейнерный класс хеша, создан для удобной работы с тем, чтобы каждому ключу соответствовало несколько значений. Метод insert() не заменяет значение ключа, если ключ уже существует, а добавляет новую пару ключ-значение. |
Инструментарий Qt содержит большое количество средств, которые позволяют разработчику абстрагироваться от деталей реализации на той или иной программной платформе. В этом разделе мы рассмотрим средства, Qt предоставляет для работы с файловой системой.
Все устройства ввода/вывода в Qt наследуют от абстрактного класса QIODevice. Среди его потомков: буфер для данных (QBuffer), процесс — программа которая выполняется в системе (QProcess), сетевой сокет (QAbstractSocket) и другие. Мы же подробно рассмотрим работу с другим его потомком — классом для работы с файлом (QFile).
Для работы с файлом необходимо создать объект класса QFile и задать для него путь к файлу (абсолютный или относительный), с которым вы будете работать. Путь и имя передают как параметр конструктора или с помощью метода setFileName().
Далее файл необходимо открыть и задать режим доступа к нему. Метод open()принимает флаги доступа и возвращает true, если файл удалось открыть. Доступные флаги доступа:
QIODevice::ReadOnly — открыть для чтения;QIODevice::WriteOnly — открыть для записи;QIODevice::ReadWrite — открыть для чтения и записи;QIODevice::Append — все данные будут добавляться в конец файла (после уже существующих данных);QIODevice::Truncate — если возможно, стереть содержимое файла перед открытием;QIODevice::Text — режим работы с текстовым файлом (важно для текстовых файлов для корректной обработки символов завершения строки в Windows и Linux).Флаги (класс QFlags) часто используют в Qt для задания комбинации настроек. Для комбинации нескольких настроек, так же как и бинарной арифметике, используют операцию побитового OR.
Для записи и чтения используют методы read() и write(), которые перегружены в нескольких вариантах. Для чтения одной строки текстового файла используют метод readLine(). Для чтения всего содержимого можно воспользоваться методом readAll(). Текущую позицию при чтении из файла определяют с помощью метода pos(). Установить позицию можно с помощью метода seek(). Метод atEnd() позволяет определить достигли ли мы конца файла при чтении. После завершения работы с файлом его нужно закрыть вызовом метода close(). Следующий пример демонстрирует чтение текстового файла и вывод его в консоль.
#include <QDebug>
#include <QFile>
int main ( int arg c, char * argv [ ] )
{
const QString lFileName ( " file.txt " );
//Проверяем существование файла
if ( ! QFile::exists ( lFileName ) )
{
qCritical ( " File % s does not exists." ,
qPrintable ( lFileName ) );
return 1;
}
QFile lFile;
//Устанавливаем имя файла
lFile.setFileName ( lFileName );
//Открываем файл — текстовый, только для чтения
if ( ! lFile.open ( QIODevice::ReadOnly | QIODevice::Text ) )
{
//Если открыть файл не удалось — выводим сообщение об ошибке
qCritical ( " Error % d : % s.", lFile.error ( ) ,
qPrintable ( lFile.errorString ( ) ) );
return 2;
}
//Пока можно прочесть строку
while ( ! lFile.atEnd ( ) )
{
// ... выводить её в консоль
qDebug ( ) << lFile.readLine ( );
}
//Заканчиваем работу с файлом
lFile.close ( );
return 0;
}
Рассмотрим работу с файлами в Qt на другом примере записи и чтения текстовой информации. В этом примере мы используем класс QTextStream для получения введённой пользователем информации в стандартный поток ввода. Конструктор QTextStream может принимать в качестве параметра указатель на потомок QIODevicе, указатель на QString или QByteArray, а также файловую переменную. В примере мы перенаправляем поток ввода в QТextStream. Далее мы читаем строку из потока ввода и записываем её в файл.
#include <QDebug>
#include <QIODevice>
#include <QFile>
#include <QTextStream>
int main ( int lArg c, char * lArgv [ ] )
{
QTextStream in ( stdin );
QFile lFile ( " in.txt " );
if ( lFile.open ( QIODevice::WriteOnly | QIODevice::Truncate ) )
{
QString lData = in.readLine ( );
lFile.write ( qPrintable ( lData ) );
lFile.close ( );
}
else
{
qDebug ( ) << " Cannot open file ! ";
}
return 0;
}
В следующем фрагменте демонстрируем обратный процесс — чтение строки из файла и вывод прочитанного строки в консоль. Опять же для чтения из файла мы используем QTextStream.
QFile lFile ( " in.txt " );
if ( lFile.open ( QIODevice::ReadOnly | QIODevice::Truncate ) )
{
QTextStream in (lFile );
QString lData = in.readLine ( );
qDebug ( ) << lData;
lFile.close ( );
}
else
{
qDebug ( ) << " Cannot open file ! ";
}
Qt и скомпилируйте его. Определите потоковый оператор для вывода класса Person, который имеет поля Name, Phone number, Address для вывода в консоль с помощью функции qDebug().Qt. Используйте классы QFile, QTextStream для записи. Адрес текстового файла жёстко задайте в тексте программы.Qt и вывода значений в консоль. Используйте классы QFile, QTextStream для чтения. Адрес текстового файла жёстко задайте в тексте программы. Если файл невозможно открыть для чтения — выведите сообщение о критической ошибке с завершением работы программы.Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.