Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка_Курсовой 18_06_12.docx
Скачиваний:
14
Добавлен:
09.11.2019
Размер:
829 Кб
Скачать
    1. Нисходящее проектирование на класcах

Особенность нисходящего проектирования с классами заключается в том, что вначале необходимо определить требуемые классы с некоторыми очевидными членами класса (поля, свойства, методы и т.д.), которые в дальнейшем будут уточняться и детализироваться. В нашем случае можно выделить два класса: класс неориентированный граф (NеorGraf), в котором будут сосредоточены характеристики графа и методы его обработки, и класс курсовой проект (Kurs_Proekt), состоящий из двух графов, методов, обеспечивающих связь с внешним текстовым файлом, перепись с файла на экран и основного метода, в котором данные вводятся с файла либо с формы, затем вызываются методы построения характеристик графов, их сравнения и печать результатов сравнения. Ниже приведены начальные структуры этих классов.

Класс NeorGraf

{

Поля целое nv – количество вершин

целое mr - количество ребер

целое diametr – характеристика графа - диаметр

целое[,] MS – матрица смежности

Свойства public целое n – количество вершин

public целое m - количество ребер

Методы public NeorGraf():base(){}

}

Класс Kurs_Proekt

{

Поля NeorGraf gr1– первый граф

NeorGraf gr2– второй граф

String filename – внешнее имя текстового файла

StreamReader Potok-поток для считывания данных с

файла

Свойства

Методы public Kurs_Proekt ()

{

gr1 = new NeorGraf();

gr2 = new NeorGraf();

}

public void Sravnenie(bool fileEkran,OpenFileDialog

openFileDialog,NumericUpDown nUDn1,

NumericUpDown nUDm1,TextBox tBFO1,

NumericUpDown nUDn2,NumericUpDown nUDm2,

TextBox tBFO2)

{

//тело метода

}

}

Приступим к проектированию метода Sravnenie.

Для обработки ошибок будем использовать исключение.

public class MyExcept : ApplicationException

{

public MyExcept(string msg) : base(msg) { }

}

public void Sravnenie(bool fileEkran,OpenFileDialog

openFileDialog,NumericUpDown nUDn1, NumericUpDown nUDm1,TextBox tBFO1,NumericUpDown nUDn2,NumericUpDown nUDm2,TextBox tBFO2)

НАЧАЛО

try//контроль переписи с файла и ввода с экрана

{

ЕСЛИ(fileEkran)ТО //данные на файле

ЕСЛИ(неподключение к файлу и создание потока)ТО

//в условии подзадача(1.1)

Вывод("Файл не выбран! Повторите ввод");

Выход

КЕСЛИ

try//контроль переписи с файла

{

перепись 1-го графа с частичным контролем

из файла на экран; (1.2)

перепись 2-го графа с частичным контролем

из файла на экран;

}

// обработка исключений при переписи с файла

catch (MyExcept e)

{

//здесь исключение вновь создается с

уточнением места ошибки

throw new MyExcept(e.Message + " с файла");

}

КЕСЛИ

try//контроль ввода с экрана

{

Ввод с экрана 1-го графа с полным контролем и

построением матрицы смежности MS1 (1.3)

Ввод с экрана 2-го графа с полным контролем и

построением матрицы смежности MS2

}

// обработка исключений при вводе с экрана

catch (MyExcept e)

{

//здесь исключение вновь создается с уточнением

места ошибки

throw new MyExcept(e.Message + " с экрана");

}

}

//обработка всех исключений

catch (MyExcept e)

{

Вывод(e.Message);

Выход;

}

Расчет диаметра графа 1(1.4)

Расчет диаметра графа 2

ЕСЛИ (характеристики равны(1.5)) ТО

Вывод("Графы эквивалентны");

ИНАЧЕ

Вывод("Графы не эквивалентны");

КЕСЛИ

КОНЕЦ

Из текста алгоритма видно, что в нем имеется 5 подзадач (1.1) –(1.5).

Дальнейшее проектирование можно выполнять двумя способами, которые были описаны ранее. Продолжаем проектирование вторым способом. Первые две подзадачи (метода) включим в класс Kurs_Proekt, а остальные - в класс NeorGraf, так как они свяаны с созданием и обработкой графов.

Реализация заглушки метода (1.1) – это подключение к файлу и создание потока.

public bool ConectFile(OpenFileDialog openFileDialog1)

{

MessageBox.Show("Подключение к файлу и создание

потока");

//return true;

return false;

}

Оставляя один из операторов return, можно создать ситуацию ошибки подключения к файлу.

Реализация заглушки метода (1.2) - перепись графа с частичным контролем из файла на экран.

public void Move_Gr_fileToEcran(NumericUpDown nUDn, NumericUpDown nUDm,TextBox tBFO

{

MessageBox.Show("Выполняется перенос графа с файла на экран");

throw new MyExcept("В данных на файле ошибка");

}

Комментируя или оставляя оператор throw, можно создать ситуацию ошибки при переписи с файла.

Реализация заглушки метода (1.3) - ввод с экрана графа с полным контролем и построением матрицы смежности MS1.

public void Input_GrInEkran(NumericUpDown nUDn, NumericUpDown nUDm, TextBox tBFO)

{

MessageBox.Show ("Выполняется ввод графа с экрана и построение

матрицы смежности");

throw new MyExcept ("В данных на форме ошибка");

}

Аналогично комментируя или оставляя оператор throw, можно создать ситуацию ошибки при вводе с экрана.

Реализация заглушки метода (1.4) - расчет диаметра графа.

public void Diametr()

{

MessageBox.Show("Расчет диаметра графа");

diametr = 2;

}

Реализация метода (1.5) - характеристики равны.

public bool Equals(NorGraf obj)

{

if (this.diametr == obj.diametr)

return true;

else

return false;

}

Подставим реализованные заглушки в метод Sravnenie.

public void Sravnenie(bool fileEkran,OpenFileDialog

openFileDialog,NumericUpDown nUDn1, NumericUpDown nUDm1,TextBox tBFO1,NumericUpDown nUDn2,NumericUpDown nUDm2,TextBox tBFO2)

НАЧАЛО

try//контроль переписи с файла и ввода с экрана

{

ЕСЛИ(fileEkran)ТО //данные на файле

ЕСЛИ(!ConectFile(openFileDialog1)/*

неподключение к файлу и создание потока*/)ТО

Вывод("Файл не выбран! Повторите ввод");

Выход

КЕСЛИ

try//контроль переписи с файла

{

//перепись 1-го графа с частичным контролем

из файла на экран; (1.2)

Move_Gr_fileToEcran(nUDn1,nUDm1,tBFO1);

//перепись 2-го графа с частичным контролем

из файла на экран;

Move_Gr_fileToEcran(nUDn2,nUDm2,tBFO2);

}

// обработка исключений при переписи с файла

catch (MyExcept e)

{

//здесь исключение вновь создается с

уточнением места ошибки

throw new MyExcept(e.Message + " с файла");

}

КЕСЛИ

try//контроль ввода с экрана

{

//Ввод с экрана 1-го графа с полным контролем и

построением матрицы смежности MS1 (1.3)

gr1.Input_GrInEkran(nUDn1, nUDm1, tBFO1);

//Ввод с экрана 2-го графа с полным контролем и

построением матрицы смежности MS2

gr2.Input_GrInEkran(nUDn2, nUDm2, tBFO2);

}

// обработка исключений при вводе с экрана

catch (MyExcept e)

{

//здесь исключение вновь создается с уточнением

места ошибки

throw new MyExcept(e.Message + " с экрана");

}

}

//обработка всех исключений

catch (MyExcept e)

{

Вывод(e.Message);

Выход;

}

//Расчет диаметра графа 1(1.4)

gr1.Diametr();

//Расчет диаметра графа 2

gr2.Diametr();

ЕСЛИ (gr1.Equals(gr2)/*характер.равны(1.5)*/) ТО

Вывод("Графы эквивалентны");

ИНАЧЕ

Вывод("Графы не эквивалентны");

КЕСЛИ

КОНЕЦ

Записываем алгоритм Sravnenie на С# , создаем классы, включаем в классы методы и заглушки, вызываем метод Sravnenie и выполняем отладку.

public void Sravnenie(bool fileEkran,OpenFileDialog openFileDialog,NumericUpDown nUDn1, NumericUpDown nUDm1,TextBox tBFO1,NumericUpDown nUDn2,NumericUpDown nUDm2, TextBox tBFO2)

{

try//контроль переписи с файла и ввода с экрана

{

if (fileEkran)

{

if (!ConectFile(openFileDialog))//подключение к

файлу и создание потока (1.1)

{

MessageBox.Show("Файл не выбран! Повторите

ввод");

return;

}

try//контроль переписи с файла

{

//перепись 1-го графа с частичным контролем

из файла на экран; (1.2)

Move_Gr_fileToEcran(gr1.ng,nUDn1,nUDm1,tBFO1);

//перепись 2-го графа с частичным контролем

из файла на экран;

Move_Gr_fileToEcran(gr2.ng, nUDn2,nUDm2,tBFO2);

}

// обработка исключений при переписи с файла

catch (MyExcept e)

//здесь исключение вновь создается с уточнением

места ошибки

{

throw new MyExcept(e.Message + " с файла");

}

}

try//контроль ввода с экрана

{

//Ввод с экрана 1-го графа с полным контролем и

построением матрицы смежности MS1 (1.3)

gr1.Input_GrInEkran(nUDn1, nUDm1, tBFO1);

//Ввод с экрана 2-го графа с полным контролем и

построением матрицы смежности MS2

gr2.Input_GrInEkran(nUDn2, nUDm2, tBFO2);

}

// обработка исключений при вводе с экрана

catch (MyExcept e)

{

//здесь исключение вновь создается с уточнением

места ошибки

throw new MyExcept(e.Message + " с экрана");

}

}

//обработка всех исключений

catch (MyExcept e)

{

MessageBox.Show(e.Message);

return;

}

//Расчет диаметра графа 1(1.4)

gr1.Diametr();

//Расчет диаметра графа 2

gr2.Diametr();

if (gr1.Equals(gr2))//сравнение характеристик (1.5)

MessageBox.Show("Графы эквивалентны");

else

MessageBox.Show("Графы не эквивалентны")

}

Не забываем включить оператор создания экземпляра проекта

Kurs_Proekt KP = new Kurs_Proekt();

И в клике кнопки вызвать метод Sravnenie

KP.Sravnenie(radioButton1.Checked, openFileDialog1,nUDn1, nUDm1,

tBFO1,nUDn2, nUDm2, tBFO2);

Приступаем к проектированию подзадачи 1.1 - подключение к файлу и создание потока.

public bool ConectFile(OpenFileDialog openFileDialog1)

{

//Выбор файла и создание потока (1.1)

if(openFileDialog1.ShowDialog() == DialogResult.OK)

{

filename = openFileDialog1.FileName;

//создание потока и подсоединение к файлу

Potok = new StreamReader(filename);

return true;

}

else

return false;

}

Приступаем к проектированию подзадачи 1.2 - переписываем граф с файла на экран с частичным контролем.

public void Move_Gr_fileToEcran(NumericUpDown nUDn, NumericUpDown nUDm,TextBox tBFO)

НАЧАЛО

Перенос чисел n и m на форму в компоненты nUDn, nUDm.

Считываем строку с файла и преобразуем ее в вектор строк (vect)

В vect[0] будет n, а в vect[1] будет m (см. в спецификации размещение данных)

Выполняем контроль n и m и заносим их в компоненты nUDn и nUDm

Переносим FO на форму в компоненту tbFO ;

Считываем FO (может занимать несколько строк) с файла в строку S и преобразуем ее в вектор строк (vect), который переписываем в tbFO без контроля.

КОНЕЦ

В подзадаче 1.2 есть подзадачи, но они реализуются простыми средствами языка C#, без оформления их отдельными методами. Реализуем данную подзадачу на C#.

void Move_Gr_fileToEcran(int ng, NumericUpDown nUDn,

NumericUpDown nUDm,TextBox tBFO)

{

//Перенос чисел n и m на форму в компоненты

numericUpDown

//Считываем строку с файла и преобразуем ее в

вектор строк (veсt)

//В vect[0] будет n, а в vect[1] будет m (см.в

спецификации размещение данных)

char ch = ' ';

string str = Potok.ReadLine();

string[] vect = str.Split(ch);

int n, m;

try// контроль формата чисел

{

n = int.Parse(vect[0]);

m = int.Parse(vect[1]);

}

catch (FormatException e)

{

//добавим в класс графа поле целого типа ng,

//которое позволит уточнить, в каком графе ошибка

throw new MyExcept("В числах n или m

недопустимый символ в графе"+ ng.ToString());

}

//Выполняем контроль n и m и заносим их в

компоненты nUDn и nUDm

if ((n < 1) || (n > 20))

throw new MyExcept("Ошибка ввода количества вершин

графа " + ng.ToString());

nUDn.Value = n;

if ((m < 1) || (m > 50))

throw new MyExcept("Ошибка ввода количества ребер

графа " + ng.ToString());

nUDm.Value = m;

//Перенос FO на форму в компоненту tbFO

//Считываем FO(может занимать несколько строк) с

файла в строку S и преобразуем

// ее в вектор строк (vect), который переписываем

в tbFO без контроля

string strp = "";

while ((str = Potok.ReadLine()) != "")

strp += str;

vect = strp.Split(ch);

int k = vect.Length;

tBFO.Clear();

for (int i = 0; i < k - 1; i++)

tBFO.AppendText(vect[i] + "\r\n");

tBFO.AppendText(vect[k - 1]);

}

Методы 1.1 и 1.2 вставим вместо заглушек в класс Kurs_Proekt.

Приступаем к проектированию подзадачи 1.3 - ввод данных с экрана с контролем и построение матрицы смежности

Input_GrInEkran (NumericUpDown nUDn, NumericUpDown nUDm, TextBox tBFO)

НАЧАЛО

Считываем с экрана n, m;

n =(int) nUDn.Value;//преобразуем в целое, так как Value типа decimal

m = (int)nUDm.Value ;

Проверка количества элементов FO

int k=tBFO.Lines.Length;

ЕСЛИ k<> n+2*m ТО

throw new MyExcept("Количество элементов FO

неверно в графе " + ng.ToString());

КЕСЛИ

Считываем FO и строим матрицу смежности (1.3.1)

Контроль симметричности матрицы смежности (1.3.2)

КОНЕЦ

В данном алгоритме есть две подзадачи - (1.3.1) и (1.3.2). Реализуем их в виде методов с логическим типом.

Реализация подзадачи (1.3.1) - считывание FO и построение матрицы смежности.

bool CreatMS(TextBox tBFO)

{

// создаем и обнуляем матрицу смежности

MS =new int[n,n];

for (int i = 0; i < n; i++)

for (int j = 0; j < n; j++)

MS[I,j]=0;

int L = 0;//индекс строки в компоненте tBFO

for (int i = 0; i < n; i++) //по вершинам графа

{

try //контроль формата чисел

{

// считываем первую вершину, следующую за i

int j = int.Parse(tBFO.Lines[L]);

//контроль j

if ((j < 0) || (j > n))

throw new MyExcept("Элемент FO - неверный в

графе "+ng.ToString());

//считываем остальные вершины, следующие за i

while (j != 0)

{

MS[i, j - 1] = 1;

L++;

j = int.Parse(tBFO.Lines[L]);

//контроль j

if ((j < 0) || (j > n))

throw new MyExcept ("Элемент FO - неверный

в графе " + ng.ToString());

}

L++;

}

catch (FormatException e)

{

throw new MyExcept ("В элементе FO недопустимый

символ в графе "+ng.ToString());

}

}

return true;

}

Реализация подзадачи (1.3.2) - контроль симметричности матрицы смежности.

bool SimetrMS(ref string msg)

{

for (int i = 0; i < n; i++)

for (int j = i + 1; j < n; j++)

if (MS[i, j] != MS[j, i])

msg = msg + "[(" + i.ToString() + "," +

j.ToString()+")и("+j.ToString()+","+

i.ToString()+")]";

if (msg != "")

return false;

else

return true;

}

Подставим подзадачи 1.3.1, 1.3.2 в подзадачу 1.3.

Input_GrInEkran (NumericUpDown nUDn, NumericUpDown nUDm, TextBox tBFO)

НАЧАЛО

Считываем с экрана n, m;

n =(int) nUDn.Value;//преобразуем в целое, так как Value типа decimal

m = (int)nUDm.Value ;

Проверка количества элементов FO

int k=tBFO.Lines.Length;

ЕСЛИ k<> n+2*m ТО

throw new MyExcept("Количество элементов FO

неверно в графе " + ng.ToString());

КЕСЛИ

//Считываем FO и строим матрицу смежности(1.3.1)

CreatMS(TextBox tBFO)

//Контроль симметричности матрицы смежности(1.3.2)

string msg = "";

ЕСЛИ (!SimetrMS(ref msg))

throw new MyExcept("Проверьте ребра " + msg + " в

графе " + ng.ToString());

КЕСЛИ

КОНЕЦ

Запишем метод 1.3 на C# и включим все три метода в класс NeorGraf.

public void Input_GrInEkran(NumericUpDown nUDn, NumericUpDown nUDm, TextBox tBFO)

{

//Считываем с экрана n, m;

n = (int)nUDn.Value;//преобразуем в целое, так как

Value типа decimal

m = (int)nUDm.Value;

// Проверка количества элементов FO

int k = tBFO.Lines.Length;

if (k != n + 2 * m)

throw new MyExcept("Количество элементов FO

неверно в графе " + ng.ToString());

//Считываем FO и строим матрицу смежности (1.3.1)

CreatMS(tBFO);

//Контроль симметричности матрицы смежности (1.3.2)

string msg = "";

if (!SimetrMS(ref msg))

throw new MyExcept("Проверьте ребра " + msg + " в

графе " + ng.ToString());

}

Переходим к проектированию подзадачи 1.4 - расчёт радиуса графа.

int Diametr()

НАЧАЛО

int r=1 ;

int[,] MR=new int[n,n] ;

int[,] B1=new int[n,n]; 

int[,] B2=new int[n,n] ;

bool pr =true;

копировать матрицу MS в MR(1.4.1)

копировать матрицу MS в В1

ПОКА pr ЦИКЛ

Pr=false;

r=r+1 ;

Умножение матриц В2=В1*MS(1.4.2)

ДЛЯ i=1 ДО n ЦИКЛ

ДЛЯ j=1 ДО n ЦИКЛ

ЕСЛИ (MR[I,j]=0) и (B2[I,j]<>0 ) ТО

MR[I,j]=r;

Pr=true;

КЕСЛИ

КЦИКЛ

КЦИКЛ

копировать матрицу B2 в В1

КЦИКЛ

Возврат r-1

КОНЕЦ

В данном алгоритме есть две подзадачи (1.4.1 и 1.4.2). Реализуем их.

Подзадача 1.4.1 - копирование матрицы.

CopyMatr(int [,] A ,ref int [,] B)

НАЧАЛО

ДЛЯ i=1 ДО n ЦИКЛ

ДЛЯ j=1 ДО n ЦИКЛ

B[I,j]=A[I,j];

КЦИКЛ

КЦИКЛ

КОНЕЦ

Подзадача 1.4.2 - умножение матриц С=А*В

MulMatr(int [,] A , int [,] B,ref int[,]C)

НАЧАЛО

int S;

ДЛЯ i=1 ДО n ЦИКЛ

ДЛЯ j=1 ДО n ЦИКЛ

S=0;

ДЛЯkj=1 ДО n ЦИКЛ

S=S+A[I,k]*B[k,j]

КЦИКЛ

C[I,j]=S;

КЦИКЛ

КЦИКЛ

КОНЕЦ

Обе подзадачи запишем на языке C# и подставим в алгоритм 1.4.

public void CopyMatr(int [,] A ,ref int [,] B)

{

for(int i=0;i< n; i++)

for(int j=0;j< n; j++)

B[i,j]=A[i,j];

}

public void MulMatr(int [,] A , int [,] B,ref int[,]C)

{

int S;

for(int i=0;i< n; i++)

for(int j=0;j< n; j++)

{

S=0;

for(int k=0;k< n; k++)

S=S+A[i,k]*B[k,j]

C[i,j]=S;

}

}

int Diametr()

НАЧАЛО

int r=1 ;

int[,] MR=new int[n,n] ;

int[,] B1=new int[n,n]; 

int[,] B2=new int[n,n] ;

bool pr =true;

//копировать матрицу MS в MR (1.4.1)

CopyMatr(MS ,ref MR)

// копировать матрицу MS в В1

CopyMatr(MS ,ref B1 )

ПОКА pr ЦИКЛ

pr=false;

r=r+1 ;

// Умножение матриц В2=В1*MS (1.4.2)

MulMatr(B1 , MS, ref B2)

ДЛЯ i=1 ДО n ЦИКЛ

ДЛЯ j=1 ДО n ЦИКЛ

ЕСЛИ (MR[I,j]=0) и (B2[I,j]<>0 ) ТО

MR[I,j]=r;

Pr=true;

КЕСЛИ

КЦИКЛ

КЦИКЛ

//копировать матрицу B2 в В1

CopyMatr(B2 ,ref B1)

КЦИКЛ

Возврат r-1

КОНЕЦ

Запишем алгоритм на C# и подставим его вместо заглушки 1.4.

public int Diametr()

{

int r=1 ;

int[,] MR=new int[n,n] ;

int[,] B1=new int[n,n]; 

int[,] B2=new int[n,n] ;

bool pr =true;

//копировать матрицу MS в MR (1.4.1)

CopyMatr(MS ,ref MR);

// копировать матрицу MS в В1

CopyMatr(MS ,ref B1 );

while ( pr)

{

pr=false;

r=r+1 ;

// Умножение матриц В2=В1*MS (1.4.2)

MulMatr(B1 , MS, ref B2);

for(int i=0; i< n; i++)

for(int j=0; j< n; j++)

if( (MR[i,j]==0) && (B2[i,j]!=0 ))

{

MR[i,j]=r;

pr=true;

}

//копировать матрицу B2 в В1

CopyMatr(B2 ,ref B1);

}

return r-1;

}

Включим все три метода в класс NeorGraf.