РефератыОстальные рефератыСпСпецификация программы uWert > Текст программы uWert Доказательство корректности программы uWert Организация многооконного интерфейса и диалога в приложениях

Спецификация программы uWert > Текст программы uWert Доказательство корректности программы uWert Организация многооконного интерфейса и диалога в приложениях

Элементы технологии программирования


в примерах и упражнениях


Уче6ное пособие


А.П.Гагарин


2010г.



СОДЕРЖАНИЕ


Введение


1. Элементы объектно-ориентированного программирования


1.1. Определение класса и пользование его экземплярами


1.2. Наследование


1.3. Полиморфизм


1.4. Свойства и события (методы объекта, делегаты)


1.5. Класс классов


2. Организация типовых оконных приложений


2.1. Оконные приложения в IDE Delphi c библиотекой VCL


2.2. Приложение Windows Forms в Microsoft Visual Studio 2008 для среды CLR на языке C#


2.3. Приложение Windows Forms в Microsoft Visual Studio 2008 для среды CLR на языке C++


2.4. Приложение Windows Forms в Microsoft Visual Studio 2008 для среды Win32


3. Списки и таблицы


3.1. Прото-СУБД на основе класса TStringList и TStringGrid (библиотека VCL Delphi)


4. Разработка и верификация расчётных приложений


4.1. Спецификация программы uWert


4.2. Текст программы uWert


4.3. Доказательство корректности программы uWert


5. Организация многооконного интерфейса и диалога в приложениях


5.1. Многооконный интерфейс на основе сохраняемых форм


5.2. Диалог на основе динамически создаваемых форм


5.2.1. Проект диалоговой функции в Delphi


5.2.2. Проект диалоговой функции в Microsoft Visual Studio 2008 (CLR, язык C#)


5.2.3. Проект диалоговой функции в Microsoft Visual Studio 2008 (CLR, язык C++)


6. Проектирование классов


6.1. Основы модельно-ориентированного проектирования


6.2. Проект разработки компьютерной поддержки библиотеки


Приложения.


1. Синтаксис и семантика класса в языках Object Pascal, C#, C++, Java


2. Основы языка UML Введение



Данное учебное пособие сложилось в ходе преподавания технологий программирования студентам 2-го курса, то есть студентам, заведомо не имеющим заметного опыта и широкого кругозора в области программирования. Поэтому пособие преследует до известной степени разнородные цели: ознакомить со сквозным процессом разработки программ в духе современного Software Engineering, ввести в использование современных интегральных сред программирования и просто поучить разработке программ, уровень сложности алгоритмизации в которых превышает уровень обычных, преимущественно тривиальных примеров.


Первый раздел содержит примеры простейших приёмов объектно-ориентированного программирования, которые нужны для дальнейшего, но, как показывает опыт преподавания, усваиваются бывшими школьниками далеко не сразу.


Второй раздел «Организация типовых оконных приложений» позволяет с полным пониманием приступить к использованию интегральных сред программирования Borland Delphi и Microsoft Visual Studio и служит иллюстрацией масштабного применения объектно-ориентированного стиля программирования.


Третий раздел «Списки и таблицы» по замыслу должен помочь освоить важнейшие типы данных. В данной редакции пособия в этом разделе приведён пример использования класса TStrings. Этот пример позволяет подвести студентов к проблемам реализации реляционной модели данных в СУБД. Материал на ту же тему содержится и в пункте 6.2.4 раздела 6.


Четвёртый раздел «Разработка и верификация расчётных приложений» содержит программу вычисления значения регулярного арифметического выражения и верификацию её путём формального доказательства.


Пятый раздел «Организация многооконного интерфейса и диалога в приложениях» по содержанию и целям является развитием второго раздела.


Шестой раздел демонстрирует проектирование АСУ библиотеки по методике, в целом соответствующей методике Rational Unified Process (RUP). Для документирования проекта используется язык UML, разрабатываемый силами Object Management Group (OMG). Полный исходный текст проектируемой программы вряд ли когда-нибудь войдёт в пособие из-за своего объёма. Приведён лишь его фрагмент, иллюстрирующий одно из ключевых проектных решений.


Во всех разделах сформулированы упражнения, позволяющие практиковаться в проектировании, разработке и исследовании программ, отталкиваясь от приведённых примеров, то есть – на достаточно объёмном и сложном материале.


Школьные и вузовские образовательные программы по информатике в настоящее время устроены в своём большинстве так, что студенты вначале знакомятся с языком Pascal в версии Turbo, а затем – в объектной (Object) версии. Поэтому вполне актуально проводить обучение современным представителям семейства C-подобных языков, соотнося учебный материал по этим языкам со знаниями языка Pascal, которые, с большой вероятностью, имеются у учащихся. Соответственно, пособие содержит тексты на языках Object Pascal (Delphi), C++ и С# и побуждает упражняться в понимании, переработке и доработке этих текстов.


Характер изложения материала в каждом из разделов умышленно усложняется от начала к концу. Начальные части разделов легко доступны всем читателям, в том числе тем, кто знакомится с темой. Уровень изложения в конце разделов позволит быстро освоить их продвинутым читателям и составит полезную нагрузку для остальных.


1. ЭЛЕМЕНТЫ ОБЪЕКТНО-ОРИЕНТИРОВАННОГО ПРОГРАММИРОВАНИЯ


1.1. Определение класса и пользование его экземплярами


Пример консольного приложения IDE Delphi, в котором определён класс A как наследник класса TComponent:


program ClassTest01;


{$APPTYPE CONSOLE}


uses SysUtils, classes;


type A = class(TComponent)


public


f: extended;


procedure S;


constructor create(AOwner:TComponent);


end;


procedure A.S;


var x: integer;


function Fact(n: extended):extended;


begin


if n=1 then result:=1


else result:=n*Fact(n-1)


end;


begin


write('Proc S from class A calculates factorial of ');


read(x);


// f:=x;


// write('is '+FloatToStr(Fact(f));


write('is '+FloatToStr(Fact(x));


read(x)


end;


constructor A.create(AOwner:TComponent);


begin


inherited create(AOwner)


end;


var x: A;


begin


x:=A.create(nil);дол


x.S;


end.


Процедура S запрашивает число у оператора, вычисляет и выводит его факториал, как показано на следующем рисунке.



Если в методе используются только методы данного класса, она может быть вызвана от переменной x типа А без порождения экземпляра класса. Однако если использовать, например, поля, как показано в закомментаренных строках примера, тогда экземпляр класса должен быть создан вызовом конструктора класса.


1.2. Наследование


Если в программу ClassTest01, приведённую в п.1.1, ввести определение класса C, наследника класса A,


type C = class(A) constructor create(AOwner:TComponent); end;


то процедуру S можно вызвать от класса С:


var x: С;


begin x.S end.



Однако если в класс C ввести объявление метода с именем S,


type C = class(A)


procedure S;


constructor create(AOwner:TComponent);


end;


а в программу – соответствующее, например, такое определение:


procedure C.S;


var x: integer;


begin


writeln('Proc S from class C');


readln(x)


end;


то процедура C.S “экранирует” процедуру S класса A. При том же обращении к S будет вызвана процедура S из класса A:



1.3. Полиморфизм


Полиморфизм обеспечивается динамическим связыванием переменной с классом присвоенного ей объекта. В следующем примере ClassTest02:


program ClassTest02;


{$APPTYPE CONSOLE}


uses SysUtils, classes;


type A = class(TComponent)


procedure M; virtual;


constructor create(AOwner:TComponent);


end;


type C = class(A)


procedure M; override;


constructor create(AOwner:TComponent);


end;


procedure A.M;


var x: integer;


begin


writeln('Proc M from class A');


readln(x)


end;


constructor A.create(AOwner:TComponent);


begin inherited create(AOwner) end;


procedure C.M;


var x: integer;


begin


writeln('Proc M from class C');


read(x)


end;


constructor C.create(AOwner:TComponent);


begin


inherited create(AOwner)


end;


var x: A;z: C;


begin


x:=A.create(nil);


x.M;


z:=C.create(nil);


z.M;


x:=z;


x.M


end.


от переменной x вызывается метод M класса А, затем от переменной z M класса С, а после присвоения x значения (объекта) переменной z вызывается M класса C.



Полиморфизм процедуры M обеспечивается директивой virtual в классе A и директивой override в классе C.


1.4. Свойства и события (методы объекта, делегаты)


1.5. Класс классов


УПРАЖНЕНИЯ


1. Составить и выполнить аналогичные примеры в среде оконного приложения Borland Delphi.


2. Составить и выполнить аналогичные примеры в среде оконного приложения Microsoft Visual Studio 2008. 2. ОРГАНИЗАЦИЯ ТИПОВЫХ ОКОННЫХ ПРИЛОЖЕНИЙ


2.1. Оконные приложения в IDE Delphi c библиотекой VCL


Пример 1. Создание заготовки проекта.


1) запустите IDE Delphi.


Вы увидите пустую форму



2) нажмите функциональную клавишу F12.


Вы увидите текст модуля:


unit Unit1;


interface


uses


Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,


Dialogs;


type


TForm1 = class(TForm)


private


{ Private declarations }


public


{ Public declarations }


end;


var


Form1: TForm1;


implementation


{$R *.dfm}


end.


Этот модуль содержит объявление класса TForm1 - наследника класса Tform и глобальную переменную Form1 этого класса. Объявление класс TForm можно найти в модуле Forms, который связан с данным модулем в операторе uses.


3) вернитесь к графическому представлению формы, вновь нажав функциональную клавишу F12, наведите на неё курсор мыши и вызовите всплывающее меню нажатием правой клавиши; в этом меню активируйтеView
as
Text
. Вы увидите


object Form1: TForm1


Left = 192


Top = 107


Width = 591


Height = 483


Caption = 'Form1'


Color = clBtnFace


Font.Charset = DEFAULT_CHARSET


Font.Color = clWindowText


Font.Height = -11


Font.Name = 'MS Sans Serif'


Font.Style = []


OldCreateOrder = False


PixelsPerInch = 96


TextHeight = 13


end


Этот текст представляет свойства класса TForm1 и их значения, которые автоматически установлены в приложении. При сохранении проекта этот текст образует файл Unit1.dfm, в то время, как Unit1 образует файл Unit1.pas.


4) активируйте в главном меню Project – View Source
.


Вы увидите текст корневого сегмента программы


program Project1;


uses


Forms,


Unit1 in 'Unit1.pas' {Form1};


{$R *.res}


begin


Application.Initialize;


Application.CreateForm(TForm1, Form1);


Application.Run;


end.


Нетрудно заметить, что выполняются три метода класса TApplication, второй из которых создаёт экземпляр класса TForm1, определённый в модуле Unit1, и присваивает его там же определённой переменной Form1. Метод Run активирует окно, “скрывающееся ” в форме. Начало корневого сегмента служит точкой формы приложения. Поэтому рассмотренные предложения выполняются, если запустить приложение, например, нажатием функциональной клавиши F9. В результате будет создан экземпляр класса TForm1 и он будет показан на экране компьютера как форма.



То есть, заготовка, предоставляемая программисту при запуске IDE является корректным, работоспособным приложением (хотя практически бессодержательным), и пользователь приложения фактически работает с экземпляром определённого в приложении класса.


Пример 2.
Добавление в форму кнопки и обработка события от её нажатия.


1) перенесите с помощью мыши кнопку из палитры компонентов на форму:



При этом в модуле Unit1 в определение класса TForm1 будет автоматически включено поле (включённое предложение подчёркнуто):


unit Unit1;


interface


uses


Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,


Dialogs;


type


TForm1 = class(TForm)


Button1: TButton;


private


{ Private declarations }


public


{ Public declarations }


end;


var


Form1: TForm1;


implementation


{$R *.dfm}


end.


А в тексте, скрытом за формой (файл Unit1.dfm) появятся предложения, определяющие кнопку как объект и его свойства:


object Form1: TForm1


Left = 192


Top = 107


Width = 287


Height = 211


Caption = 'Form1'


Color = clBtnFace


Font.Charset = DEFAULT_CHARSET


Font.Color = clWindowText


Font.Height = -11


Font.Name = 'MS Sans Serif'


Font.Style = []


OldCreateOrder = False


PixelsPerInch = 96


TextHeight = 13


object Button1: TButton


Left = 64


Top = 72


Width = 75


Height = 25


Caption = 'Button1'


TabOrder = 0


end


end


2) дважды кликните по кнопке или по пустому полю строки Click в закладке “События” инспектора объектов (когда кнопка в фокусе!).


В результате в Unit1 в определение класса включается заголовок обработчика события


procedure Button1Click(Sender: TObject);


а в раздел implementation включается заготовка тела этого метода:


procedure TForm1.Button1Click(Sender: TObject);


begin



end;


end.


В текст файла Unit1.dfm, в описание кнопки добавляется строка


OnClick = Button1Click


После введения программистом в тело обработчика предложений, задающих требуемую обработку события, приложение может быть запущено. Например, после ввода предложения


ShowMessage(‘Привет!')


запуска приложения и нажатия на кнопку на форму выдаётся соответствующее сообщение:



УПРАЖНЕНИЯ


1. Добавьте в форму главное меню и обработайте события от активации его пунктов.


2.2. Приложение Windows Forms в Microsoft Visual Studio 2008 для среды CLR на языке C#


Пример 1. Создание заготовки проекта.


3) запустите IDE Visual Studio 2008,


4) активируйте в главном меню File
New
Application


При создании нового проекта этого типа Visual Studio 2008 автоматически создает заготовку проекта в виде директории с именем проекта, содержащей:


модуль имя_проекта
.csproj


модуль Form1.cs


модуль Form1.Designer.cs


модуль Program.cs


директория bin


директория obj


директория Properties.


В директории Properties содержатся модули: AssemblyInfo.cs, Resources.Designer.cs, Resources.resx, Settings.Designer.cs, Settings.settings.


В главном окне среды проектирования отображаются исходные тексты на языке C# (с расширением cs). Они отображаются либо автоматически при открытии проекта, либо могут быть выведены на экран с помощью главного меню Файл - Открыть – Файл … . Кроме того, в главном окне автоматически или по команде главного меню Вид-Конструктор показывается закладка Form1.cs[Конструктор], на которой представлен прототип главного окна (формы) проектируемого приложения.



Модуль Program.cs, содержит статический класс Program с методом main(). Этот метод является первым, который начинает выполняться при запуске проектируемого приложения.


Метод main() вызывает методы класса Application, определённого в пространстве имён System.Windows.Forms и содержащего, в частности, метод Run, запускающий обработку сообщений к окну. Окно (форма) создаётся тут же оператором new
как экземпляр класса Form1, который определён в модулях Form1.cs и Form1.Designer.cs проекта. Форма Form1 становится главной формой приложения.


Далее приведён текст модуля Program.cs для проекта CSprim


using System;


using System.Collections.Generic;


using System.Linq;


using System.Windows.Forms;


namespace CSprim


{


static class Program


{


/// <summary>


/// Главная точка входа для приложения.


/// </summary>


[STAThread]


static void Main()


{


Application.EnableVisualStyles();


Application.SetCompatibleTextRenderingDefault(false);


Application.Run(new Form1());


}


}}


Определение класса Form1 и содержащие его модули создаются автоматически при создании проекта. Класс разделён на две части, первая из которых, Form1.cs, содержит конструктор этого класса, вызывающий функцию InitializeComponent, которая определена в модуле Form1.Designer.cs.


Далее приведён текст модуля Form1.cs


using System;


using System.Collections.Generic;


using System.ComponentModel;


using System.Data;


using System.Drawing;


using System.Linq;


using System.Text;


using System.Windows.Forms;


namespace CSprim


{


public partial class Form1 : Form


{


public Form1()


{


InitializeComponent();


}


}


}


Модуль Form1.Designer.cs содержит:


определение поля components для коллекции компонентов, сопоставляемых с формой; эта коллекция определяется как пустая; тип поля – интрефейс Icontainer из пространства имён System.ComponentModel, объявляющий метод Dispose – расформирования коллекции и освобождение ресурсов, занятых её элементами;


определение функции Dispose, которая освобождает ресурсы компонентов, входящих в коллекцию поля components, и ресурсы самой формы; .


определение функции InitializeComponent, которая создает экземпляр класса Container (для компонентов) и присваивает его полю components, устанавливает шрифт для формы и её титульную надпись.


Модуль Модуль Form1.Designer.cs:


namespace CSprim


{


partial class Form1


{


/// <summary>


/// Требуется переменная конструктора.


/// </summary>


private System.ComponentModel.IContainer components = null;


/// <summary>


/// Освободить все используемые ресурсы.


/// </summary>


/// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>


protected override void Dispose(bool disposing)


{


if (disposing && (components != null))


{


components.Dispose();


}


base.Dispose(disposing);


}


#region Код, автоматически созданный конструктором форм Windows


/// <summary>


/// Обязательный метод для поддержки конструктора - не изменяйте


/// содержимое данного метода при помощи редактора кода.


/// </summary>


private void InitializeComponent()


{


this.components = new System.ComponentModel.Container();


this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;


this.Text = "Form1";


}


#endregion


}


}


Все эти построения осуществляются автоматически, заготовка приложения является корректным приложением, которое может быть запущено в режиме отладки в среде проектирования или независмо от среды отладки как модуль имя-проекта
.exe в директории Debug – поддиректории bin или obj директории проекта.


При запуске приложения метод main() создает экземпляр класса Form1, вызывая оператором new
его конструктор, а тот вызывает функцию InitializeComponent(), которая заполняет форму, присваивает форме и попавшим на неё компонентам заданные параметры и выводит её на экран. Метод Run активизирует очередь сообщений к форме как окну.


Пример 2. Добавление в форму кнопки и обработка события от её нажатия.


При разработке приложения на форму могут устанавливаться компоненты и вписываться обработчики событий, связанных с этитми компонентами. При этом в модуле Form1.cs автоматически формируются заготовки обработчиков событий, а в модуле Form1.Designer.cs – объявления компонентов как полей класса. В текст объявления функции InitalizeComponent(), также автоматически, вводятся предложения, обеспечивающие создания экземпляров компонентов формы при создании формы и присвоения им заданных значений свойств.


Далее приведён текст модулей Form1.cs и Form1.Designer.cs после установки на форме экранной кнопки. При этом Form1.cs[Конструктор] приобретает следующий вид.



Модуль Form1.cs:


using System;


using System.Collections.Generic;


using System.ComponentModel;


using System.Data;


using System.Drawing;


using System.Linq;


using System.Text;


using System.Windows.Forms;


namespace CSprim


{


public partial class Form1 : Form


{


public Form1()


{


InitializeComponent();


}


private void button1_Click(object sender, EventArgs e)


{


MessageBox
.Show("
Привет
"
);


}


}


}


Обработчик button_Click формируется автоматически, кроме подчёркнутой строки

MessageBox.Show("Привет");


которую вводит программист. В результате при нажатии на экранную кнопку на эуран выдаётся сообщение “Привет!”.


Модуль Form1.Designer.cs (в него автоматически введены подчёркнутые строки):


namespace CSprim


{


partial class Form1


{


/// <summary>


/// Требуется переменная конструктора.


/// </summary>


private System.ComponentModel.IContainer components = null;


/// <summary>


/// Освободить все используемые ресурсы.


/// </summary>


/// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>


protected override void Dispose(bool disposing)


{


if (disposing && (components != null))


{


components.Dispose();


}


base.Dispose(disposing);


}


#region Код, автоматически созданный конструктором форм Windows


/// <summary>


/// Обязательный метод для поддержки конструктора - не изменяйте


/// содержимое данного метода при помощи редактора кода.


/// </summary>


private void InitializeComponent()


{


this.button1 = new System.Windows.Forms.Button();


this.SuspendLayout();


//


// button1


//


this.button1.Location = new System.Drawing.Point(97, 94);


this.button1.Name = "button1";


this.button1.Size = new System.Drawing.Size(75, 23);


this.button1.TabIndex = 0;


this.button1.Text = "button1";


this.button1.UseVisualStyleBackColor = true;


this
.button1.Click += new System.EventHandler(this.button1_Click);


//


// Form1


//


this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);


this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;


this.ClientSize = new System.Drawing.Size(292, 273);


this.Controls.Add(this.button1);


this.Name = "Form1";


this.Text = "Form1";


this.ResumeLayout(false);


}


#endregion


private System.Windows.Forms.Button button1;


}


}


УПРАЖНЕНИЯ


1. Добавьте в форму главное меню и обработайте события от активации его пунктов.


2.3. Приложение Windows Forms в Microsoft Visual Studio 2008 для среды CLR на языке C++


2.4. Приложение Windows Forms в Microsoft Visual Studio 2008 для среды Win32


// CppWin0101.cpp: определяет точку входа для приложения.


//


#include "stdafx.h"


#include "CppWin0101.h"


#define MAX_LOADSTRING 100


// Глобальные переменные:


HINSTANCE hInst; // текущий экземпляр


TCHAR szTitle[MAX_LOADSTRING]; // Текст строки заголовка


TCHAR szWindowClass[MAX_LOADSTRING]; // имя класса главного окна


// Отправить объявления функций, включенных в этот модуль кода:


ATOM MyRegisterClass(HINSTANCE hInstance);


BOOL InitInstance(HINSTANCE, int);


LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);


INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);


int APIENTRY _tWinMain(HINSTANCE hInstance,


HINSTANCE hPrevInstance,


LPTSTR lpCmdLine,


int nCmdShow)


{


UNREFERENCED_PARAMETER(hPrevInstance);


UNREFERENCED_PARAMETER(lpCmdLine);


// TODO: разместите код здесь.


MSG msg;


HACCEL hAccelTable;


// Инициализация глобальных строк


LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);


LoadString(hInstance, IDC_CPPWIN0101, szWindowClass, MAX_LOADSTRING);


MyRegisterClass(hInstance);


// Выполнить инициализацию приложения:


if (!InitInstance (hInstance, nCmdShow))


{


return FALSE;


}


hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_CPPWIN0101));


// Цикл основного сообщения:


while (GetMessage(&msg, NULL, 0, 0))


{


if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))


{


TranslateMessage(&msg);


DispatchMessage(&msg);


}


}


return (int) msg.wParam;


}


//


// ФУНКЦИЯ: MyRegisterClass()


//


// НАЗНАЧЕНИЕ: регистрирует класс окна.


//


// КОММЕНТАРИИ:


//


// Эта функция и ее использование необходимы только в случае, если нужно, чтобы данный код


// был совместим с системами Win32, не имеющими функции RegisterClassEx'


// которая была добавлена в Windows 95. Вызов этой функции важен для того,


// чтобы приложение получило "качественные" мелкие значки и установило связь


// с ними.


//


ATOM MyRegisterClass(HINSTANCE hInstance)


{


WNDCLASSEX wcex;


wcex.cbSize = sizeof(WNDCLASSEX);


wcex.style = CS_HREDRAW | CS_VREDRAW;


wcex.lpfnWndProc = WndProc;


wcex.cbClsExtra = 0;


wcex.cbWndExtra = 0;


wcex.hInstance = hInstance;


wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_CPPWIN0101));


wcex.hCursor = LoadCursor(NULL, IDC_ARROW);


wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);


wcex.lpszMenuName = MAKEINTRESOURCE(IDC_CPPWIN0101);


wcex.lpszClassName = szWindowClass;


wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));


return RegisterClassEx(&wcex);


}


//


// ФУНКЦИЯ: InitInstance(HINSTANCE, int)


//


// НАЗНАЧЕНИЕ: сохраняет обработку экземпляра и создает главное окно.


//


// КОММЕНТАРИИ:


//


// В данной функции дескриптор экземпляра сохраняется в глобальной переменной, а также


// создается и выводится на экран главное окно программы.


//


BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)


{


HWND hWnd;


hInst = hInstance; // Сохранить дескриптор экземпляра в глобальной переменной


hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,


CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);


if (!hWnd)


{


return FALSE;


}


ShowWindow(hWnd, nCmdShow);


UpdateWindow(hWnd);


return TRUE;


}


//


// ФУНКЦИЯ: WndProc(HWND, UINT, WPARAM, LPARAM)


//


// НАЗНАЧЕНИЕ: обрабатывает сообщения в главном окне.


//


// WM_COMMAND - обработка меню приложения


// WM_PAINT -Закрасить главное окно


// WM_DESTROY - ввести сообщение о выходе и вернуться.


//


//


LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)


{


int wmId, wmEvent;


PAINTSTRUCT ps;


HDC hdc;


switch (message)


{


case WM_COMMAND:


wmId = LOWORD(wParam);


wmEvent = HIWORD(wParam);


// Разобрать выбор в меню:


switch (wmId)


{


case IDM_ABOUT:


DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);


break;


case IDM_EXIT:


DestroyWindow(hWnd);


break;


default:


return DefWindowProc(hWnd, message, wParam, lParam);


}


break;


case WM_PAINT:


hdc = BeginPaint(hWnd, &ps);


// TODO: добавьте любой код отрисовки...


EndPaint(hWnd, &ps);


break;


case WM_DESTROY:


PostQuitMessage(0);


break;


default:


return DefWindowProc(hWnd, message, wParam, lParam);


}


return 0;


}


// Обработчик сообщений для окна "О программе".


INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)


{


UNREFERENCED_PARAMETER(lParam);


switch (message)


{


case WM_INITDIALOG:


return (INT_PTR)TRUE;


case WM_COMMAND:


if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)


{


EndDialog(hDlg, LOWORD(wParam));


return (INT_PTR)TRUE;


}


break;


}


return (INT_PTR)FALSE;


}


УПРАЖНЕНИЯ


1. Добавьте в форму главное меню и обработайте события от активации его пунктов.


3. СПИСКИ И ТАБЛИЦЫ


3.1. Прото-СУБД на основе класса TStringList и TStringGrid (библиотека VCL Delphi)











unit Toy;


interface


uses


Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,


Dialogs, Grids, Menus;


type


TFToy = class(TForm)


Grid: TStringGrid;


MainMenu1: TMainMenu;


N1: TMenuItem;


N2: TMenuItem;


N3: TMenuItem;


N4: TMenuItem;


OpenDialog1: TOpenDialog;


SaveDialog1: TSaveDialog;


procedure FormCreate(Sender: TObject);


procedure N3Click(Sender: TObject);


procedure ListToGrid(l, g: integer);


procedure GridToList(g, l: integer);


procedure ShiftUp;


procedure ShiftDown;


procedure LoadGrid;


procedure N4Click(Sender: TObject);


procedure GridKeyDown(Sender: TObject; var Key: Word;


Shift: TShiftState);


private


{ Private declarations }


public


{ Public declarations }


end;


var


FToy: TFToy; sList1, sList2: TStringList; curl, curg: integer; vr:TGridRect;


implementation


{$R *.dfm}


uses math;


procedure TFToy.ShiftUp;


var i: integer;


begin


if Grid.RowCount>1then


for i:=2to Grid.RowCount-1 do


begin


Grid.cells[1,i-1]:=Grid.cells[1,i];


Grid.cells[2,i-1]:=Grid.cells[2,i]


end;


if sList1.Count-1=curl


then begin


Grid.cells[1,Grid.RowCount-1]:='';


Grid.cells[2,Grid.RowCount-1]:=''


end


else begin


Grid.cells[1,Grid.RowCount-1]:=sList1[curl+1];


Grid.cells[2,Grid.RowCount-1]:=sList2[curl+1]


end


end;


procedure TFToy.ShiftDown;


var i: integer;


begin


if Grid.RowCount>1


then begin


for i:=Grid.RowCount-2 downto 1 do


begin


Grid.cells[1,i+1]:=Grid.cells[1,i];


Grid.cells[2,i+1]:=Grid.cells[2,i]


end;


Grid.cells[1,i+1]:=sList1[curl-1];


Grid.cells[2,i+1]:=sList2[curl-1]


end


else begin


Grid.cells[1,1]:='';


Grid.cells[2,1]:=''


end


end;


procedure TFToy.GridToList(g, l: integer);


begin


if l>=sList1.Count


then begin


sList1.Add(Grid.cells[1,g]);


sList2.Add(Grid.cells[2,g])


end


else begin


sList1[l]:=Grid.cells[1,g];


sList2[l]:=Grid.cells[2,g]


end


end;


procedure TFToy.ListToGrid(l, g: integer);


begin


Grid.cells[1,g]:=sList1[l];


Grid.cells[2,g]:=sList2[l]


end;


procedure TFToy.LoadGrid;


var i: integer;


begin


if sList1.Count>0


then begin


for i:=1 to min(Grid.RowCount-1, sList1.Count)do


ListToGrid(sList1.Count-min(Grid.RowCount-1, sList1.Count)+i-1,i);


curl:=sList1.Count-1;


curg:=i-1


end


else begin


curl:=0;


curg:=1


end;


Grid.Cells[0,curg]:=' * ';


vr.left:=1;vr.right:=1; vr.Top:=curg; vr.bottom:=curg;


Grid.Selection:=vr


end;


procedure TFToy.FormCreate(Sender: TObject);


begin


sList1:=TStringList.Create;


sList2:=TStringList.Create;


OpenDialog1.Execute;


if not(OpenDialog1.FileName='')


then begin


sList1.LoadFromFile(OpenDialog1.FileName);


sList2.LoadFromFile(copy(OpenDialog1.FileName,1,length(OpenDialog1.FileName)-4)+'1.txt');;


LoadGrid


end


else begin


Grid.Cells[0,1]:=' * ';


curl:=0;


curg:=1


end


end;


procedure TFToy.N3Click(Sender: TObject);


begin


SaveDialog1.Execute;


if SaveDialog1.FileName=''


then showmessage('Имя файла не определено!')


else begin


sList1.SaveToFile(SaveDialog1.FileName);


sList2.SaveToFile(copy(SaveDialog1.FileName,1,length(SaveDialog1.FileName)-4)+'1.txt')


end


end;


procedure TFToy.N4Click(Sender: TObject);


begin


close


end;


procedure TFToy.GridKeyDown(Sender: TObject; var Key: Word;


Shift: TShiftState);


begin


if key=vk_Down


then begin


GridToList(curg, curl);


if curg=Grid.RowCount-1


then begin


ShiftUp;


curl:=curl+1


end


else begin


Grid.Cells[0,curg]:='';


curg:=curg+1;


Grid.Cells[0,curg]:=' * ';


curl:=curl+1


end;


vr.left:=1;vr.right:=1; vr.Top:=curg-1; vr.bottom:=curg-1;


Grid.Selection:=vr


end;


if key=vk_Up


then begin


GridToList(curg, curl);


if curg=1


then if curl>0


then begin


ShiftDown;


curl:=curl-1


end


else


else begin


Grid.Cells[0,curg]:='';


curg:=curg-1;


Grid.Cells[0,curg]:=' * ';


curl:=curl-1


end;


vr.left:=1;vr.right:=1; vr.Top:=curg+1; vr.bottom:=curg+1;


Grid.Selection:=vr


end


end;


end.



УПРАЖНЕНИЯ


1. Обеспечьте в прото-СУБД поиск путём явного перебора элементов базы данных.


2. Обеспечьте в прото-СУБД поиск путём использования метода IndexOf.


3. Экспериментально сравните быстродействие вариантов из упражнений 1 и 2.















4. РАЗРАБОТКИ И ВЕРИФИКАЦИЯ РАСЧЁТНЫХ ПРИЛОЖЕНИЙ


4.1. Спецификация программы uWert


Программа uWert является экранным приложением, обеспечивающим вычисле-ние заданного пользователем регулярного арифметического выражения.


Регулярное арифметическое выражение (РАВ) определяется в алфавите L десятичных цифр, знаков операций сложения +, вычитания - и умножения *, а также левой и правой круглой скобок по индукции:


1. Нумерал (здесь последовательность цифр без знака и без пробелов) является РАВ.


2. a) если строка X является РАВ, то строка (X) является РАВ;


b) если строки X и Y являются РАВ, то строки X+Y, X-Y, X*Y являются РАВ.


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


Это приложение имеет простой графический пользовательский интерфейс: окно ввода регулярного арифметического выражения, окно результата и кнопка, нажатие на которую вызывает вычисление.



4.2. Текст программы uWert


Программа отлажена на языке Object Pascal (Borland Delphi). В приведённом ниже тексте тела нескольких процедур перенумерованы для удобства дальнейших ссылок.


Unit uWert;


interface


uses


Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,


Dialogs, StdCtrls;


type


TForm1 = class(TForm)


eExpression: TEdit;


eValue: TEdit;


Button1: TButton;


procedure Button1Click(Sender: TObject);


private


{ Private declarations }


public


{ Public declarations }


end;


R = record


va: integer;


sgn: char;


end;


Stack = class(TComponent)


private


ar: array[1..100]of R;


top: integer;


protected


procedure push(vr: R);


function pop: R;


public


constructor create(AOwner: TComponent);


destructor Destroy;


function show(n:integer):R;


property Depth: integer read top;


end;


LetterBefore=(lbNone, lbDig, lbSign, lbLBr, lbRBr);


OperationMode=(omBOS, omNorm, omEOS);


OperandNumber=(onFirst,onSecond);


var


Form1: TForm1;


buf: Stack;


lb: LetterBefore;


implementation


{$R *.dfm}


constructor Stack.create(AOwner: TComponent);


begin


inherited create(AOwner);


top:=0


end;


destructor Stack.Destroy;


begin


inherited destroy


end;


procedure Stack.push(vr: R);


begin


if top<100


then begin


top:=top+1;


ar[top]:=vr


end


else


end;


function Stack.pop: R;


begin


if top>0 then begin


result:=ar[top];


top:=top-1


end


else raise Exception.Create('Stack is empty!')


end;


function Stack.show(n:integer):R;


begin


result:=ar[n]


end;


procedure TForm1.Button1Click(Sender: TObject);


var i, n, fdig, ldig: integer; result: integer;wr: R;


function SelectDigit: integer;


begin //involve sign of the number


if(fdig>2)and((eExpression.text[fdig-1]='-')or(eExpression.text[fdig-1]='+'))


and((eExpression.text[fdig-2]='-')or(eExpression.text[fdig-2]='+')


or(eExpression.text[fdig-2]='*')or(eExpression.text[fdig-2]='/')


or(eExpression.text[fdig-2]='('))


or(fdig=2)and ((eExpression.text[1]='-')or(eExpression.text[1]='+'))


then fdig:=fdig-1;


result:=StrToInt(copy(eExpression.text, fdig, ldig-fdig+1))


end;


function Calc(n,m: integer; s: char): integer;


begin


if s='+'then result:=n+m


else result:=n-m


end;


procedure Alloc(v: integer;s: char);//sign upon digit


var vp: integer; sp: char;


begin


1: wr:=buf.pop;


2: if wr.sgn='*'


3: then if s='*'//sgn='*'


4: then wr.va:=wr.va*v


5: else begin //s='+' or '-'


6: vp:=wr.va*v;


7: wr:=buf.pop;//delete multiplicative cell


8: wr.va:=Calc(wr.va,vp,wr.sgn)//update last cell


9: end


10: else if s='*'//sgn='+' or '-'


11: then begin


12: buf.push(wr);//additive part is restored


13: wr.va:=v


14: end


15: else wr.va:=Calc(wr.va,v,wr.sgn);


16: wr.sgn:=s;


17: buf.push(wr)


end;


procedure Sab(c: char);//sign upon bracket


var vp: integer;


begin


1: wr:=buf.pop;


2: if wr.sgn='*'


3: then if not(c='*')//'+' or '-'


4: then begin


5: vp:=wr.va;


6: wr:=buf.pop;//delete bracket cell


7: wr.va:=Calc(wr.va,vp,wr.sgn)//update last cell


8: end;


9: wr.sgn:=c;


10: buf.push(wr)


end;


procedure spin(i: integer; c: char);


var vp: integer;


begin


1: case c of


2: '(': if(lb=lbNone)or(lb=lbSign)or(lb=lbLBr)


3: then begin


4: with wr do begin va:=0; sgn:= '+'end;


5: buf.push(wr);//create new additive cell


6: lb:=lbLBr;


7: end


8: else raise Exception.Create('Wrong sequence!');


9: ')','F': begin


10: wr:=buf.pop;


11: if wr.sgn='*'


12: then begin //sgn='+' or '-'


13: if lb=lbDig then vp:=wr.va*SelectDigit


14: else vp:=wr.va;


15: wr:=buf.pop;


16: wr.va:=Calc(wr.va,vp,wr.sgn)


17: end


18: else if lb=lbDig then wr.va:=Calc(wr.va,SelectDigit,wr.sgn);


19: if c=')'then begin


20: vp:=wr.va;


21: wr:=buf.pop;


22: if wr.sgn='*'then wr.va:=wr.va*vp


23: else begin


24: buf.push(wr);//restore cell to create


25: wr.va:=vp;//cell for case of future


26: wr.sgn:='*'//multiplication


27: end;


28: lb:=lbRBr


29: end;


30: buf.push(wr)


31: end;


32: '+','-','*':


32: begin


33: if((c='*')or(c='/'))and((lb=lbNone)or(lb=lbLBr))then raise Exception.Create('wrong input digit');


34: if lb=lbDig then Alloc(SelectDigit,c);


35: if lb=lbRBr then Sab(c);


36: lb:=lbSign


37: end;


38: '0','1','2','3','4','5','6','7','8','9':


39: begin


40: if(lb=lbNone)or(lb=lbSign)or(lb=lbLBr)


41: then begin


42: fdig:=i;


43: ldig:=i;


44: lb:=lbDig


45: end


46: else ldig:=i;


47: if lb=lbRBr then raise Exception.Create('Wrong sign sequence'+ ' '+IntToStr(i));


48: end


49: end//case


end;


begin


buf:=Stack.create(self);


with wr do begin va:=0; sgn:= '+'end;


buf.push(wr);


lb:=lbNone;


try


for i:=1to length(eExpression.text)do spin(i, eExpression.text[i]);


if(lb=lbDig)or(lb=lbRBr)


then


else raise Exception.Create('wrong end of input'+ ' '+IntToStr(i));


spin(i,'F');


eValue.text:=IntToStr(buf.pop.va);


if buf.Depth>1then raise Exception.Create('wrong end of input!')


except


on E: Exception do begin showmessage(E.message);buf.Destroy end


end


end;


end.


4.3. Доказательство корректности программы uWert


Концепция программы состоит в следующем:


1) исходное РАВ обрабатывается в цикле литера за литерой по одной литере на каждом шаге цикла, без возвратов,


2) рабочая информация накапливается в стеке и переменных fdig, ldig и lb,


3) ячейка стека содержит промежуточный результат вычисления или его часть,


4) переменные fdig и ldig – это номера первой и последней литеры “текущего” нумерала, то есть нумерала, в пределах которого находится переменная цикла,


5) переменная lb хранит литеру, предшествующую “текущей”, то есть литере, номер которой в исходном РАВ совпадает со значением переменной цикла.


Для более формального исследования программы и доказательства её корректности далее приведён ряд определений.


“Мультипликативное окончание” М(X) для РАВ X определяется индукцией по построению X:


I. База индукции.


1.1. Если X – нумерал, то M(X) = ‘’ (то есть, мультипликативное окончание отсутствует).


1.2. Если X = m*n , где m и n – нумералы, то M(X) = X.


II. Шаг индукции:


2.1. М((X)) = (X), (то есть, РАВ (X) совпадает со своим мультипликативным окончанием).


2.2. M(Y+Z) = M(Z).


2.3. M(Y-Z) = M(Z).


2.4. M(Y*Z) = M(Y)*Z, если M(Z) = Z, иначе M(Y*Z) = M(Z).


Очевидно, что если M(X) не пусто, то М(X) является РАВ.


Мультипликативным называется РАВ, совпадающее со своим окончанием.


Выражение XY определено, если только существует такое Z, что X=ZY и тогда XY = Z.


Функция F(X) от регулярного арифметического выражения (РАВ) определяется по индукции:


I. База индукции. Если ‘X’ - нумерал, то F(X) = StrToInt(‘X’).


II. Шаг индукции:


2.1. Если X и Y являются РАВ, то


F(X+Y) = F(X)+F(Y),


F(X-Y) = F(X)-F(Y).


2.2. F(X*Y) = F(X)*F(Y), если M(X) = X и M(Y) = Y,


иначе F(X*Y) = F(X*YM(Y))+F(M(Y)).


F от пустой строки равно 0.


Теорема 1
. Пусть
программа uWert (далее просто Программа) применяется к слову eExpression.Text = ‘AXB’, где X – РАВ, а B – строка, которая может быть пустой, и приступает к выполнению процедуры spin в цикле при i = length(‘A’)+1, причём:


a) lb = lbNone, если A пуста, или lb = lbSign или lb = lbLBr, в противном случае,


b) стек buf содержит последовательность ячеек r1, …, rk, и ячейка rk содержит число n и знак операции ‘+’ или ‘-’.


Тогда
на шаге i = length(‘AX’) цикла на выходе процедуры spin установится одно из следующих состояний.


Случай А.


lb = lbDig,


переменные fdig и ldig указывают начало и, соответственно, конец нумерала m, завершающего X,


стек buf содержит последовательность ячеек r1, …, rk, и ячейка rk содержит число n + F(Xm) и прежний знак операции ‘+’ или ‘-’.


Случай В.


lb = lbDig,


переменные fdig и ldig указывают начало и, соответственно, конец нумерала m, завершающего X,


стек buf содержит последовательность ячеек r1, …, rk, rk+1, ячейка rk содержит число n + F(XS) и прежний знак операции, а rk+1 содержит число F(Sm) и знак операции ‘*’, при этом S – мультипликативное окончание X. Если X – мультипликативное РАВ, то F(XS)=0.


Случай
С.


lb = lbRBr,


стек buf содержит последовательность ячеек r1, …, rk, rk+1, ячейка rk содержит число n+ F(XS) и прежний знак операции, а rk+1 содержит число F(S) и знак операции ‘*’, при этом S – мультипликативное окончание X. Если X – мультипликативное РАВ, то F(XS)=0.


Доказательство. Проводится индукцией по построению X как РАВ.


I. База индукции. Пусть X - нумерал (то есть последовательность цифр без знака и без пробелов).


Тогда Программа выполнит length(‘X’) шагов цикла, в которых будут работать строки 39 - 48 процедуры spin, переменные fdig и ldig установится на начало и, соответственно, конец строки X, а lb будет устанавливаться равным lbDig на всех шагах до шага length(‘X’) включительно. Стек не изменяется. То есть, реализуется случай А.


II. Шаг индукции.


2.1. Пусть X = (Y), где Y – РАВ.


Тогда в результате выполнения строк 2 – 7 процедуры spin в стек будет добавлена ячейка rk+1, содержащая число 0 и знак ‘+’, и, таким образом, перед следующим выполнение шага цикла для Y установятся условия данной леммы, причём lb = lbLBr, B = ‘)B’. По предположению индукции Программа выполнит length(Y) шагов цикла и на последнем из них на выходе из процедуры spin установится состояние, соответствующее одному из 3 указанных случаев.


Пусть реализован случай А.


Тогда на следующем шаге цикла в результате выполнения строк 18 – 26 к числу в ячейке rk+1 будет прибавлено число m и установлен знак операции ‘*’. Эта ячейка будет содержать F(‘X). В строке 28 переменной lb будет присвоено значение lbRBr, то есть, в данном случае при обработке (X) реализуется случай C.


Пусть реализован случай В.


Тогда на следующем шаге цикла в результате выполнения строк 13, 15 и 16 ячейка rk+2 снимается со стека, число из ячейки rk+2 умножается на число m, со стека снимается ячейка rk+1 и произведение складывается с её содержимым. Затем в строке 21 снимается ячейка rk, но поскольку в ней указана аддитивная операция, в строке 24 она возвращается в стек, в строке 30 в стек вводится ячейка rk+1, а строки 25 и 26 обеспечивают в ней вычисленную в строке 16 сумму и знак умножения.


Таким образом, в данном случае при обработке (X) реализуется случай C.


Пусть реализован случай C.


Тогда на следующем шаге цикла в результате выполнения строки 10 ячейка rk+2 снимается со стека, и число из неё в строке 14 временно сохраняется. Затем в строке 15 со стека снимается ячейка rk+1, и в строке 16 число из ячейки rk+1 складывается с сохранённым числом – результатом обработки X и в строке 20 временно сохраняется. Затем в строке 21 со стека снимается ячейка rk, но поскольку в ней указана аддитивная операция, в строке 24 она возвращается в стек, в строке 30 в стек вводится ячейка rk+1, а строки 25 и 26 обеспечивают в ней сохранённое число и знак умножения.


Таким образом, в данном случае при обработке (X) реализуется случай C.


2.2. Пусть X= YwZ, где Y и Z – РАВ, а w – ‘+’ или ‘-’.


Тогда применим индукционное предположение к Y и рассмотрим случаи.


Пусть реализован случай А.


Тогда на следующем шаге цикла в результате выполнения строки 35 вызывается процедура Alloc. В ней в строке 15 число, выделенное значениями переменных fdig и ldig, складывается с числом в ячейке rk. В результате число в ячейке rk становится равным n+F(X). Строки 1, 16 и 17 обеспечивают занесение его в эту ячейку Переменная lb устанавливается равной lbSign.


Пусть реализован случай B.


Тогда на следующем шаге цикла в результате выполнения строки 35 вызывается процедура Alloc. В ней в строке 6 число, выделенное значениями переменных fdig и ldig, умножается на число в ячейке rk+1, а в строках 7 и 8 складывается с числом из ячейки rk. Строки 1, 16 и 17 обеспечивают занесение суммы в эту ячейку и установку в ней w как знака операции. В результате число в ячейке rk становится равным n+F(X). Переменная lb устанавливается равной lbSign.


Пусть реализован случай С.


Тогда на следующем шаге цикла в результате выполнения строки 36 вызывается процедура Sab. В ней в строке 7 число, сформированное в ячейке rk, складывается с числом или вычитается из числа, сформированного в ячейке rk+1. В результате число в ячейке rk становится равным n+F(X). Переменная lb устанавливается равной lbSign.


Далее Программа применяется к Z и по предположению индукции Программа переходит к одному из случаев, определённых в формулировке леммы.


Пусть при обработке Z реализован случай А.


Тогда переменные fdig и ldig указывают начало и, соответственно, конец нумерала m, завершающего Z и, следовательно, строки Y+Z. Переменная lb будет равна lbDig. Стек имеет rk ячеек, и последняя из них содержит n+F(Y)+F(Zm) = n+F(Y+Zm). То есть, при обработке Y+Z реализован случай А.

Пусть при обработке Z реализован случай B.


Тогда cтек имеет rk+1 ячеек. Переменная lb будет равна lbDig. Ячейка rk содержит число n+F(Y)+F(ZM(Ym)) = n+F(Y+ZM(Ym) в обозначениях случая А. Ячейка rk+1 содержит число F(M(Zm)) = F(M(Y+Zm)). То есть, при обработке Y+Z реализован случай B.


Пусть при обработке Z реализован случай С.


Тогда cтек имеет rk+1 ячеек. Переменная lb будет равна lbRBr. Ячейка rk содержит число n+F(Y)+F(ZM(Y)) = n+F(Y+ZM(Y) в обозначениях случая А. Ячейка rk+1 содержит число F(M(Z)) = F(M(Y+Z)). То есть, при обработке Y+Z реализован случай С.


2.3. Пусть X=Y*Z. Рассмотрим представление (разложение) X = Y*ZM(Y*Z)+M(Y*Z).


Если обе части разложения не пусты, то применим к ним предположение индукции п.2.2 теоремы.


Рассмотрим случай, когда M(Y*Z) пусто. Тогда существуют такое РАВ Q и число m, что Y*Z =Q+m. Применим к ним предположение индукции п.2.2 теоремы.


Рассмотрим случай, когда Y*ZM(Y*Z) пусто, то есть, Y*Z – мультипликативный РАВ.


Тогда применим Программу к Y, как в п.2.2. Тогда после обработки Y* Программа придёт в следующее состояние. Переменная lb = lbSign, стек содержит rk+1 ячеек, в ячейке rk содержится исходное число n. Ячейка rk+1 содержит число F(X), а знак является знаком операции умножения.


Рассмотрим применение в этих условиях Программы к Z индукцией по построению Z.


I. База индукции.


1.1. Пусть Z является нумералом m. Тогда на выходе из его обработки переменные fdig и ldig указывают начало и, соответственно, конец этого нумерала. Стек содержит те же rk+1 ячеек. Число в ячейке rk+1 F(X) = F(Y) = F(Y*mm) = F(Xm). То есть, выполняются условия случая B.


1.2. Пусть Z является (Y). Тогда нетрудно убедиться, как в п.2.1 выше, после обработки Программой такого Z установятся условия случая C. Число в ячейке rk+1 F(X) = F(Y)*F(Z)=D(Y*Z).


II. Шаг индукции. Пусть X=Y*Z*m.


2.1. Пусть X=Y*Z*m. По предположению индукции после обработки Y*Z установятся условия теоремы. Применяя рассуждения п.1.1, можно убедиться, что после обработки m установятся условия случая B. Число в ячейке rk+1 F(Xm) = F(Y*Z*mm) = F(Y)*F(Z*mm).


2.2. Пусть X=Y*Z*(U). По предположению индукции после обработки Y*Z установятся условия теоремы. Применяя рассуждения п.1.2, можно убедиться, что после обработки (U) установятся условия случая C. Число в ячейке rk+1 F(X) = F(Y*Z*(U)) = F(Y)*F(Z)*F(U)) = F(Y)*F(Z*(U)).


Теорема доказана.


Следствие.
Если программу uWert применить к РАВ X, то в качестве результата будет получено число F(X).


Доказательство. Пусть Программа применяется к РАВ X. Нетрудно убедиться, что при входе в цикл выполняются условия Теоремы 1, причём стек содержит одну ячейку, то есть, k=1, n=0 и z=’+’. Поэтому Программа выйдет из цикла и перейдёт к процедуре spin(i, ‘F’) , установив один из 3 случаев состояния, указанных в Теореме.


Рассмотрим действия процедуры spin(i, ‘F’) в каждом из этих случаев.


Случай А.


В строке 18 число в ячейке 1 складывается с числом в конце X. В результате это число становится равным F(X).


Случай B.


Стек содержит 2 ячейки. Строка 13 умножает число из ячейке 2 на число в конце X. Затем в строках 15 и 16 произведение складывается с числом в ячейке 1, а ячейка 2 выводится из стека. В результате единственная ячейка стека содержит F(X).


Случай C. Стек содержит 2 ячейки. Строка 14 временно сохраняет число из ячейки 2. Затем в строках 15 и 16 оно складывается с числом в ячейке 1, а ячейка 2 выводится из стека. В результате единственная ячейка стека содержит F(X).


Число из ячейки стека выводится в окно eValue.


Что и требовалось доказать.


УПРАЖНЕНИЯ


1. Оцените конструктивную сложность программы по M.Холстеду.


2. Оцените вычислительную сложность программы.


5. ОРГАНИЗАЦИЯ МНОГООКОННОГО ИНТЕРФЕЙСА И ДИАЛОГА В ПРИЛОЖЕНИЯХ


5.1. Многооконный интерфейс на основе сохраняемых форм


5.2. Диалог на основе динамически создаваемых форм


5.2.1. Проект диалоговой функции в Delphi


unit CyrDialog;


interface


////////////////////////////////////////////////////////////////////////////////


//* Модуль обеспечивает диалог приложения с пользователем


//* и для этой цели предоставляет функцию Rudial, аналогичную


//* функции MessageDLG. Отличие состоит в том, что Rudial


//* показывает кнопки с русскязычными надписями.


uses classes, forms, dialogs, stdctrls, controls;


type TDForm = class(TCustomForm)end;


function Rudial(const Msg: string; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; HelpCtx: Longint): Word;


var vform: TDForm;


implementation


uses math, graphics, windows, sysutils;


function Rudial(const Msg: string; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; HelpCtx: Longint): Word;


var vbut: TButton; vt: TLabel; i, n: integer;


ab: array [1..11]of string; mr: array [1..11]of TModalResult;


begin


n:=0;


if mbOK in Buttons then begin inc(n); ab[n]:='О''КЭЙ'; mr[n]:=mrOK end;


if mbYes in Buttons then begin inc(n); ab[n]:='ДА'; mr[n]:=mrYES end;


if mbNO in Buttons then begin inc(n); ab[n]:='НЕТ'; mr[n]:=mrNO end;


if mbCancel in Buttons then begin inc(n); ab[n]:='ОТМЕНА'; mr[n]:=mrCancel end;


if mbAbort in Buttons then begin inc(n); ab[n]:='БАСТА'; mr[n]:=mrAbort end;


if mbRetry in Buttons then begin inc(n); ab[n]:='ПОВТОР'; mr[n]:=mrRetry end;


if mbIgnore in Buttons then begin inc(n); ab[n]:='НУ И ЧТО'; mr[n]:=mrIgnore end;


if mbAll in Buttons then begin inc(n); ab[n]:='ВСЕ'; mr[n]:=mrALL end;


if mbNoTOALL in Buttons then begin inc(n); ab[n]:='НИКАКИЕ'; mr[n]:=mrALL+1 end;


if mbYEStoALL in Buttons then begin inc(n); ab[n]:='ВСЕ'; mr[n]:=mrYEStoALL end;


try


vform:=TDForm.C

reateNew(Application);


with vform do


begin


Height:=110;


BorderStyle:=bsDialog;


caption:='Ответьте нажатием кнопки.';


position:=poScreenCenter;


BorderWidth:=3;


FormStyle:=fsStayOnTop;


vt:=TLabel.Create(vform);


vt.parent:=vform;


vt.AutoSize:=true;


vt.caption:=msg;


vt.Font.Style:=[fsBold];


Width:=max(vt.width+50,70*n+24*(n-1)+50);


vt.top:=10;


vt.left:=(width-vt.width)div 2;


for i:=1to n do


begin


vbut:=TButton.Create(vform);


with vbut do


begin


parent:=vform;


top:=40;


width:=70;


height:=23;


left:=(vform.width-70*n-20*(n-1))div 2+(i-1)*(70+20);


Caption:=ab[i];


font.style:=[fsBold];


ModalResult:=mr[i]


// onClick:=CliRu


end


end;


result:=ShowModal;


FreeAndNil(vform)


end


finally


if not(vform=nil)then vform.free


end


end;


{procedure TDForm.CliRu(sender: TObject);


begin


TForm(TComponent(sender).owner).close


end;}


end.


5.2.2. Проект диалоговой функции в Microsoft Visual Studio 2008 (CLR, язык C#)


В среде проектирования включение дополнительных форм в проект обеспечивается в главном меню командами Проект – Добавить форму Windows …. В результате открывается окно выбора элемента, в котором уже выбран пункт “Форма Windows Form”. Пользователю достаточно нажать экранную кнопку Добавить. В это же окно можно попасть, активируя другие подпункты пункта главного меню Проект, начинающиеся со cлова Добавить.


В проект будет добавлены файлы с именем новой формы и расширением cs и Designer.cs. К новой форме можно обращаться при запуске приложения, выполнив предложения:


System.Windows.Forms.Form vbox;//объявление переменной


vbox = new NBox();//создание экземпляра формы.


Далее её можно сделать, например, сделать видимой на равне с главной формой предложением:


vbox.Show ();


или видимой в модальном режиме, то есть в режиме вызова (с приостановкой активности вызывающей формы:


vbox.ShowDialog();


Кроме того форму можно определить и использовать без “дизайнера”, то есть отдельного модуля, обеспечивающего хранение содержимого формы и заполнение её при запуске. Для этого достаточно определить соответствующий класс и вызывать его конструктор, а заполнение формы обеспечивать по месту этого вызова.Такой случай показан в нижеследующем приложении.


Главная форма:


using System;


using System.Collections.Generic;


using System.ComponentModel;


using System.Data;


using System.Drawing;


using System.Linq;


using System.Text;


using System.Windows.Forms;


namespace WinForm12


{


public partial class Form1 : Form


{


public Form1()


{


InitializeComponent();


}


private void button1_Click(object sender, EventArgs e)


{


NBox.PseudoFun();


// this.Close();


}


}


}


Наряду с главной формой Form1 в проекте имеется модуль NewBox.cs:


using System;


using System.Windows.Forms;


//using NUnit.Framework;


namespace WinForm12


{


public class NBox : Form


{


public static void PseudoFun()


{


// MessageBox.Show("bingo!");


System.Windows.Forms.Form vbox;


vbox = new NBox();


vbox.Name = "NBox";


System.Windows.Forms.Button vbut;


vbut = new System.Windows.Forms.Button();


// vbut.Show();


vbut.Location = new System.Drawing.Point(100, 100);


vbut.Size = new System.Drawing.Size(100,30);


vbut.Text = "ЖМИ";


vbox.Controls.Add(vbut);


// vbut.Click += new EventHandler(NBox.vbut_Click);


vbut.Click += NBox.vbut_Click;


vbox.ShowDialog();


}


public void Main()


{


MessageBox.Show("bingo!");


}


public NBox()


{


InitializeForm();


}


private void InitializeForm()


{


this.Text = "Nbox";


}


private static void vbut_Click(object sender, EventArgs e)


{


// System.Windows.Forms.Button lbut;


// lbut = sender as Button;


// System.Windows.Forms.Form lbox;


// lbox = lbut.Parent as Form;


// MessageBox.Show(lbox.Text);


// lbox.Close();


((sender as Button).Parent as Form).Close();


}


}


}


В этом модуле содержится класс NBox, определяющий форму и включающий в себя статический метод PseudoFun, который создаёт экземпляр формы NBox, заносит на неё кнопку и обработчик её нажатия и вызывает форму в модальном режиме.


using System;


using System.Windows.Forms;


namespace WinForm12


{


public class NBox : Form


{


public static void PseudoFun()


{


System.Windows.Forms.Form vbox;


vbox = new NBox();


vbox.Name = "NBox";


System.Windows.Forms.Button vbut;


vbut = new System.Windows.Forms.Button();


vbut.Location = new System.Drawing.Point(100, 100);


vbut.Size = new System.Drawing.Size(100,30);


vbut.Text = "ЖМИ";


vbox.Controls.Add(vbut);


// vbut.Click += new EventHandler(NBox.vbut_Click);


vbut.Click += NBox.vbut_Click;


vbox.ShowDialog();


}


public NBox()


{


InitializeForm();


}


private void InitializeForm()


{


this.Text = "Nbox";


}


private static void vbut_Click(object sender, EventArgs e)


{


// System.Windows.Forms.Button lbut;


// lbut = sender as Button;


// System.Windows.Forms.Form lbox;


// lbox = lbut.Parent as Form;


// lbox.Close();


((sender as Button).Parent as Form).Close();


}


}


}


5.2.3. Проект диалоговой функции в Microsoft Visual Studio 2008 (CLR, язык C++)


Приложение, аналогичное последнему, рассмотренному в предыдущем разделе, можно построить в той же среде проектирования, но для языка C++.


В этом случае проект содержит главный файл с расширением cpp, а именно:


CLRWin02.cpp: главный файл проекта.


#include "stdafx.h"


#include "TestForm.h"


using namespace CLRWin02;


int nn=25;


[STAThreadAttribute]


int main(array<System::String ^> ^args)


{


// Включение визуальных эффектов Windows XP до создания каких-либо элементов управления


Application::EnableVisualStyles();


Application::SetCompatibleTextRenderingDefault(false);


// Создание главного окна и его запуск


Application::Run(gcnew TestForm());


return 0;


}


Модуль NewBox.h, содержащий определение формы, которая динамически создавается и вызывается в модальном режиме из модуля TestForm.h.


#pragma once


#include "NewBox.h"


namespace CLRWin02 {


using namespace System;


using namespace System::ComponentModel;


using namespace System::Collections;


using namespace System::Windows::Forms;


using namespace System::Data;


using namespace System::Drawing;


/// <summary>


/// Сводка для Form1


///


/// Внимание! При изменении имени этого класса необходимо также изменить


/// свойство имени файла ресурсов ("Resource File Name") для средства компиляции управляемого ресурса,


/// связанного со всеми файлами с расширением .resx, от которых зависит данный класс. В противном случае,


/// конструкторы не смогут правильно работать с локализованными


/// ресурсами, сопоставленными данной форме.


/// </summary>


public ref class TestForm : public System::Windows::Forms::Form


{


public:


TestForm(void)


{


InitializeComponent();


//


//TODO: добавьте код конструктора


//


}


protected:


/// <summary>


/// Освободить все используемые ресурсы.


/// </summary>


~TestForm()


{


if (components)


{


delete components;


}


}


private: System::Windows::Forms::MenuStrip^ menuStrip1;


protected:


private: System::Windows::Forms::ToolStripMenuItem^ testToolStripMenuItem;


private:


/// <summary>


/// Требуется переменная конструктора.


/// </summary>


System::ComponentModel::Container ^components;


#pragma region Windows Form Designer generated code


/// <summary>


/// Обязательный метод для поддержки конструктора - не изменяйте


/// содержимое данного метода при помощи редактора кода.


/// </summary>


void InitializeComponent(void)


{


this->menuStrip1 = (gcnew System::Windows::Forms::MenuStrip());


this->testToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem());


this->menuStrip1->SuspendLayout();


this->SuspendLayout();


//


// menuStrip1


//


this->menuStrip1->Items->AddRange(gcnew cli::array< System::Windows::Forms::ToolStripItem^ >(1) {this->testToolStripMenuItem});


this->menuStrip1->Location = System::Drawing::Point(0, 0);


this->menuStrip1->Name = L"menuStrip1";


this->menuStrip1->Size = System::Drawing::Size(292, 24);


this->menuStrip1->TabIndex = 0;


this->menuStrip1->Text = L"menuStrip1";


//


// testToolStripMenuItem


//


this->testToolStripMenuItem->Name = L"testToolStripMenuItem";


this->testToolStripMenuItem->Size = System::Drawing::Size(40, 20);


this->testToolStripMenuItem->Text = L"Test";


this->testToolStripMenuItem->Click += gcnew System::EventHandler(this, &TestForm::testToolStripMenuItem_Click);


//


// TestForm


//


this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);


this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;


this->ClientSize = System::Drawing::Size(292, 266);


this->Controls->Add(this->menuStrip1);


this->MainMenuStrip = this->menuStrip1;


this->Name = L"TestForm";


this->Text = L"TestForm";


this->menuStrip1->ResumeLayout(false);


this->menuStrip1->PerformLayout();


this->ResumeLayout(false);


this->PerformLayout();


}


#pragma endregion


private: System::Void testToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e) {


PseudoFun();


};


};


}


Модуль TestForm.h содержит определение класса TestForm, содержащего пункт в главном меню, при активировании которого вызывается функция PseudoFun(), определённая в модуле NewBox.


Модуль NewBox:


namespace CLRWin02 {


using namespace System::Windows::Forms;


static void vbut_Click(System::Object^ sender, System::EventArgs^ e)


{


dynamic_cast< System::Windows::Forms::Form^ >(dynamic_cast< System::Windows::Forms::Button^ >(sender)->Parent)->Close();


};


void PseudoFun()


{


System::Windows::Forms::Form ^vForm2;


vForm2 = gcnew System::Windows::Forms::Form();


vForm2->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;


vForm2->ClientSize = System::Drawing::Size(400, 200);


vForm2->Name = L"NBox";


vForm2->Text = L"Кириллизованный MessageBox";


System::Windows::Forms::Button^ vbut;


vbut = (gcnew System::Windows::Forms::Button());


vForm2->Controls->Add(vbut);


vbut->Location = System::Drawing::Point(100, 100);


vbut->Size = System::Drawing::Size(100, 30);


vbut->Text = L"ЖМИ";


vbut->UseVisualStyleBackColor = true;


vbut->Click += gcnew System::EventHandler(vbut_Click);


vForm2->ShowDialog();


}


}


Легко заметить, что в случае языка C++, не допускающего определение класса частями в нескольких модулях (как со спецификатором partial в языке C#l), фрагмент приложения, порождаемый средой проектирования автоматически и инициирующий форму, помещается в том же модуле, в котором находится определение класса, в данном случае – в модуле TestForm.h.


В проект входят вспомогательные модули:


stdafx.cpp: исходный файл, содержащий только стандартные включаемые модули


// CLRWin02.pch будет предкомпилированным заголовком


// stdafx.obj будет содержать предварительно откомпилированные сведения о типе


#include "stdafx.h"


stdafx.h: включаемый файл для стандартных системных включаемых файлов


// или включаемых файлов для конкретного проекта, которые часто используются, но


// не часто изменяются


#pragma once


TestForm.resx, app.aps, app.ico, CLRWin02.vcproj, а также


AssemblyInfo.cpp


#include "stdafx.h"


using namespace System;


using namespace System::Reflection;


using namespace System::Runtime::CompilerServices;


using namespace System::Runtime::InteropServices;


using namespace System::Security::Permissions;


//


// Общие сведения об этой сборке предоставляются следующим набором


// атрибутов. Отредактируйте значения этих атрибутов, чтобы изменить


// общие сведения об этой сборке.


//


[assembly:AssemblyTitleAttribute("CLRWin02")];


[assembly:AssemblyDescriptionAttribute("")];


[assembly:AssemblyConfigurationAttribute("")];


[assembly:AssemblyCompanyAttribute("Microsoft")];


[assembly:AssemblyProductAttribute("CLRWin02")];


[assembly:AssemblyCopyrightAttribute("Copyright (c) Microsoft 2010")];


[assembly:AssemblyTrademarkAttribute("")];


[assembly:AssemblyCultureAttribute("")];


//


// Сведения о версии сборки состоят из следующих четырех значений:


//


// Основной номер версии


// Дополнительный номер версии


// Номер построения


// Редакция


//


// Можно задать все значения или принять номер построения и номер редакции по умолчанию,


// используя "*", как показано ниже:


[assembly:AssemblyVersionAttribute("1.0.*")];


[assembly:ComVisible(false)];


[assembly:CLSCompliantAttribute(true)];


[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)];


Главная форма и вызванное диалоговое окно выглядят на экране следующим образом;



6. ПРОЕКТИРОВАНИЕ КЛАССОВ


6.1. Основы модельно-ориентированного проектирования


Откуда берутся объекты в АСУ и бизнес-приложениях?


В настоящее время систематический подход к объектно-ориентированному проектированию представлен, главным образом, так называемым, MDA (model-driven architecture), или МОП (модельно-ориентированным проектированием). Основоположник – Rational Rose, подхватившей более 10 лет назад наработки OMG.


Идея MDA: проектирование включает в себя создание имитационной модели реальной системы ведётся на основе этой модели, и в неё же встраивается проектируемое компьютерное приложение для замены или развития её определённых функций.


Модельно-ориентированное и, соответственно, объектно-ориентированное проектирование реализуются в конкретных организационных формах в рамках определённых концепций жизненного цикла программ. Относительно независимым от этих форм и концепций является перечень “дисциплин” – видов деятельности, составляющих процесс создания программы (специальные виды технологических процессов):


бизнес-моделирование (business modeling),


работа с требованиями (анализ требований requirements),


проектирование (design),


реализация,


тестирование,


развёртывание,


конфигурирование,


управление изменениями,


управление проектом,


связь с окружением.


Дисциплины характеризуются своими результатами – “артефактами”. Основным артефактом бизнес-моделирования является имитационная модель реальной системы. Артефакты анализа требований: виденье (как бы ТЗ), описание (модель) “прецедентов”, словарь, спецификация требований, функциональных и прочих.


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


Модель реальной системы отображает основные объекты моделируемой системы, их свойства и отношения. Для этой модели характерно отражение статических аспектов системы.


Динамический аспект системы отражается, главным образом, в описании прецедентов и функциональных требований. Прецедент (use case). Основной прецедент и другие.


Важным элементом бизнес-моделирования и анализа требований является определение границы системы, в модель должна определять внутренние объекты и внешние (по отношению к этой границе), с которыми они взаимодействуют.


Этап проектирования начинается принятием решения о месте создаваемой компьютерной системы в составе реальной системы. В общем случае одни объекты реальной системы ликвидируются без следа, другие преобразуются, входя внутрь компьютерной системы, третьи изменяют свои связи и свойства. В результате принятия этого решения должны быть переработаны вышеуказанные артефакты.


Последующие решения связаны с уточнением состава объектов уже внутри компьютерной системы, детализацией свойств и операций (“методов”), выбором компьютерной платформы, операционной среды и языка (системы) программирования для реализации. Все эти мероприятия создают необходимые предпосылки для перехода от проектирования к реализации.


UML предоставляет графические средства для составления “диаграмм”:


диаграммы прецедентов,


диаграммы классов,


диаграмм взаимодействия, а именно: диаграммы последовательностей (sequence diagram) и диаграммы кооперации (collaboration diagram), в частности, системной диаграммы последовательностей. UML доступен в разных системах, в частности, в Microsoft Visio, Rational Rose, Delphi, начиная с издания 8.


6.2. Проект разработки компьютерной поддержки библиотеки


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


6.2.1. Начальная фаза проектирования


В соответствии с рекомендациями Унифицированного процесса проектирования (UP) [1] во время начальной фазы проектирования в качестве рабочих материалов («артефактов») разрабатываются диаграмма концептуальных классов и диаграмма прецедентов, приведённые ниже.


Диаграмма концептуальных классов отражает условия разработки, состоящие в том, что библиотека не оснащена компьютерной поддержкой, но имеется каталог элементов хранения (ЭХ) и реестр читателей, и то и другое на карточках. Масштаб библиотеки невелик: она обходится одним библиотекарем.


На диаграмме концептуальных классов отражены только операции по выдаче и возврату публикаций, операции, связанные с прецедентами “Регистрация читателя” и “Комплектация библиотеки”, не показаны, чтобы избежать излишней густоты связей. Читатель может указать эти связи на отдельных экземплярах диаграммы концептуальных классов в качестве упражнения.


Наименование ролей и ассоциаций даны в таком объёме, чтобы избегать повторений и переполнения пространства диаграммы.


Далее один из прецедентов представлен в табличной форме. Описание прецедента отражают фактический порядок осуществления заказов на получение публикации в библиотеке. В частности, пользователь имеет самостоятельный доступ к каталогу для поиска публикаций. Каталог не содержит информации о выдаче публикаций, и читатель может её получить только в ходе заказа.



Диаграмма концептуальных классов проекта поддержки библиотеки



Диаграмма прецедентов проекта поддержки библиотеки


Прецедент из проекта поддержки библиотеки

















Имя прецедента


Выполнение заказа


Исполнители


Читатель и библиотекарь


Описание


Осн
. Читатель передает библиотекарю информацию, идентифицирующую себя и публикацию, которую читатель хотел бы получить. Библиотекарь убеждается по реестру, что читатель зарегистрирован в библиотеке и экземпляр требуемой публикации может быть выдан.


Библиотекарь передает экземпляр требуемой публикации и фиксирует факт выдачи.


A1.
Читатель не зарегистрирован в библиотеке. Заказ отклоняется.


A2.
Читатель зарегистрирован, но заказанная публикация выдана. Заказ отклоняется


Предусловия


Читатель реализовал прецедент «Справка о наличии» и


узнал, что искомая публикация входит в библиотечный фонд.


Постусловия


Если читатель получил заказанную публикацию, то в карточке читателя отмечается факт выдачи.



В данном случае, Осн. – основная последовательность действий (основной сценарий).


A1-A2. Альтернативные сценарии.


УПРАЖНЕНИЯ.


1. Описать остальные прецеденты проекта


6.2.2.Первые проектные решения


В рамках следующей фазы проектирования принимается решение о границах проектируемой компьютерной поддержки и её месте в библиотеке. Оно состоит в том, что картотечные каталог и реестр заменяются компьютерной системой, которая обеспечивает ведение двух баз данных – по фонду публикаций и контингенту читателей. Читатель имеет прямой доступ к фонду публикаций для поиска и чтения. Все функции оперативного изменения содержимого баз данных осуществляет библиотекарь. Это решение фиксируется в уточненных описаниях прецедентов (в табличной и графической формах) и диаграммах проектных классов и системных взаимодействий.


Далее представлены первичная версия диаграммы проектных классов, диаграммы системных последовательностей основного сценария прецедента «Выполнение заказа» и соответствующей диаграммы кооперации.


Эти диаграммы представляют интерфейс между пользователем – библиотекарем и проектируемой компьютерной системой и оставляют открытыми многие детали этого интерфейса равно, как и вопросы его реализации внутри системы.



Первичная диаграмма проектных классов



Диаграмма системных последовательностей для прецедента «Выполнение заказа»



Диаграмма кооперации (системная) для сценария «Выполнение заказа»


6.2.3. Ключевые элементы реализации


В ходе реализации принятых решений складывается вполне типовая ситуация, когда информационная система (ИС) должна обеспечивать учёт действий пользователя с некоторым множеством (фондом) однотипных объектов (элементов фонда), например, менеджера с проектами, в рассматриваемом случае - библиотекаря с экземплярами печатных изданий и читателями. Обобщённая концептуальная диаграмма классов в этой ситуации показана на Рис.1.



Рисунок 1. Концептуальная диаграмма классов для типового фрагмента проекта


Единственный атрибут элемента – состояние – обобщает всевозможные состояния моделируемого объекта, например, книга может быть выдана, проект – приостановлен, читатель - зарегистрирован. Ассоциация “действует” обобщает всевозможные действия пользователя, изменяющие состояния объекта, а также “Включение объекта в фонд” и “Изъятие объекта из фонда”.


Диаграмма последовательностей для системных операций представлена на Рис.2, а соответствующая диаграмма кооперации – на Рис.3.



Рисунок 2. Диаграмма последовательностей системных операций для типового фрагмента проекта



Рисунок 3. Диаграмма кооперации системных операций для типового фрагмента проекта


Диаграмма классов проекта строится на основе концептуальной диаграммы классов и диаграмм взаимодействия. При этом определяется набор классов, которые исполняют системные операции, показанные в диаграммах взаимодействия, и служат прототипами классов исходного языка программирования, на котором записывается проект. Первичными кандидатами в классы проекта являются классы концептуальной диаграммы.


Простейшее и вполне удовлетворительное решение этой задачи состоит в назначении всех системных операций классу “Фонд” и реализации их в виде методов соответствующего класса в программе. Выбор в языке программирования способа представления “Элементов”, входящих в “Фонд” определяется следующими требованиями, вытекающими из определения системных операций:


· в “Фонд” может входить любое (в частности, пустое) конечное множество однотипных “Элементов”,


· необходимы элементарные операции для добавления, удаления и выборки “Элемента” по некоторому признаку.


В языке C# этим требованиям удовлетворяют классы List(T) и ArrayList. Функциональность этих классов можно передать классу “Фонд”, реализовав его как их наследника или введя в “Фонд” атрибут типа ArrayList или List(T). Для реализации концептуального класса “Элемент” можно выбрать типы Struct или Class.


На Рис.4 показана диаграмма классов для первого варианта проекта (Варианта А), в котором “Фонд” реализуется как наследник класса List(T).



Рисунок 4. Диаграмма классов для первого варианта фрагмента проекта Соответствующие диаграмма последовательностей и диаграмма кооперации показаны на Рис.5 и 6.



Рисунок 5. Диаграмма последовательностей для первого варианта типового фрагмента проекта



Рисунок 6. Диаграмма кооперации для первого варианта типового фрагмента проекта


В этом варианте проекта установлено, что элементы фона идентифицируются строкой и сам пользователь заботится об уникальности элементов. Хотя на диаграммах показаны только те операции типа List(T), которые необходимы для реализации выбранных системных операций, и не показаны базовые операции, необходимые для реализации пользовательского интерфейса, класс “Фонд” оказался функционально перегружен. Поэтому предложен второй вариант (Вариант Б), в котором введен класс “Список элементов”, и “Фонд” связан с экземпляром этого класса как с элементом своей конструкции. Кроме того, введен класс “Фасад”, который реализует связь с пользователем на базе формы


Соответствующие диаграмма классов и диаграмма последовательностей показаны на Рис.7 и 8.



Рисунок 7. Диаграмма классов для второго варианта проекта



Рисунок 8.Диаграмма последовательностей для второго варианта проекта (операции «Включить» и «Показать»).



Рисунок 9.Диаграмма последовательностей для второго варианта проекта (операции “Ввести” и “Исключить”).


6.2.4. Программная реализация на языке C++


Приведённые выше диаграммы могут быть конкретизированы на языке C++ в среде Microsoft Visual Studio в виде версии CLR следующим образом (проект CppLab02).


Класс Fasade, отвечающий за взаимодействие с оператором, определён в модуле (файле) Fasade.h – наследнике класса Form. Экземпляр класса Fasade как главная форма приложения обеспечивает визуальный интерфейс с оператором, когда приложение запущено. Далее показан вид этой формы.



Пункты главного меню представляют собой операции, которые пользователь активирует, когда работает с фондом. «Включить» создает элемент фонда со свойствами, значения которых пользователь должен перед операцией установить в окнах «Идентификатор» и «Состояние». «Показать» обеспечивает поиск элемента фонда по значению, установленному в окне «Идентификатор», и вывод в свойства State этого элемента в окно «Состояние» на форме. «Ввести» ищет элемент по «Идентификатору» и присваивает свойству State найденного элемента значение из окна «Состояние». «Исключить» находит элемент фонда по значению, установленному в окне «Идентификатор», и удаляет его из фонда. Если поиск в этих операциях не приводит к успеху, то в окне «Состояние» устанавливается значение


-3. Значение окна «Идентификатор» должно быть десятичным числом.


Операции реализуются обработчиками событий Click соответствующих пунктов меню. Их тексты нетрудно найти в листинге файла Fasade.h, приведённом далее.


#pragma once


#include "Fond.h"


namespace CppLab02 {


using namespace System;


using namespace System::ComponentModel;


using namespace System::Collections;


using namespace System::Collections::Generic;


using namespace System::Windows::Forms;


using namespace System::Data;


using namespace System::Drawing;


/// <summary>


/// Сводка для Fasade


///


/// Внимание! При изменении имени этого класса необходимо также изменить


/// свойство имени файла ресурсов ("Resource File Name") для средства компиляции управляемого ресурса,


/// связанного со всеми файлами с расширением .resx, от которых зависит данный класс. В противном случае,


/// конструкторы не смогут правильно работать с локализованными


/// ресурсами, сопоставленными данной форме.


/// </summary>


public ref class Fasade : public System::Windows::Forms::Form


{


private: CppLab02::_Fond^ vFond;


public: Fasade(void)


{


InitializeComponent();


//


//TODO: добавьте код конструктора


//


vFond = gcnew _Fond();


}


protected:


/// <summary>


/// Освободить все используемые ресурсы.


/// </summary>


~Fasade()


{


if (components)


{


delete components;


}


}


private: System::Windows::Forms::MenuStrip^ menuStrip1;


protected:


private: System::Windows::Forms::ToolStripMenuItem^ включитьToolStripMenuItem;


private: System::Windows::Forms::ToolStripMenuItem^ показатьToolStripMenuItem;


private: System::Windows::Forms::ToolStripMenuItem^ ввестиToolStripMenuItem;


private: System::Windows::Forms::ToolStripMenuItem^ исключитьToolStripMenuItem;


private: System::Windows::Forms::TextBox^ id;


private: System::Windows::Forms::TextBox^ State;


private: System::Windows::Forms::Label^ label1;


private: System::Windows::Forms::Label^ label2;


private:


/// <summary>


/// Требуется переменная конструктора.


/// </summary>


System::ComponentModel::Container ^components;


#pragma region Windows Form Designer generated code


/// <summary>


/// Обязательный метод для поддержки конструктора - не изменяйте


/// содержимое данного метода при помощи редактора кода.


/// </summary>


void InitializeComponent(void)


{


this->menuStrip1 = (gcnew System::Windows::Forms::MenuStrip());


this->включитьToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem());


this->показатьToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem());


this->ввестиToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem());


this->исключитьToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem());


this->id = (gcnew System::Windows::Forms::TextBox());


this->State = (gcnew System::Windows::Forms::TextBox());


this->label1 = (gcnew System::Windows::Forms::Label());


this->label2 = (gcnew System::Windows::Forms::Label());


this->menuStrip1->SuspendLayout();


this->SuspendLayout();


//


// menuStrip1


//


this->menuStrip1->Items->AddRange(gcnew cli::array< System::Windows::Forms::ToolStripItem^ >(4) {this->включитьToolStripMenuItem,


this->показатьToolStripMenuItem, this->ввестиToolStripMenuItem, this->исключитьToolStripMenuItem});


this->menuStrip1->Location = System::Drawing::Point(0, 0);


this->menuStrip1->Name = L"menuStrip1";


this->menuStrip1->Size = System::Drawing::Size(292, 24);


this->menuStrip1->TabIndex = 0;


this->menuStrip1->Text = L"menuStrip1";


//


// включитьToolStripMenuItem


//


this->включитьToolStripMenuItem->Name = L"включитьToolStripMenuItem";


this->включитьToolStripMenuItem->Size = System::Drawing::Size(70, 20);


this->включитьToolStripMenuItem->Text = L"Включить";


this->включитьToolStripMenuItem->Click += gcnew System::EventHandler(this, &Fasade::включитьToolStripMenuItem_Click);


//


// показатьToolStripMenuItem


//


this->показатьToolStripMenuItem->Name = L"показатьToolStripMenuItem";


this->показатьToolStripMenuItem->Size = System::Drawing::Size(67, 20);


this->показатьToolStripMenuItem->Text = L"Показать";


this->показатьToolStripMenuItem->Click += gcnew System::EventHandler(this, &Fasade::показатьToolStripMenuItem_Click);


//


// ввестиToolStripMenuItem


//


this->ввестиToolStripMenuItem->Name = L"ввестиToolStripMenuItem";


this->ввестиToolStripMenuItem->Size = System::Drawing::Size(54, 20);


this->ввестиToolStripMenuItem->Text = L"Ввести";


this->ввестиToolStripMenuItem->Click += gcnew System::EventHandler(this, &Fasade::ввестиToolStripMenuItem_Click);


//


// исключитьToolStripMenuItem


//


this->исключитьToolStripMenuItem->Name = L"исключитьToolStripMenuItem";


this->исключитьToolStripMenuItem->Size = System::Drawing::Size(76, 20);


this->исключитьToolStripMenuItem->Text = L"Исключить";


this->исключитьToolStripMenuItem->Click += gcnew System::EventHandler(this, &Fasade::исключитьToolStripMenuItem_Click);


//


// id


//


this->id->Location = System::Drawing::Point(38, 82);


this->id->Name = L"id";


this->id->Size = System::Drawing::Size(100, 20);


this->id->TabIndex = 1;


//


// State


//


this->State->Location = System::Drawing::Point(40, 135);


this->State->Name = L"State";


this->State->Size = System::Drawing::Size(100, 20);


this->State->TabIndex = 2;


//


// label1


//


this->label1->AutoSize = true;


this->label1->Location = System::Drawing::Point(35, 66);


this->label1->Name = L"label1";


this->label1->Size = System::Drawing::Size(87, 13);


this->label1->TabIndex = 3;


this->label1->Text = L"Идентификатор";


//


// label2


//


this->label2->AutoSize = true;


this->label2->Location = System::Drawing::Point(37, 119);


this->label2->Name = L"label2";


this->label2->Size = System::Drawing::Size(61, 13);


this->label2->TabIndex = 4;


this->label2->Text = L"Состояние";


//


// Fasade


//


this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);


this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;


this->ClientSize = System::Drawing::Size(292, 266);


this->Controls->Add(this->label2);


this->Controls->Add(this->label1);


this->Controls->Add(this->State);


this->Controls->Add(this->id);


this->Controls->Add(this->menuStrip1);


this->MainMenuStrip = this->menuStrip1;


this->Name = L"Fasade";


this->Text = L"Работа с фондом";


this->menuStrip1->ResumeLayout(false);


this->menuStrip1->PerformLayout();


this->ResumeLayout(false);


this->PerformLayout();


}


#pragma endregion


private: System::Void включитьToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e)


{


vFond->Include(this->State, this->id->Text);


};


private: System::Void показатьToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e)


{


vFond->Show(this->State, this->id->Text);


};


private: System::Void ввестиToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e)


{


vFond->Write(this->State, this->id->Text);


};


private: System::Void исключитьToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e)


{


vFond->Remove(this->State, this->id->Text);


};


};


}


В этих обработчиках вызываются соответствующие методы класса _Fond в соответствии с диаграммой на рис.8 и 9.


Класс _Fond определён в модуле (файле) Fond.h, листинг которого приведён далее.


#pragma once


#include "Fasade.h"


namespace CppLab02 {


using namespace System;


using namespace System::ComponentModel;


using namespace System::Collections::Generic;


using namespace System::Windows::Forms;


using namespace System::Data;


using namespace System::Drawing;


ref class _Element


{


public: String^ id;


int State;


public: _Element(String^ _id, int _State)


{


id = _id;


State = _State;


};


public: ~_Element(void) {};


};


ref class _Fond //: public System::Windows::Forms::Form


{


static int lid;


_Element ^el;


public: List<_Element^>^ _List;


public: _Fond(void)


{


_List = gcnew List<_Element^>();


};


public: ~_Fond() {};


static bool comp(_Element^ ident)


{


if(ident->State == lid)


{


return true;


}


else


{


return false;


};


};


public: _Element^ Find(int vid)


{


lid = vid;


return _List->Find(gcnew Predicate<_Element^>(comp));


};


public: void Include(TextBox^ sender, String^ _id)


{


_List->Add(gcnew _Element(sender->Text,Convert::ToInt32(_id)));


};


public: void Show(TextBox^ sender, String^ _id)


{


el = Find(Convert::ToInt32(_id));


if (el !=nullptr){sender->Text = el->id;}


else{sender->Text = "-3";};


};


public: void Remove(TextBox^ sender, String^ _id)


{


el = Find(Convert::ToInt32(_id));


if(el !=nullptr){if(!_List->Remove(el))


{sender- >Text = "-3";};}


else{sender->Text = "-3";};


};


public: void Write(TextBox^ sender, String^ _id)


{


el = Find(Convert::ToInt32(_id));


if (el != nullptr){el->id = sender->Text;}


else{sender->Text = "-3";};


};


};


}


В этом же модуле определён класс _Element, для хранения экземпляров которого предназначены экземпляры класса _Fond.


Заслуживает внимания организация поиска в фонде.


В классе _Fond хранимые элементы (экземпляры класса _Element) представлены полем _List. Тип этого поля – параметризованый класс List(T), определённый в среде проектирования. Экземпляры этого класса – списки элементов типа T, в нашем случае – типа _Element.


Метод Find класса _Fond, предназначенный для поиска в списке элементов, использует метод Find класса List(T).Этот метод применяет к каждому элементу списка предикат, полученный им в качестве входного параметра. Этот предикат порождается на основе метода comp класса _Fond.Выполнение предиката фактически состоит в выполнении этого метода comp применительно к элементу, поданному ему на вход, в среде метода Find. Поэтому он использует для сравнения локальную переменную lid, содержащую поисковый признак. Если comp возвращает true, то элемент возращается методом Find, как результат поиска. В противном случае возвращается «нулевой» указатель.


УПРАЖНЕНИЯ


1. Реализовать ключевые элементы реализации, приведённые в п.6.2.4, на языке C# Microsoft Visual Studio 2008 для среды CLR.


2. Реализовать ключевые элементы реализации, приведённые в п.6.2.4, на языке C++ в Microsoft Visual Studio 2008 для среды Win32.


ПРИЛОЖЕНИЕ 1


Синтаксис и семантика класса в языках
Object
Pascal
,
C
#,
C
++,
Java


Определение типа class.


Type
<
имя класса> =
class
[(<имя класса-предка>)]


<компонент класса>



<компонент класса>


end
;


Класс – тип данных, экземпляр которых называется объектом. Объект – порция данных, имеющая определенную классом структуру и типы значений. Переменная, типом которой является некоторый класс, содержит указатель на эту область.


Иерархия классов.


Компоненты класса


<компонент класса> = :: <поле> | <метод>| <свойство>


<поле> =:: [<атрибут видимости >] <имя поля> : <тип>;


.


Связь между типами class и record.


Поля должны идти до всех остальных компонентов. Доступ к полю


<метод> = :: [<атрибут видимости >]<метод-функция>; [<директивы>] |


[<атрибут видимости >]<метод-процедура>;[<директивы>] |


[<атрибут видимости >]<конструктор> ;[<директивы>] |


[<атрибут видимости >]<деструктор>; [<директивы>]



<директивы> =:: <директива >;<директива>; … <директива>;


<директива> =:: reintroduce | overload | virtual | dynamic | override | register | pascal | cdecl | stdcall | safecall | abstract | message | platform | deprecated | library


<cвойство> = :: [<>]property <имя>:<тип>{[read <имя функции>]


[write<имя процедуры>]}


[stored <Булево значение>]


[default <значение>] | nodefault];


stored и default управляют сохранением публикуемого свойства в модуль .dfm. По умолчанию store true. Default имеет силу только для порядковых значений и значений типа set в диапазоне от 0 до 31. Для строки, вещественного типа и указателей умолчание неявное.


<cвойство> = :: [<>]property <имя>[

<индекс>:<тип>]

:<тип>{[read <имя функции>]


[write<имя процедуры>]}


[stored <Булево значение>]


[default | nodefault];


<атрибут видимости > =:: private | protected | public | published | automated


Далее сравнительный обзор языков C++, Java и C# приводится c опорой на Object Pascal.


2.7.1. Что общего у этих четырёх языков?


Хотя это разные языки – существенные различия наблюдаются на уровнях _ лексики, синтаксиса и семантики – они, несомненно, могут быть отнесены к одному типу, который характеризуется общей “архитектоникой” – составом и иерархическим соподчинением языковых компонентов.


Лексику во всех этих языках образуют: зарезервированные слова и специальные знаки, литералы и идентификаторы (имена). Синтаксис оперирует с термами (литералами и идентификаторами), выражениями, простыми и составными предложениями (statement).


Главное содержание (смысл) программы – это определение некоторого пространства, в котором при конкретном выполнении программы размещаются значения обрабатываемых при этом выполнении данных, а также определение преобразования этих значений, и, в некоторых случаях, самого пространства. Это преобразование обычно разделяется на относительно самостоятельные компоненты, которые сопоставляются с предложениями особого типа, так называемыми, операторами или “инструкциями” и трактуются как их содержание (смысл). Последовательности таких предложений-операторов явно задают (с точностью до количества прохождений через них) последовательность “передачи управления” между ними, иными словами, последовательность шагов преобразований, выполняемых программой. Для всех четырёх рассматриваемых языков последовательность передачи управления задаётся явно: последовательностью расположения операторов в программе и специальными операторами перехода, что позволяет отнести все четыре рассматриваемых языка к языкам “операторного” типа.


Кроме предложений операторного типа в рассматриваемых языках имеются предложения типа объявления/определения, а также предложения и конструкции специального типа, в частности: блоки, конструкции для организации обработки особых случаев (“исключений”), организации областей видимости имён.


Во всех именах имеется глобальное пространство имён, которое может охватывать несколько модулей-файлов, но в разных языках оно организовано по-разному.


2.7.2. Что общего у языков C++, Java и C#, что отличает их от Object Pascal?


На уровне лексики: case-sensitivity (лексемы, различающиеся регистром букв – разные лексемы).


Тип “строка” представлен только 0-терминированной строкой и специальными классами.


Имеется тип void
, используемый, в частности, для объявления безтипового указателя.


Операции:


&& вместо AND


|| вместо OR


! вместо NOT


== вместо =


!= вместо <>


& для побитового И


| для побитового ИЛИ


^ для побитового НЕТ


Есть операции сдвига битов << и >>


Операторы (инструкции):


Оператор присваивания =
вместо :=, оператор присваивания возвращает значение (присвоенное).


Границы блока {}, а не begin
и end
.


Конструкция условного перехода (ветвления):


if
(условие
) простой оператор
или блок
[else
простой оператор
или блок
]


for
(инициатор
, условие
, шаг
) простой оператор
или блок


где инициатор
и шаг
– последовательность операторов.


while
(условие
) простой оператор
или блок


do
простой оператор
или блок
while
(условие
)


switch
(выражение
){


с
ase
значение
: последовательность операторов


case
значение
: последовательность операторов




case
значение
: последовательность операторов


[ default
простой оператор
или блок
] }


Аналоги этим конструкциям в языке Pascal очевидны. Однако switch
существенно отличается от case
языка Pascal тем, что если выражение имеет одно из значений, предусмотренных в case
, то вслед за последовательностью операторов этого выбранного case
выполняются последовательности всех нижележащих case
.


Кроме того, имеется конструкция “запятая”, отсутствующая в языке Pascal:


(условие
)?оператор присваивания
, … ,оператор присваивания


: оператор присваивания
, … ,оператор присваивания
;


Синтаксис объявления:


спецификатор
тип
имя
[= выражение
]


Порядок имени и типа составляет нарочитое формальное отличие от языка Pascal. Принципиальное отличие состоит в том, что в языке Pascal объявления сосредоточены в определённых позициях текста программы, отмеченных специальными зарезервированными словами: type
, var
, const
в разделах implementation
модулей, между заголовком функции или процедуры и begin
и т.п.


Это, во-первых, придаёт тексту на языке Pascal “формулярный” вид и, во-вторых скрывает действие, связанное с объявлением: выделение области памяти, соответствующее форматирование. Эти действия оторваны от операторной части программы и происходят в обязательном порядке как бы предосмотра до выполнения операторов.


В языках C++, Java и C# объявление простого типа располагается среди операторов и действенно, если только через него “пройдёт управление”.


Константа – частный случай переменной: переменная со спецификатором const
.


Важную роль играет спецификатор static
. Кроме классов, он может быть использован в функциях.


Новый экземпляр типа может быть создан динамически с помощью оператора new, в частном случае:


переменная
= new


Однако в различных языках для такого создания требуются дополнительные спецификации.


Определение функции:


спецификатор
тип
имя
([список формальных параметров
])тело функции


Тело функции представляет собой блок.


Определение без тела, то есть заголовок функции образует её объявление. Объявления обеспечивают использование функции в нескольких различных частях (модулях) программы при наличии одного определения.


Тип в заголовке функции – это тип возвращаемого ею значения. Это значение представлено в теле функции встроенной переменной return
. Если значение не возвращается, то есть функция является процедурой, как в языке Pascal, то должен быть указан тип void
.


Круглые скобки после имени служат формальным признаком функции при её объявлении (определении) и вызове. Список параметров может быть пустым.


функция main вызывается при запуске программы. Аргументы этой функции передаются операционной системой из командной строки.


Все рассматриваемые языки содержат типы class
и interface
, однако синтаксис объявления варьирует от одного языка к другому.


Конструктор получает имя класса.


Обращение к вызывающему объекту (self
в языке Pascal) обеспечивается встроенным словом this
.


Пространство имён структурировано, могут быть определены подпространства.


2.7.3. Особенности языка C++.


Среди типов нет типа struct
.


Определение типа с помощью оператора typedef
.


Кроме указателей есть тип “ссылка”. В функциях он используется для передачи значения по ссылке.


Оператор new
вырабатывает указатель, например;


int ^n = new
int


или


int ^n = new
int(0) с инициализатором.


Имеется возможность заранее выделять место и в нём размещать объект.


Для уничтожения объекта в случае его динамического создания предназначен оператор delete
.


Автоматические объекты могут создаваться со спецификатором register
.


В объявлении функции могут отсутствовать имена формальных параметров (только типы).


При объявлении и определении функций можно задавать значения по умолчанию. Они подставляются вместо отсутствующих последних фактических параметров.


В объявлении функции может быть задан список формальных параметров с переменное количество элементов:


(…) или (параметр
, …) или (параметр
…).


В целом, можно заметить, что в C++ процедурно-ориентированное программирование испытало далеко идущее развитие. В частности, имеются шаблоны-функции (функции, в которых тип является свободным параметром, который может быть установлен при их использовании) и обобщённые функции (generic).


Определение класса:


[спецификатор
] class
имя класса
[: спецификатор-видимости
имя-класса
, …, спецификатор-видимости
имя-класса
][{тело класса
}] [переменные
];


Объявление – это определение без тела. Объявление позволяет пользоваться именем в ограниченных целях – для определения указателей.


Для C++ характерно множественное наследование.


Возможно вложение классов.


Нестатические поля нельзя инициировать в теле класса.


В классе отсутствуют свойства как член класса.


Методы могут быть встроенными и невстроенными. Невстроенные связываются с классом через ::, то есть


имя-класса
:: имя-функции


Экземпляр класса может быть создан динамически оператором new, а также обычным указанием имени класса при имени переменной.(инициализация осуществляется конструктором по умолчанию).


Деструктор именуется ~имя-класса


Обращение к члену класса осуществляется через “точку”, если база – объект (переменная,типа класс), и через -> (“стрелку”), если база – указатель на объект.


Виртуализация метода обеспечивается спецификатором virtual
.


Обращение к членам классов вверх по иерархии наследования обеспечивается оператором using
.


Имеются шаблоны классов (тип – свободный параметр).


Глобальное поле видимости обеспечивается оператором #
include
, проставляемыми в начале модуля. Предусмотрены специальный тип файлов – заголовочный (расширение h).


Пространство имён задаётся или продолжается оператором


namespace
имя-пространства
{ пространство
}


Объект в пространстве имён квалифицируется именем пространства через ::.


Глобальное пространство не имеет имени. Можно определить безымянное локальное пространство имён.


Using
задаёт имя пространства по умолчанию до конца текущего пространства имён.


2.7.4. Особенности языка Java.


Компиляция осуществляется в специальный промежуточный байт-код,исполняемый аппаратурно-независимой Java-машиной, которая создаёт для программы “контекст времени выполнения”.


UNICODE.


Нет оператора goto
.


Конкатенация выражается знаком +.


Строка выражается объектом класса string. Этот объект доступен только для чтения. При изменении старый экземпляр уничтожается и создаётся новый.


Указателей как отдельного типа нет (?).


В функциях и методах передача параметров только по значению. Указатель дублируется. Возврат составных значений – только через объект.


Определение класса


спецификатор
class имя
[extends имя-предка
]{тело
}[implements имя-интерфейса
]


В классе отсутствуют свойства как член класса.


Определения методов встроенные (?).


В определении класса предусмотрены блоки статической инициализации


static
{ };


Нет деструкторов.


Создание объекта – посредством оператора new
.


Обращение к члену класса – через “точку” от имени переменной, содержащей объект.


Обращение к членам классов вверх по иерархии наследования обеспечивается оператором super
.


Классы могут быть (по спецификатору) abstract, final


Нет глобальных статических переменных.


Приложение запускается с указанием имени класса, в котором вызывается функция с именем main
.


Глобальное поле видимости обеспечивается оператором package
, проставляемыми в начале модуля.


package
имя-пакета


import
имя-пакета.*



2.7.5. Особенности языка C#.


Компиляция осуществляется в специальный промежуточный байт-код, исполняемый аппаратурно-независимой средой в .Net, которая создаёт для программы “контекст времени выполнения”. Исполняемый файл exe вызывает “контекст времени исполнения”.


Есть типы decimal
и struct
.


Нет указателей.


Определение класса


[спецификатор
] class
имя класса
[: спецификатор-видимости
имя-класса
][{тело класса
}];


Наследование от класса однозначное. Множественное наследование может быть наследование от интерфейсов.


Поля могут иметь спецификатор const
.


Методы встроенные. В методе могут быть передачи параметров по ссылке с инициализацией и без инициализации параметра (ref
и out
).


Есть свойства


спецификация
тип
имя-свойства
{


get {return = }


set { }


}


Классы могут быть (по спецификатору) abstract, final, partial


Введёна специальная разновидность членов класса – “событие”, которым можно присваивать в качестве значения цепочку указателей на обработчики. Присвоение в форме


имя события
+=new
имя-делегата
(объект.имя обработчика)


События определяются


public
event
имя-делегата имя-события


где определяется как тип


public delegate
void
имя
-
делегата
(сигнатура
)


Могут определяться деструкторы


~ имя-класса
( )


но они явно не вызываются.


Пространство имён задаётся или продолжается оператором


namespace
имя-пространства
{ пространство
}


Using
задаёт имя пространства по умолчанию до конца текущего пространства имён.


Объект в пространстве имён квалифицируется именем пространства через “толчку”.


Приложение запускается с указанием имени класса, в котором вызывается функция с именем main
.


ПРИЛОЖЕНИЕ 2


Основы языка
UML

Сохранить в соц. сетях:
Обсуждение:
comments powered by Disqus

Название реферата: Спецификация программы uWert > Текст программы uWert Доказательство корректности программы uWert Организация многооконного интерфейса и диалога в приложениях

Слов:13036
Символов:128853
Размер:251.67 Кб.