ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 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 помощи рекурсии, получены навыки в обработке иерархическими списков.



ПРИЛОЖЕНИЕ А

ИСХОДНЫЙ КОД ПРОГРАММЫ

Mainwindow.cpp:

#include "mainwindow.h"

#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 "mainwindow.h"

#include <QApplication>

#include <QLabel>


int main(int argc, char *argv[])

{

QApplication a(argc, argv);

MainWindow w;

w.show();

return a.exec();

}


Mainwindow.h:

#ifndef 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);

}

};