ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 19.03.2019
Просмотров: 214
Скачиваний: 1
МИНОБРНАУКИ РОССИИ
Санкт-Петербургский государственный
электротехнический университет
«ЛЭТИ» им. В. И. Ульянова (Ленина)
Кафедра МОЭВМ
отчёт
по лабораторной работе №2
по дисциплине «АиСД»
Тема: Иерархические списки
Студент гр. 3303 |
|
|
Преподаватель |
|
|
Санкт-Петербург
2018
Изучение иерархических списков и способов работы с ними.
Сравнить два иерархических списка на идентичность.
Коды всех функций, слотов, и описания структур находятся в Приложении А.
В файле hierarchical_list.h описаны структуры s_expr и two_ptr, которые вместе описывают структуру элементов списка: первая из них описывает структуру узла списка (union), вторая же хранит пару указателей на начало и конец данного списка. Также с помощью директивы typedef был задан синоним lisp для (s_expr *).
Затем были описаны функции работы со списком:
-
функция удаления списка destroy (lisp s);
-
функция head( const lisp s), возвращающая указатель на начало списка;
-
функция tail( const lisp s), возвращающая указатель на конец списка;
-
функция isNull(const lisp s), проверяющая, является ли список пустым;
-
функция cons(const lisp h, const lisp t), создающая точечную пару элементов (новый список из «головы» и «хвоста»).
Также были описаны функции работы с элементами списка:
-
функция make_atom(const char * x), создающая элемент списка, хранящий переданную в функцию строку;
-
функция isAtom(const lisp s), проверяющая, является ли элемент списка обычным узлом, а не началом другого списка.
-
функция concat(const lisp y, const lisp z), объединяющая два списка;
-
функции equal_lisp(const lisp x,const lisp y) и equal_seq(const lisp x,const lisp y) сравнивающие 2 списка;
-
функции read_seq( lisp & y, istringstream & streamIn ), read_s_expr(char * prev, lisp& y, istringstream & streamIn), read_lisp(lisp& y, istringstream & streamIn) для считывания списка в скобочной записи с входного потока.
Далее были описаны слоты – функции, вызываемые при нажатии определённых пунктов меню:
-
слот on_actionInfo_triggered() – вызывается при выборе в меню пункта «Info» и вызывает справку по программе;
-
слот on_actionAbout_Authour_triggered() – вызывается при выборе в меню пункта «Author» и вызвает справку об авторе;
-
слоты on_file_button_1_clicked и on_file_button_2_clicked – вызываются при нажатии на кнопку «файл» и загружают данные из заданного файла в текстовые поля;
-
слот on_equationButton_clicked – вызывается при нажатии на кнопку «Сравнить» и выполняет считывание списков из текстовых полей и производит их сравнение с последующим выводом.
Все вышеописанные функции являются методами или слотами базового класса главного окна QMainWindow и имеют свои прототипы в файле mainwindow.h.
Далее был описан класс HelpBrowser в файле helpbrowser.h, в котором содержится лишь описание конструктора, который в переданном по указателю виджете располагает кнопки для переключения между html страницами, и «соединяет» соответствующие сигналы со слотами.
Далее были созданы 5 html файлов, описывающих страницы для виджета HelpBrowser.
Само приложение
представляет из себя окно с двумя
текстовыми полями QTextEdit
и меню вверху окна. В текстовые поля с
подписями «1 список»
и «2 список»
пользователь может ввести строки,
представляющую из себя скобочныю записи
иерархических списков, или же загрузить
их в это же окно с помощью кнопок «Файл».
При нажатии на кнопку «Сравнить»
происходит сравнение файлов и вывод
результата. Также в верхнем меню есть
пункты Help и Author
для просмотра информации о всех функциях
программы, задании и её авторе
соответственно. При их выборе создастся
отдельное окно - QWidget.
На рисунках 1-4 приведены примеры работы программы.
Рисунок 1 – Пример работы программы
Рисунок 2 – Загрузка списка из файла
Рисунок 3 – Справка по программе
Рисунок 4 – Информация об авторе
Вывод:
С
помощью функций стандартных библиотек
c++
было осуществлено решение поставленной
задачи c
помощи рекурсии, получены навыки в
обработке иерархическими списков.
ПРИЛОЖЕНИЕ А
#include "ui_mainwindow.h"
#include "HelpBrowser.h"
#include <QMessageBox>
#include <iostream>
#include <sstream>
#include <cstdlib>
#include <fstream>
using namespace std ;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->textEdit_1->setText("\0");
ui->textEdit_1->setText("\0");
head_1 = NULL;
head_2 = NULL;
}
MainWindow::~MainWindow()
{
delete ui;
}
//работа с списком
void MainWindow::destroy (lisp s){
if (s != NULL){
if(!isAtom(s)){
destroy(head(s));
destroy(tail(s));
}
delete s;
}
}
lisp MainWindow::head(const lisp s){
if(s != NULL ){
if(!isAtom(s)){
return s->node.pair.hd;
}else{
QMessageBox::warning(this, "Error","Head(atom)");
exit(1);
}
}else{
QMessageBox::warning(this, "Error","Head(NULL)");
exit(1);
}
}
lisp MainWindow::tail(const lisp s){
if(s != NULL ){
if(!isAtom(s)){
return s->node.pair.tl;
}else{
QMessageBox::warning(this, "Error","Tail(atom)");
exit(1);
}
}else{
QMessageBox::warning(this, "Error","Tail(NULL)");
exit(1);
}
}
bool MainWindow::isNull(const lisp s){
return s == NULL;
}
lisp MainWindow::cons(const lisp h, const lisp t){
lisp p;
if (isAtom(t)){
QMessageBox::warning(this, "Error"," cons(*, atom)");
exit(1);
}else{
p = new s_expr;
if( p== NULL){
QMessageBox::warning(this, "Error"," Memory ...");
exit(1);
}
p->node.pair.hd = h;
p->node.pair.tl = t;
p->tag = false;
return p;
}
}
//работа с Atom
lisp MainWindow::make_atom(const char *x){
lisp s = new s_expr;
s->tag = true;
s->node.atom = new char[50];
strncpy(s->node.atom,x,50);
return s;
}
bool MainWindow::isAtom(const lisp s){
if(s == NULL) return false;
else return (s -> tag);
}
//считывание списка
void MainWindow::read_lisp(lisp &s, std::istringstream &in_stream){
char str[2];
if(in_stream.peek()=='\0'){
s=NULL;
return ;
}
while(in_stream.peek() == ' ')
in_stream.get();
in_stream.get(str[0]);
str[1]='\0';
read_s_expr(str,s,in_stream);
}
void MainWindow::read_s_expr(char *prev, lisp &s, std::istringstream &in_stream){
if(strcmp(prev, ")") == 0){
QMessageBox::warning(this, "Error","! List.Error 1");
return;
}else{
if(strcmp(prev, "(") != 0 ){
s = make_atom(prev);
}else{
read_seq(s,in_stream);
}
}
}
void MainWindow::read_seq(lisp &s, std::istringstream &in_stream){
char str[40] ="";
int i =0;
while(in_stream.peek() == ' ')
in_stream.get();
while(in_stream.peek() != ' ' && in_stream.peek() != ')'
&& in_stream.peek() != '(' && in_stream.peek() !='\n'){
in_stream.get(str[i]);
str[i+1]='\0';
i++;
}
if(strlen(str) == 0){
in_stream.get(str[i]);
str[i+1]='\0';
//i++;
}
lisp p1 = NULL,p2 =NULL;
if(strlen(str) == 0){
QMessageBox::warning(this, "Error","! List.Error 2");
return;
}else if(strcmp(str,")") == 0){
s = NULL;
}else{
read_s_expr(str,p1,in_stream);
read_seq(p2,in_stream);
s = cons(p1,p2);
}
}
//сравнение
bool MainWindow::equal_lisp(const lisp x,const lisp y){
bool sum = true;
if( isNull(x) || isNull(y) ) return false;
if(isAtom(x) && isAtom(y)){
if(strcmp(x->node.atom,y->node.atom) != 0) return false;
}else if(!isAtom(x) && !isAtom(y)){
sum = sum && equal_seq(x,y);
}else{
return false;
}
return sum;
}
bool MainWindow::equal_seq(const lisp x,const lisp y){
bool sum = true;
if (!isNull(x)&& !isNull(y)) {
sum = sum && equal_lisp(head(x),head(y));
sum = sum && equal_seq(tail(x),tail(y));
}else if(isNull(x) && isNull(y)){
return true;
}else{
return false;
}
return sum;
}
void MainWindow::on_equationButton_clicked(){
string str_1 = ui->textEdit_1->toPlainText().toLocal8Bit().data();
istringstream input_string_1(str_1);
string str_2 = ui->textEdit_2->toPlainText().toLocal8Bit().data();
istringstream input_string_2(str_2);
read_lisp(head_1,input_string_1);
read_lisp(head_2,input_string_2);
if(equal_lisp(head_1,head_2)){
QMessageBox::information(0, "Результат", "Списки идентичны");
}else{
QMessageBox::information(0, "Результат", "Списки различны");
}
}
void MainWindow::on_actionInfo_triggered()
{
HelpBrowser *helpBrowser = new HelpBrowser(":/", "index.htm");
helpBrowser->resize(400, 300);
helpBrowser->show();
}
void MainWindow::on_actionAbout_Authour_triggered()
{
HelpAuthor *helpAuthor = new HelpAuthor(":/", "author.htm");
helpAuthor->resize(300, 400);
helpAuthor->show();
}
void MainWindow::on_file_button_1_clicked()
{
QString patch_to_file = QFileDialog::getOpenFileName(this,"Open file", QDir::currentPath(),
"File with date (*.txt);;All files (*.*)");
if(patch_to_file.isEmpty()) return;
QFile file(patch_to_file);
QByteArray data;
if(!file.open(QIODevice::ReadOnly)) return;
data = file.readLine();
ui->textEdit_1->setText(data);
}
void MainWindow::on_file_button_2_clicked()
{
QString patch_to_file = QFileDialog::getOpenFileName(this,"Open file", QDir::currentPath(),
"File with date (*.txt);;All files (*.*)");
if(patch_to_file.isEmpty()) return;
QFile file(patch_to_file);
QByteArray data;
if(!file.open(QIODevice::ReadOnly)) return;
data = file.readLine();
ui->textEdit_2->setText(data);
}
Main.cpp:
#include <QApplication>
#include <QLabel>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
Mainwindow.h:
#define MAINWINDOW_H
#include <QMainWindow>
#include <hierarchical_list.h>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
lisp head(const lisp s);
lisp tail(const lisp s);
lisp cons(const lisp h, const lisp t);
lisp make_atom(const char * x);
bool isAtom(const lisp s);
bool isNull(const lisp s);
void destroy(lisp s);
// функции для считывания списка
void read_lisp(lisp& s, std::istringstream & in_stream );
void read_s_expr(char * prev, lisp & s, std::istringstream & in_stream);
void read_seq(lisp& s, std::istringstream & in_stream);
//для сравнения списков
bool equal_lisp(const lisp x,const lisp y);
bool equal_seq(const lisp x,const lisp y);
private slots:
void on_equationButton_clicked();
void on_actionInfo_triggered();
void on_actionAbout_Authour_triggered();
void on_file_button_1_clicked();
void on_file_button_2_clicked();
private:
Ui::MainWindow *ui;
lisp head_1;
lisp head_2;
};
#endif // MAINWINDOW_H
Helpbrowser.h:
#pragma once
#include <QtWidgets>
class HelpBrowser : public QWidget {
Q_OBJECT
public:
HelpBrowser(const QString& strPath,
const QString& strFileName,
QWidget* pwgt = 0
) : QWidget(pwgt)
{
setAttribute(Qt::WA_DeleteOnClose);
QPushButton* backButton = new QPushButton("<<");
QPushButton* homeButton = new QPushButton("Home");
QPushButton* nextButton = new QPushButton(">>");
QTextBrowser* textBrowser = new QTextBrowser;
connect(backButton , SIGNAL(clicked()),
textBrowser, SLOT(backward())
);
connect(homeButton, SIGNAL(clicked()),
textBrowser, SLOT(home())
);
connect(nextButton, SIGNAL(clicked()),
textBrowser, SLOT(forward())
);
connect(textBrowser, SIGNAL(backwardAvailable(bool)),
backButton , SLOT(setEnabled(bool))
);
connect(textBrowser, SIGNAL(forwardAvailable(bool)),
nextButton, SLOT(setEnabled(bool))
);
textBrowser->setSearchPaths(QStringList() << strPath);
textBrowser->setSource(QString(strFileName));
//Layout setup
QVBoxLayout* pvbxLayout = new QVBoxLayout;
QHBoxLayout* phbxLayout = new QHBoxLayout;
phbxLayout->addWidget(backButton );
phbxLayout->addWidget(homeButton);
phbxLayout->addWidget(nextButton);
pvbxLayout->addLayout(phbxLayout);
pvbxLayout->addWidget(textBrowser);
setLayout(pvbxLayout);
}
};
class HelpAuthor : public QWidget {
Q_OBJECT
public:
HelpAuthor(const QString& strPath,
const QString& strFileName,
QWidget* pwgt = 0
) : QWidget(pwgt)
{
setAttribute(Qt::WA_DeleteOnClose);
QTextBrowser* textBrowser = new QTextBrowser;
textBrowser->setSearchPaths(QStringList() << strPath);
textBrowser->setSource(QString(strFileName));
//Layout setup
QVBoxLayout* pvbxLayout = new QVBoxLayout;
QHBoxLayout* phbxLayout = new QHBoxLayout;
pvbxLayout->addLayout(phbxLayout);
pvbxLayout->addWidget(textBrowser);
setLayout(pvbxLayout);
}
};