ФЕДЕРАЛЬНОЕ АГЕНТСТВО СВЯЗИ
ФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ БЮДЖЕТНОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ ВЫСШЕГО ОБРАЗОВАНИЯ
«САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ ТЕЛЕКОММУНИКАЦИЙ ИМ. ПРОФ. М.А. БОНЧ-БРУЕВИЧА»
(СПбГУТ)
Кафедра программной инженерии и вычислительной техники
Отчёт
по лабораторной работе №9 на тему: «Разработка кросс-платформенного приложения»
по дисциплине «Операционные системы»
Выполнил: студент группы ИКВТ-61, UКозырев А.Б.
« » 2018 г. ___________/А.Б. Козырев/
Принял: __к.т.н. Дагаев А.В.
« » 2018 г. ___________/_А.В. Дагаев/
Задание: разработать приложение с применением posix функций на кроссплатформенных языках программирования
Среда разработки приложения: Qt Creator 4.8.0
Разрабатываемое приложение основано на использовании Qt Widgets Application – среды для создания графического интерфейса.
Созданное приложение AppWidget управляет программой Euler.exe (исходный код и реализация в приложении)
Исходный код:
#include "appwidget.h"
#include "ui_appwidget.h"
#include <QProcess>
#include <QDebug>
#include <QStringList>
#include <QFile>
#include "windows.h"
QString method = "random";
QString algorithm = "normal";
AppWidget::AppWidget(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::AppWidget)
{
ui->setupUi(this);
}
AppWidget::~AppWidget()
{
delete ui;
}
void AppWidget::on_start_explicit_clicked()
{
QProcess process;
QString program = "C:\\EulerApp\\release\\Euler.exe";
process.setCreateProcessArgumentsModifier([] (QProcess::CreateProcessArguments *args)
{
args->flags |= CREATE_NEW_CONSOLE;
args->startupInfo->dwFlags &= ~STARTF_USESTDHANDLES;
});
process.start(program);
process.waitForFinished(-1);
process.close();
}
void AppWidget::on_choice_force_clicked(bool checked)
{
if (checked)
method = "random";
}
void AppWidget::on_choice_strategy_clicked(bool checked)
{
If (checked)
method = "strategy";
}
void AppWidget::on_choice_modified_clicked(bool checked)
{
If (checked)
algorithm = "modified";
}
void AppWidget::on_choice_normal_clicked(bool checked)
{
If (checked)
algorithm = "normal";
}
void AppWidget::on_start_inhibit_clicked()
{
QProcess process;
QString startingSquare = "no";
QString finalSquare = "no";
QStringList parameters;
QString inputStart = ui->start_square->text();
QString inputFinal = ui->final_square->text();
QString inputIterations = ui->repeat_count->text();
QString inputProbability = ui->given_probability->text();
if (inputStart.isEmpty() == FALSE)
startingSquare = "yes";
if (inputFinal.isEmpty() == FALSE)
finalSquare = "yes";
if (inputIterations.isEmpty() == TRUE)
inputIterations = "0";
if (inputProbability.isEmpty() == TRUE)
inputProbability = "0";
if (inputIterations.toInt() != 0 && ui->choice_iterate->isChecked())
{
inputProbability = "0";
ui->given_probability->clear();
}
else if (inputProbability.toDouble() != 0 && ui->choice_probability->isChecked())
{
inputIterations = "0";
ui->repeat_count->clear();
}
parameters << startingSquare << inputStart << finalSquare
<< inputFinal << method << algorithm << inputIterations << inputProbability;
QString program = "C:\\EulerApp\\release\\Euler.exe";
process.startDetached(program, parameters);
process.waitForFinished(-1);
process.close();
QFile inputFile("C:/EulerApp/release/report.txt");
if (!inputFile.open(QIODevice::ReadOnly))
{
qDebug() << "Ошибка открытия для чтения";
}
else
{
QTextStream in(&inputFile);
if (!in.atEnd() && ui->choice_iterate->isChecked())
{
QString line = in.readLine();
ui->result_probability->setText(line);
ui->result_count->clear();
inputFile.close();
}
else if (!in.atEnd() && ui->choice_probability->isChecked())
{
in.readLine();
QString line = in.readLine();
ui->result_count->setText(line);
ui->result_probability->clear();
inputFile.close();
}
}
}
void AppWidget::on_clear_button_clicked()
{
ui->start_square->clear();
ui->final_square->clear();
ui->repeat_count->clear();
ui->given_probability->clear();
ui->result_probability->clear();
ui->result_count->clear();
}
void AppWidget::on_choice_iterate_clicked(bool checked)
{
if (checked)
ui->given_probability->clear();
}
void AppWidget::on_choice_probability_clicked(bool checked)
{
if (checked)
ui->repeat_count->clear();
}
void AppWidget::on_close_window_clicked(bool checked)
{
if (checked)
this->close();
}
Для того, чтобы понять, как работает данное окно, следует обратиться к скриншоту:
В дизайнере формы окна выбирается каждый элемент, затем пишется код для организации его работы.
Предположим, пользователь нажимает на кнопку “DISPLAY APPLICATION”.
Тогда, управление переходит в тело слота on_start_explicit_clicked()
void AppWidget::on_start_explicit_clicked()
{
QProcess process;
QString program = "C:\\EulerApp\\release\\Euler.exe";
process.setCreateProcessArgumentsModifier([] (QProcess::CreateProcessArguments *args)
{
args->flags |= CREATE_NEW_CONSOLE;
args->startupInfo->dwFlags &= ~STARTF_USESTDHANDLES;
});
process.start(program);
process.waitForFinished(-1);
process.close();
}
, и выполняется следующая последовательность действий.
-
Создаётся новый процесс QProcess
-
Указывается путь к исполняемой программе (Euler.exe)
-
Вызывается модификатор аргументов нового процесса, который устанавливает дочерний процесс в самостоятельном окне
-
Запускается дочерний процесс в своём консольном окне
-
Родительский процесс ожидает завершения дочернего процесса (Euler.h)
-
Дочерний процесс закрывается ещё раз для надёжности
В результате этих действий получается следующий результат:
Мы видим, что дочерний процесс начал работу в своём окне, стандартный вывод изолирован. Процесс родитель (окно формы) зависает до окончания работы дочернего процесса.
Предположим, пользователь выбирает конечное поле, задаёт требуемую вероятность, настраивает алгоритм работы программы Euler.exe, а затем нажимает на кнопку «START»
Тогда, управление переходит в тело слота для кнопки «START», а именно:
void AppWidget::on_start_inhibit_clicked()
{
QProcess process;
QString startingSquare = "no";
QString finalSquare = "no";
QStringList parameters;
QString inputStart = ui->start_square->text();
QString inputFinal = ui->final_square->text();
QString inputIterations = ui->repeat_count->text();
QString inputProbability = ui->given_probability->text();
if (inputStart.isEmpty() == FALSE)
startingSquare = "yes";
if (inputFinal.isEmpty() == FALSE)
finalSquare = "yes";
if (inputIterations.isEmpty() == TRUE)
inputIterations = "0";
if (inputProbability.isEmpty() == TRUE)
inputProbability = "0";
if (inputIterations.toInt() != 0 && ui->choice_iterate->isChecked())
{
inputProbability = "0";
ui->given_probability->clear();
}
else if (inputProbability.toDouble() != 0 && ui->choice_probability->isChecked())
{
inputIterations = "0";
ui->repeat_count->clear();
}
parameters << startingSquare << inputStart << finalSquare
<< inputFinal << method << algorithm << inputIterations << inputProbability;
QString program = "C:\\EulerApp\\release\\Euler.exe";
process.startDetached(program, parameters);
process.waitForFinished(-1);
process.close();
QFile inputFile("C:/EulerApp/release/report.txt");
if (!inputFile.open(QIODevice::ReadOnly))
{
qDebug() << "Ошибка открытия для чтения";
}
else
{
QTextStream in(&inputFile);
if (!in.atEnd() && ui->choice_iterate->isChecked())
{
QString line = in.readLine();
ui->result_probability->setText(line);
ui->result_count->clear();
inputFile.close();
}
else if (!in.atEnd() && ui->choice_probability->isChecked())
{
in.readLine();
QString line = in.readLine();
ui->result_count->setText(line);
ui->result_probability->clear();
inputFile.close();
}
}
}
, и выполняется следующая последовательность действий:
-
Создаётся новый объект класса QProcess
-
Начальное поле и конечное поле инициализируются на значение “no”, потому что пользователь может просто не ввести ничего в форму.
-
Считываются все поля ввода через указатель на объекты формы Ui::AppWidget ui->[объект_формы]->text()
-
Проверяются условия нулевых строк, устанавливаются ограничения на нелегальные случаи ввода.
-
Создаётся список параметров для командной строки класса QString
-
Указывается путь к исполняемой программе (Euler.exe)
-
Запускается дочерний процесс в фоновом режиме с параметрами командной строки.
-
Родительский процесс ожидает завершения дочернего
-
Родительский процесс закрывает дочерний процесс и вмести с ним программу Euler.exe
-
Родительский процесс открывает файл с результатом вычислений (вероятность, количество циклов), теми результатами, которые записываются в самой программе Euler.exe
-
Родительский процесс начинает считывать результаты построчно через объект QTextStream in
-
После чтения строки, указатель ui публикует результат в требуемое поле главной формы.
-
Файл закрывается
В результате этих действий получается следующий результат:
Например, сколько нужно итераций для точности 0,9 если конечное поле а1?
Ответ: 49
Сколько нужно итераций для точности 0,99 , если конечно поле а1?
Ответ: 106
Какова вероятность того, что движок совершит полный маршрут заканчивая в поле с1, если количество итераций = 10000?
Ответ: 0,9672
Подробнее о программе Euler.exe в приложении.
При нажатии на кнопку “CLEAR” все поля очищаются от записей через указатель ui->[field_name]->clear();
При нажатии на кнопку “CLOSE” – основное окно AppWidget закрывается.
При нажатии на радио кнопку вызываются следующие слоты:
void AppWidget::on_choice_force_clicked(bool checked)
{
if (checked)
method = "random";
}
void AppWidget::on_choice_strategy_clicked(bool checked)
{
if (checked)
method = "strategy";
}
void AppWidget::on_choice_modified_clicked(bool checked)
{
if (checked)
algorithm = "modified";
}
void AppWidget::on_choice_normal_clicked(bool checked)
{
if (checked)
algorithm = "normal";
}
void AppWidget::on_choice_iterate_clicked(bool checked)
{
if (checked)
ui->given_probability->clear();
}
void AppWidget::on_choice_probability_clicked(bool checked)
{
if (checked)
ui->repeat_count->clear();
}
Все они нужны только для инициализации переменных method, algorithm и очищения содержимого полей.
Переменные method и algorithm передаются в командную строку, и они не могут быть нулевыми, иначе программа не сможет стартовать.