Міністерство освіти та науки України
Національний університет “Львівська політехніка”
Алгоритмічна реалізація циклічного кодера та декодера. Створення Windows Forms програм
на основі Microsoft Visual Studio .NET
Інструкція до лабораторної роботи № 2
з дисципліни “Основи збору, передачі та оброблення інформації”
для студентів базового напрямку 6.0914
“Комп’ютеризовані системи, автоматика і управління”
та базового напрямку 050201 “Системна інженерія”
Затверджено
на засіданні кафедри
“Комп’ютеризовані
системи автоматики”
Протокол № __ від __.__.2008
Львів 2008
Алгоритмічна реалізація циклічного кодера та декодера. Створення Windows Forms програм на основі Microsoft Visual Studio .NET: Інструкція до лабораторної роботи № 2 з дисципліни “Основи збору, передачі та оброблення інформації” для студентів базового напрямку 6.0914 “Комп’ютеризовані системи, автоматика і управління” та базового напрямку 050201 “Системна інженерія” / Укл.: А.Г. Павельчак, Р.В. Проць, В.В. Самотий – Львів: НУЛП, 2008. – 32 с.
Укладачі: А.Г. Павельчак, к.т.н., асистент
Р.В. Проць, к.т.н., доцент
В.В. Самотий, д.т.н., професор
Відповідальний за випуск:
А.Й. Наконечний, д.т.н., професор
Рецензент: З.Р. Мичуда, д.т.н., професор
Мета роботи: отримати навики по розробленню Windows Forms програм CLR за допомогою інструментарію Visual C++ 2005 та реалізувати циклічний кодер/декодер алгоритмічною мовою С++.
1. Загальне уявлення про Windows Forms
Windows Forms (Форми Windows) – це набір засобів для швидкого розроблення програм (RAD – Rapid Application Development), які виконуються в середовищі CLR (Common Language Runtime, загальномовне виконуюче середовище). Основним об’єктом створюваної програми є форма (вікно) на базі якої виконується верстка майбутньої програми. На формі розміщуються різні елементи керування (їх понад 60), що призначені для взаємодії з користувачем. Форма та елементи керування представляють собою об’єкти відповідних класів С++/CLI. Кожен клас має багатий набір властивостей, що визначає поведінку та зовнішній вигляд елементу керування чи форми. Ці властивості можуть задаватися та змінюватися як на етапі розроблення програми за допомогою засобів IDE (Integrated Development Environment, інтегроване середовище розробника), так і в процесі її виконання за допомогою доданого в неї програмного коду. Окрім властивостей, класи також містять функції для виконання операцій з елементами керування та формою.
При новому проекті програми створюється як її вікно Windows Forms на основі класу Form, так і необхідний для її відображення програмний код. Після створення нового проекту розроблення програми зводиться до таких основних операцій:
Інтерактивне макетування графічного інтерфейсу користувача за допомогою засобів IDE шляхом перетягування необхідних елементів керування на робочу форму. На цьому етапі можна створювати також необхідні додаткові вікна форм.
Зміна властивостей елементів керування та форми у відповідній вкладці Properties (Властивості) IDE у відповідності до потреб програми.
Створення відповідних обробників подій для елементів керування та форми шляхом подвійного натиснення мишею на них у вкладці Form Design та додавання відповідного програмного коду у функції обробників подій.
Наповнення проекту програмним кодом, що реалізує необхідні функціональні можливості майбутнього програмного продукту.
2. Створення Windows Forms програм CLR
Створення варіанту програми CLR з графічним інтерфейсом користувача будемо здійснювати поетапно, від створення скелету програми до його наповнення програмним кодом.
Запускаємо Visual Studio 2005. Вибираємо пункт меню File ( New ( Project для того, щоб відкрити діалог New Project.
Рис. 2.1. Створення нового проекту Windows Forms програми
Тепер виконуємо по пунктах: 1 – серед типів проектів мишею вибираємо пункт CLR; 2 – серед шаблонів вибираємо пункт Windows Forms Application; 3 – вводимо назву проекту, наприклад, myprogram; 4 – вибираємо місце розташування проекту; 5 – натискаємо кнопку OK та отримуємо готовий скелет програми. По замовчанню він виглядає як на рис. 2.2.
Початково вигляд IDE (рис. 2.2) складається з таких частин:
Меню
File – відкрити, створити, добавити, закрити, друкувати тощо;
Edit – стандартні команди правки: копіювання, вставка тощо;
View – команди для відображення та приховування усіх вікон та панелей з інструментами;
Project – команди для роботи з проектом: додавання елементів, форм, вказівників тощо;
Build – команди компіляції програми;
Debug – команди відлагодження програми;
Data – команди для роботи з даними;
Format – команди форматування розташованих елементів (вирівнювання, інтервали тощо);
Tools – команди додаткових інструментів та налаштувань Visual Studio .NET;
Window – керування розташуванням вікон;
Help – довідка,
панелі інструментів (Standard, Text Editor).
Вікно Solution Explore (Провідник проекту, Ctrl+Alt+L) містить компоненти проекту. Пункти контекстного меню цього вікна дають можливість змінювати вміст проекту, а також додавати нові компоненти.
Режими дизайну та коду (Shift+F7 / Ctrl+Alt+0). Форма представляє собою основу для розташування елементів керування. Перейти в режим коду можна декількома способами: натиснути праву кнопку миші в будь-якій частині форми та вибрати в контекстному меню View Code; або у вікні Solution Explore зробити те саме на компоненті Form1.h; або просто двічі клацнути мишею по формі – і при цьому автоматично згенерується метод Form1_Load().
Вікно Toolbox (панель компонентів, Ctrl+Alt+x) містить компоненти Windows-форм, які також називаються елементами керування, що розміщуються на формі.
Структура проекту програми Windows Forms Application
По замовчанню структура проекту складається з таких файлів:
myprogram.cpp (назва файлу така ж як назва проекту) це базовий файл, що містить основну функцію програми.
// директиви препроцесора
#include "stdafx.h"
#include "Form1.h"
// доступ до простору імен myprogram
using namespace myprogram;
// атрибути
[STAThreadAttribute]
// основна функція main
int main(array<System::String ^> ^args)
{
// Встановлення Windows XP візуальних ефектів
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
// Створення основного вікна та його запуск
Application::Run(gcnew Form1());
return 0;
}
Form1.h заголовний файл, програмний код якого описує клас Form1 для представлення вікна програми. Зазначимо, що цей клас визначений у власному просторі імен myprogram.
#pragma once
namespace myprogram {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
public ref class Form1 : public System::Windows::Forms::Form
{
public:
Form1(void)
{ InitializeComponent(); }
protected:
~Form1()
{
if (components) { delete components; }
}
private:
System::ComponentModel::Container ^components;
#pragma region Windows Form Designer generated code
void InitializeComponent(void)
{
this->components = gcnew System::ComponentModel::
Container();
this->Size = System::Drawing::Size(300,300);
this->Text = L"Form1";
this->Padding = System::Windows::Forms::Padding(0);
this->AutoScaleMode = System::Windows::Forms::
AutoScaleMode::Font;
}
#pragma endregion
};
}
У конструкторові форми викликається функція InitializeComponent(), визначення якої розміщується в кінці класу. Ця функція визначає параметри вікна програми та компонентів, що додаються у форму. Згідно наведених у програмі коментаріїв, цей розділ коду не варто модифікувати з допомогою редактора коду, оскільки він автоматично обновлюється при інтерактивній зміні вікна програми.
Перша стрічка коду цієї функції відповідає за відслідковування компонентів, що поступово додаються у форму. Тобто в члені components класу Form1 зберігається дескриптор об’єкту Container, у якому в списку зберігаються компоненти графічного інтерфейсу користувача. Решта операторів функції визначають властивості форми, які можна змінювати у вікні Properties (Властивості) форми рис. 2.3.
AssemblyInfo.cpp файл атрибутів рівня зборки проекту.
stdafx.h, stdafx.cpp файли, необхідні для попередньої компіляції.
myprogram.vcproj основний проектний файл VC++, у якому міститься інформація про версію Visual C++, платформу, конфігурацію та властивості проекту.
Вікно властивостей Properties (Alt+Enter) – основний інструмент налаштування форми та її компонентів (рис. 2.3). Вміст цього вікна представляє собою весь список властивостей вибраної у цей момент компоненти чи форми.
Рис. 2.3. Вікно Properties об’єкту Form1
У таблиці 2.1 наведений опис деяких властивостей форми, що переважно визначаються в режимі дизайну. При виборі значення властивості, відмінної від прийнятої по замовчанню, вона виділяється жирним шрифтом, що полегшує в подальшому визначення внесених змін.
Таблиця 2.1. Деякі властивості форми
Властивість
Опис
Name
Назва форми в проекті. Це не заголовок форми, а ім’я класу форми (наприклад, ref class Form1).
BackColor
Колір форми.
BackgroundImage
Зображення на задньому фоні.
ControlBox
Встановлює наявність / відсутність кнопок у верхньому правому куті форми: «Згорнути», «Розгорнути», «Закрити».
Cursor
Встановлює вид курсору при його знаходженні на формі.
Font
Форматування шрифту.
FormBorderStyle
Визначення вигляду границь форми. Можливі варіанти:
None – форма без границь та стрічки заголовку;
FixedSingle – тонкі границі без можливості зміни розміру користувачем;
Fixed3D – границі без можливості зміни розміру з трьохмірним ефектом;
FixedDialog – границі без можливості зміни та без іконки;
Sizable –звичайні границі: користувач може їх змінювати;
FixedToolWindow – фіксовані границі, у наявності лише кнопка закриття форми;
SizableToolWindow – границі з можливістю зміни розмірів, в наявності лише кнопка закриття форми.
Icon
Зображення іконки, що розміщується у заголовку форми.
MaximizeBox
Визначає активність кнопки «Розгорнути» у верх. прав. куті.
MaximumSize
Максимальний розмір ширини та висоти форми в пікселях. Форма буде приймати вказаний розмір при натисненні на кнопку «Розгорнути».
MinimizeBox
Визначає активність кнопки «Згорнути» у верх. прав. куті.
MinimumSize
Мінімальний розмір ширини та висоти форми в пікселях. Форма буде приймати вказаний розмір при зміні її границь користувачем (якщо властивість FormBorderStyle= Sizable).
Size
Ширина та висота форми.
StartPosition
Визначення розташування форми при запуску програми. Можливі варіанти:
Manual – форма з’являється у верх. лівому куті екрану;
CenterScreen – у центрі екрану;
WindowsDefaultLocation – розташування форми по замовчанню. Якщо користувач змінив розміри форми, то при наступному її запуску вона буди мати той самий вигляд та розташування;
WindowsDefaultBounds – границі форми приймають фіксований розмір;
CenterParent – у центрі батьківської форми.
Text
Заголовок форми.
WindowState
Визначення положення форми при запуску. Можливі варіанти:
Normal – форма запускається з розмірами, вказаними у властивості Size;
Minimized – форма запускається з мінімальними розмірами, вказаними у властивості MinimumSize;
Maximized – форма розгортається у весь екран.
Процес візуальної побудови графічного інтерфейсу користувача зводиться до простого перетягування в режимі Form Design необхідних елементів керування на робочу форму та встановлення у вікні Property значень їх властивостей. При цьому автоматично генерується код для добавлених елементів керування у вигляді членів класу Form1, а у функції InitialiseComponent() розміщується код ініціалізації кожного із цих об’єктів.
// у середині класу Form1, наприклад, оголошення елемента мітки
private: System::Windows::Forms::Label^ label1;
// ініціалізація мітки у функції InitialiseComponent
void InitializeComponent(void)
{ //………… // label1
this->label1->AutoSize = true;
this->label1->Location = System::Drawing::Point(68, 92);
this->label1->Name = L"label1";
this->label1->Size = System::Drawing::Size(35, 13);
this->label1->TabIndex = 2;
this->label1->Text = L"label1";
Для реалізації поставленої задачі перед програмою та взаємодії користувача з графічним інтерфейсом необхідно створити функції оброблення подій. Середовище IDE автоматично генерує скелет цих функцій та реєструє їх за допомогою делегатів подій.
Делегати та події.
Подія (event) – це член класу, який дає можливість об’єкту сигналізувати про настання визначеної події, а процес сигналізації для події передбачає використання делегату (delegate). Делегат – це об’єкт, що інкапсулює один чи більше вказівників на функції із заданим списком параметрів та типом повернення. Таким чином, делегат представляє собою в C++/CLI засіб подібний вказівнику на функцію в звичайному С++.
Оголошення делегата виглядає як прототип функції, якому передує ключове слово delegate, і при цьому задає вказівникове ім’я типу об’єкту делегата та список параметрів і тип повернення функції, яка може бути асоційована з делегатом. Делегат є об’єктом класу System::Delegate, і, відповідно, успадковує члени цього класу. Оголошення делегата може виглядати так:
public delegate void Handler (int value);
Для заданого типу делегата (у нашому випадку Handler) можемо створювати об’єкти делегатів цього типу. При цьому конструктор делегата може приймати один або два аргументи. У першому випадку цим єдиним аргументом може бути глобальна функція або статична функція-член класу зі списком параметрів і типом повернення як в оголошенні делегата.
void Sun1 (int value) { ……. }
void Sun2 (int value) { ……. }
Handler^ handler = gcnew Handler (Sun1); //Об’єкт делегату
Виклик делегата можемо здійснювати одним зі способів
handler –> Invoke (25);
handler (25); // спрощений варіант попереднього оператора
і при цьому здійснюється виклик всіх функцій, що є в списку делегата.
Для типів делегатів операція «+» є перевантаженою, щоби об’єднувати списки викликів для двох делегатів у новий делегат. Щоби модифікувати список викликів делегата hendler та добавити в нього виклик функції Sun2 необхідно написати такий код
handler += gcnew Handler (Sun2);
Тепер при виклику делегата hendler виконаються послідовно обидві функції Sun1() та Sun2().
Для виключення зі списку викликів делегата певної функції необхідно використати операцію «–=»
handler –= gcnew Handler (Sun1);
Конструктор делегата з двома аргументами використовується для виклику членів-функцій вказаних об’єктів.
public ref class Planet {
void Venus (int value) { ……. }
void Mars (int value) { ……. }
}
//………
Planet^ obj = gcnew Planet; //cтворення об’єкту типу Planet
Handler^ handler2 = gcnew Handler (obj, & Planet :: Venus); //ств-ння делегату
handler2 += gcnew Handler (obj, & Planet :: Mars); // додавання ф-ції Mars
handler2 (35); //виклик делегату
Як уже було сказано раніше, сигналізація про події передбачає використання делегата, що містить вказівники на функцій, які повинні бути викликані при настанні визначеної події. Більшість подій пов’язані з елементами керування на зразок кнопок чи меню та ініціалізуються в процесі взаємодії користувача з кодом програми.
Подія – це член вказівникового класу, який оголошується з ключовим словом event та іменем класу-делегату.
public delegate void TreeHandler (int value); //Оголошення делегату
// Клас зі членом-подією
public ref class Tree {
public:
event TreeHandler^ woodpecker;
void TriggerEvents () // функція для збудження подій
{ woodpecker (22); woodpecker (33); }
};
Оголосимо клас, що містить функції для оброблення події woodpecker
public ref class ReactionTree {
public:
void Day (int m) { Console::WriteLine(L"число дня {0}",m); }
void Night (int m) { Console::WriteLine(L"число ночі {0}",m); }
};
Тепер ми можемо створити об’єкт типу Tree та зареєструвати функції, що приймають повідомлення про подію woodpecker.
Tree^ appletree = gcnew Tree; // створення об’єкту типу Tree
ReactionTree^ reaction = gcnew ReactionTree; // створення об’єкту обробки
appletree->woodpecker += gcnew TreeHandler (reaction, & ReactionTree :: Day);
appletree->TriggerEvents(); //ініціалізація події woodpecker
У реальному житті делегат – це дипломатичний представник, що наділений особливими повноваженнями своєї організації. Керівництво організації наперед визначає, які функції (методи) повинен виконати делегат: наприклад, здійснити щорічну перевірку філіалу, які параметри необхідно передати (передати пакет документів) і що отримати у відповідь (отримати щорічну звітність). Подією, що ініціалізує роботу делегата, може бути закінчення робочого року. Організація може володіти декількома філіалами й не мати представлення на етапі планування, куди відправиться цей співробітник у якості делегата.
Коли ми розміщуємо на формі кнопку, ми знаємо, що при появі події – натисненні на кнопку – щось повинно відбутися: кнопка повинна повідомити об’єкту чи об’єктам, що ми її натиснули. Однак, ці об’єкти ще можуть бути не визначені. Замість того аби прив’язувати кнопку до конкретної події, ми пов’язуємо події кнопки з делегатом, а коли програма буде виконуватися, призначимо делегатом той метод, який буде необхідний.
Слід зазначити, що платформа .NET має велику кількість вбудованих подій, доступ до яких здійснюється по їх назві. Більше того, саме середовище пов’язує, наприклад для події Click (натиснення мишею по формі), обробника та необхідний метод, використовуючи вбудований делегат EventHandler:
this->Click += gcnew System::EventHandler(this, &Form1::Form1_Click);
Платформа .NET потребує точної сигнатури для будь-якого обробника подій. Form1_Click () та всі інші обробники подій повинні обов’язково виглядати так:
System::Void Form1_Click(System::Object^ sender, System::EventArgs^ e) {
// код для оброблення події
}
У створеному нами проекті в режимі Form Design розмістимо на формі 2 елементи мітки. Для цього необхідно перейти у вікно Toolbox (Ctrl+Alt+x) та вибрати мишею цей елемент , а потім розмістити його на формі, натиснувши мишею у визначеному місці форми (рис. 2.4). Далі вибираємо мишею першу мітку label1 та у вікні Properties (лівий Alt+Enter) змінюємо величину шрифту на 16 кегель (рис. 2.5). Аналогічно змінюємо шрифт і для другої мітки.
Зберігаємо проект програми та запускаємо його на виконання . Спостерігаємо вивід Windows-вікна як на рис. 2.4. Закриваємо.
Рис. 2.4. Розміщення елементів керування «мітка» на формі
Рис. 2.5. Зміна розміру шрифту для елементів керування
У режимі Form Design заходимо у вікно Properties (Alt+Enter) та вибираємо мишею в ньому вкладку Events (події) . Далі вибираємо мишею подію Click та двічі натискаємо по ній (рис. 2.6). У результаті чого автоматично згенерується у файлі form1.h функція-обробник події для натиску мишею по формі Form1_Click().
Рис. 2.6. Вкладка подій у вікні Properties
Додамо до неї програмний код, щоб вона виглядала так:
private: System::Void Form1_Click(System::Object^ sender, System::
EventArgs^ e) {
if (dynamic_cast <System::Windows::Forms::MouseEventArgs^> (e)->
Button == System::Windows::Forms::MouseButtons::Left)
{
label1->Text=Convert::ToString(i1);
i1++;
}
if ( dynamic_cast <System::Windows::Forms::MouseEventArgs^>(e)->
Button == System::Windows::Forms::MouseButtons::Right)
{
label2->Text=Convert::ToString(i2);
i2++;
}
}
Одразу після цієї функції запишемо стрічку для оголошення змінних цілого типу, які є членами класу Form1.
int i1, i2;
Зберігаємо проект програми та запускаємо його на виконання . Почергово тиснемо ліву та праву клавіші миші. Спостерігаємо зміну значень в елементах керування label1 та label2. Цей ефект досягається шляхом відслідковування значення об’єкту подій System:: EventArgs^ e. У першому умовному операторові порівнюється значення об’єкту е, приведеного до типу <System::Windows::Forms:: MouseEventArgs^> зі значенням натиску лівої клавіші миші. У другому умовному операторові відбувається аналогічне порівняння, але з правою клавішею миші.
У режимі Form Design розмістимо на формі такі елементи: Label та 2 елементи Button (рис. 2.7). Для елементу label3 у вікні Properties встановимо значення кеглю шрифта рівним 12, а для властивості Text впишемо стрічку «Ви задоволені своїми знаннями?». Для елементів кнопок також впишемо у властивості Text, відповідно, «Так» для button1, та «Ні» для button2.
Вибираємо на формі елемент button1 та у вкладці Events (події) вікна Properties двічі натискаємо мишею по події MouseMove, і в результаті чого отримуємо автоматично згенеровану функцію-обробник події button1_MouseMove(). Функцію-обробник модифікуємо так:
Рис. 2.7. Розміщення елементів керування на формі
private: System::Void button1_MouseMove(System::Object^ sender, System::
Windows::Forms::MouseEventArgs^ e) {
button1->Top -= e->Y;
button1->Left += e->X;
if (button1->Top < -10 || button1->Top > 100)
button1->Top= 60;
if (button1->Left < -80 || button1->Left > 250)
button1->Left= 120;
}
Знову переходимо в режим Form Design та двічі тиснемо мишею по елементові button1, у результаті чого генеруємо функцію-обробник події button1_Click().Функцію-обробник модифікуємо так:
private: System::Void button1_Click(System::Object^ sender, System::
EventArgs^ e) {
MessageBox::Show("Ви хороший студент", "Похвала",
MessageBoxButtons::OK, MessageBoxIcon::Asterisk);
}
У режимі Form Design двічі тиснемо мишею по іншому елементові button2, і в результаті чого також генеруємо функцію-обробник події button2_Click(). Цю функцію-обробник модифікуємо так:
private: System::Void button2_Click(System::Object^ sender, System::
EventArgs^ e) {
MessageBox::Show("Значить вчитись треба краще",
"Побажання", MessageBoxButtons::OK,
MessageBoxIcon::Warning);
}
Зберігаємо проект програми та запускаємо його на виконання . Почергово тиснемо мишею по обох кнопка та отримуємо вікна з відповідними повідомленнями. Звичайно, натиснути мишею по першій кнопці задача не з простих.
Знову перейдемо в режим Form Design та розмістимо на формі такі елементи: 3 шт. TextBox та 2 шт. Button (рис. 2.8). Для кнопок button3 та button4 змінюємо їх властивості Text так, щоб вони виглядали як на рисунку.
Рис. 2.8. Розміщення елементів керування на формі
Двічі тиснемо мишею по кнопці button3 (10->2) та у згенеровану функцію-обробник події button3_Click() вписуємо такий код:
private: System::Void button3_Click(System::Object^ sender, System::
EventArgs^ e) {
unsigned int word;
word = Convert :: ToUInt32 ( textBox1->Text);
String^ line = "";
do
{
if (word % 2) line = "1" + line;
else line = "0" + line;
word = word / 2;
}
while (word >= 2);
if (word > 0) line = "1" + line;
textBox2->Text = line;
}
Переходимо в режим Form Design та подвійним натиском миші по кнопці button4 (2->10) генеруємо функцію-обробник події button4_Click(), де вписуємо такий код:
private: System::Void button4_Click(System::Object^ sender, System::
EventArgs^ e) {
unsigned int word, count;
String ^line = textBox2->Text;
count = line->Length - 1; word = 0;
for each (wchar_t ch in line)
{
word += Convert::ToUInt32(ch.ToString())<<count;
count --;
}
textBox3->Text = word.ToString ();
}
Зберігаємо проект програми та запускаємо його на виконання . У верхнє вікно textBox1 вводимо ціле число та тиснемо кнопку «10->2». У середньому вікні textBox2 спостерігаємо вивід цього число в двійковому виді. Тепер тиснемо нижню кнопку «2->10» та споспотерігаємо вивід числа в нижньому вікні textBox3 знову в десятковій формі. У середньому вікні введемо інше число в двійковій формі та натиснемо кнопку «2->10», і, відповідно, у нижньому вікні це число буде відображене в десятковій формі.
У режимі Form Design додамо до форми ще такі елементи: 2 шт. Button , а один TextBox (рис. 2.9).
Рис. 2.9. Розміщення елементів керування на формі
Для елементу textBox4 встановимо властивість Multiline = true та розтягнемо його як на рисунку. Відповідно, для кнопок встановимо надписи «додати» та «відняти». Для широкого вікна textBox4 встановлюємо значення властивості ScrollBars = Vertical;
Подвійним натиском миші по кнопці button5 (додати) генеруємо функцію-обробник події button5_Click(), де вписуємо такий код:
private: System::Void button5_Click(System::Object^ sender, System::
EventArgs^ e) {
array<String^>^ myArr;
myArr = textBox4->Lines;
myArr->Resize(myArr, myArr->Length + 1);
textBox4->Lines = myArr;
textBox4->AppendText(textBox1->Text + "->" + textBox2->Text);
}
Для кнопки button6 (відняти) у режимі Form Design також генеруємо функцію-обробник події button6_Click(), де вписуємо такий код:
private: System::Void button6_Click(System::Object^ sender, System::
EventArgs^ e) {
array<String^>^ myArr;
myArr = textBox4->Lines;
if (myArr->Length != 0)
myArr->Resize(myArr, myArr->Length - 1);
textBox4->Lines=myArr;
}
Зберігаємо проект програми та запускаємо його на виконання . У верхнє вікно textBox1 вводимо ціле число та тиснемо кнопку «10->2». Тепер натискаємо кнопку button5 (додати). У результаті чого у широкому текстовому вікні textBox4 додасться стрічка, яка містить число в десятковій та двійковій формах. Ще декілька раз введемо інші десяткові числа та натиснемо кнопки «10->2» і «додати». У широкому вікні кожного разу додаватиметься стрічка з форматом виводу числа. При натисненні кнопки button6 (відняти) із широкого вікна зникатиме остання стрічка.
Тепер у режимі Form Design спробуємо створити для нашої форми меню. Для цього додамо до форми елемент MenuStrip . Елемент розміститься у верхній частині вікна програми, а також у нижньому контейнері розміститься його іконка. Зліва над елементом керування відобразиться невеличка стрілка. Натиск мишею по ній відкриє спливаюче вікно, як показано на рис. 2.10.
Рис. 2.10. Вікно MenuStrip Tasks
Елемент Insert Standard Items генерує чотири стандартні елементи меню: File, Edit, Tools, Help, що містять списки відповідних пунктів меню. Елемент RenderMode дає можливість вибрати стиль зображення стрічки меню. Опція Dock дає можливість вибрати сторону форми, до якої буде пристикована стрічка меню, або ж залишає стрічку меню у відстикованому стані. Опція GripStyle визначає видимість рамки для переміщування меню. Для переходу в режим налаштування властивостей пунктів меню слід вибрати опцію Edit Items.
Наповнення елементами меню відбувається достатньо просто. Для цього слід просто вписати назву елементу в біле поле з надписом Type Here . Наступні елементи можна вписувати як у нижньому віконці «Type Edit», так і у віконці справа. Заповнимо елементами меню як на рис. 2.11.
Рис. 2.11. Наповнення меню елементами
Оброблення подій для елементів меню аналогічне як і для елемента кнопки. Для цього необхідно двічі натиснути на вибраному елементові, наприклад, з надписом «Лектор» та вписати в згенеровану функцію-обробник події такий код:
private: System::Void лекторToolStripMenuItem_Click(System::Object^ sender,
System::EventArgs^ e) {
MessageBox::Show("Доцент Проць Р.В.", "Лектор",
MessageBoxButtons::OK, MessageBoxIcon::Asterisk);
}
А для елемента з надписом «Викладач лабораторних робіт» згенерувати функцію-обробник події та вписати такий код.
private: System::Void викладачЛабораторнихРобітToolStripMenuItem_Click
(System::Object^ sender, System::EventArgs^ e) {
MessageBox::Show("асистент Павельчак А.Г.",
"Викладач лабораторних робіт",
MessageBoxButtons::OK, MessageBoxIcon::Asterisk);
}
Зберігаємо проект програми та запускаємо його на виконання . Вибираємо один із запрограмованих пунктів меню та спостерігаємо появу додаткового інформаційного вікна.
Для вивчення можливостей інших елементів керування необхідно просто додавати їх у форму та досліджувати їх властивості, користуючись допомогою літератури та довідкою програмного пакету Microsoft Visual Studio 2005.
3. Циклічний кодер
Циклічні коди відносяться до числа блокових систематичних кодів, у яких кожна комбінація кодується самостійно (у вигляді блоку) таким чином, що інформаційні k та контрольні m символи (розряди) завжди знаходяться на визначених місцях. Назва кодів походить від їх циклічних властивостей: якщо – кодове слово циклічного коду, тоді , отримане циклічним зсувом елементів C, також є кодовим словом. Усі циклічні зсуви C, утворюють кодові слова. І як результат циклічної властивості, ці коди володіють значною кількістю структурних зручностей, які можна використати при реалізації операцій кодування та декодування.
Можливість виявлення та виправлення практично любих помилок при відносно малій надлишковості та простій реалізації зробило ці коди широко розповсюдженими. Циклічні коди використовуються в безпровідній телефонії та у мобільному зв’язку.
Теорія циклічних кодів базується на теорії груп та алгебрі многочленів над полем Галуа. Поліном (многочлен), який можна представити у вигляді добутку поліномів нижчих степенів, називають звідним, в протилежному випадку незвідним. Поліноми у полі двійкових чисел називають незвідними, якщо вони діляться без остачі тільки на себе чи на одиницю. Незвідні поліноми можна записати у вигляді алгебричного поліному, або у вигляді двійкових чи десяткових чисел, наприклад
В основу циклічного кодування закладено використання незвідних поліномів , які для циклічних кодів називають твірними поліномами.
Найпростіший спосіб утворення циклічного коду полягає у множенні заданої кодової комбінації на твірний поліном . Недоліком такого підходу є те, що контрольні розряди m будуть розміщені у найрізноманітніших місцях кодової комбінації. Такий підхід вважається не раціональним, і тому використовується спосіб, який розміщує контрольні розряди після інформаційних.
Метод побудови циклічного коду
Множимо вхідну кодову комбінацію на одночлен , що має таку ж степінь, що й твірних поліном
. (3.1)
Ділимо добуток на твірний поліном
, (3.2)
де – частка від ділення, що має той самий степінь, що й поліном ; – залишок від ділення, що має степінь, не більший від (менший, ніж степінь дільника ).
Множачи цей вираз на та переносячи у другу частину рівняння, згідно правил алгебри двійкового поля, тобто без зміни знаку на зворотній, отримуємо
, (3.3)
де – закодоване повідомлення. Звідси
, (3.4)
Приклад:
Зауваження: є певна надлишковість коду, пов’язана з необхідністю визначати кількість розрядів на початку та в кінці алгоритму, тобто в середині циклу do ( while обчислення кількості розрядів виконується двічі.
Формуємо повідомлення циклічного коду (3.4).
4. Циклічний декодер
Ідея виявлення помилок у прийнятому циклічному коді полягає у тому, що при відсутності помилок закодоване повідомлення ділиться на твірний поліном без залишку. При цьому контрольні розряди m відкидаються, а інформаційні розряди k використовуються за призначенням.
Обчислюємо залишок від результату ділення за правилами алгебри двійкового поля (алгоритм знаходження цього залишку аналогічний алгоритму п.2 циклічного кодера).
При робимо висновок, що комбінація прийнята без помилок. Наявність залишку свідчить, що комбінація спотворена.
Якщо , тоді виконуємо процедуру виправлення помилок за такою схемою.
Виконуємо підрахунок ваги залишку , тобто підрахунок кількості «1» у залишку.
Якщо вага залишку рівна чи менша числу помилок, що виправляються , то прийняту комбінацію сумують за модулем 2 із залишком та отримують виправлену комбінацію.
Якщо , то проводять циклічний зсув на один біт вліво та отриману комбінацію знову ділять на твірний поліном . Якщо вага отриманого залишку , то циклічно зсунуту комбінацію сумують із залишком, а потім циклічно зсувають її у зворотну сторону вправо на 1 розряд (повертають на попереднє місце). В результаті отримують виправлену комбінацію.
Якщо після циклічного зсуву на один біт знову , то проводять додаткові зсуви вліво. При цьому після кожного зсуву зсунуту комбінацію ділять на та перевіряють вагу залишку. При виконують дії, вказані в п.b, з тією лиш різницею, що зворотних циклічних зсувів вправо роблять стільки, скільки їх було зроблено вліво.
Вилучаємо контрольні розряди.
Загальний алгоритм побудови циклічного декодера.
Оголошуємо та ініціалізуємо ідентифікатори ( String^ ErrorText; беззнаковий цілий F_X, G_X, P_X, R_X, first_F_X, first_R_X; int всі решта, проміжні змінні чи маски для F_X, R_X мають теж беззнаковий тип).
Встановлюємо початкові значення для таких змінних:
shift = i_cycling = 0; break_R_X =1; (break_R_X ( інформація про наявність помилки, i_cycling ( кількість виконаних циклів )
Зчитуємо закодоване повідомлення у двійковому вигляді.
Далі у циклі виконуємо такий код:
Зауваження: недоліком алгоритму виправлення помилок за допомогою циклічних зсувів є можливість виникнення ситуації зациклення: тобто при циклічному зсуві вліво та діленні на твірний поліном значення ваги W не зменшується, а через певне число циклів повторюється комбінація початкових значень та . Тому для цього ми запам’ятовуємо первинні значення та , та у кожному наступному циклі порівнюємо їх з новими. Якщо зауважуємо співпадіння – формуємо інформацію про помилку та завершуємо процес декодування.
Здійснюємо перевірку на помилку зациклення та виконуємо зворотний циклічний зсув .
Вилучаємо контрольні розряди.
Виводимо декодоване повідомлення у двійковому вигляді.
Виводимо інформацію про наявні помилки у вигляді інформаційного вікна або у компоненті для виводу тексту (наприклад TextBox із заданою опцією Multiline = true).
5. Порядок виконання роботи
Вдома детально вивчити поданий у інструкції довідковий теоретичний матеріал до лабораторної роботи.
У навчальній лабораторії в присутності викладача виконати практичне заняття з розділу 2 (стр. 2) по створенню Windows Forms програм CLR. Необхідний до виконання матеріал виділений сірим маркером.
Згідно варіанту (порядкового номера в журналі викладача) завдання (таблиця 1 та 2), вдома написати програму для реалізації вказаного алгоритму, а в лабораторії вписати програмний код та налагодити цю програму.
Отримані на комп’ютері числові результати представити викладачу.
По результатах виконаної роботи оформити звіт та здати його.
Таблиця 1. Завдання до лабораторної роботи
* перелік спотворень циклічного декодування вибирається з таблиці 2
Завдання
Написати мовою С++ програму, що реалізує алгоритм роботи циклічного кодера та декодера для коду БЧХ, згідно варіанту завдання. Вигляд програми має відповідати рис. 5.1.
Функція кодування зчитує число у двійковому вигляді з вікна №1 (G_X () та виводить закодоване повідомлення у двійковому вигляді у вікно №2 (F_X). Параметри коду БЧХ задаються у середині програми. Відповідно до цих даних вибрати мінімальний по розміру беззнаковий цілий тип.
Функція декодування зчитує закодоване повідомлення у двійковому вигляді з вікна №2 (F_X), а з вікна №4 зчитує у двійковому виді маску з “1” у спотворюваних розрядах, за допомогою якої здійснює інверсію розрядів закодованого повідомлення F_X. Результат декодування виводить у вікно №3 (( G_X). Механізм виявлення та виправлення помилок реалізувати за допомогою алгоритму з циклічними зсувами. Усю необхідну додаткову інформацію виводити у широке інформаційне вікно.
На основі розробленої програми провести дослідження можливостей по виявленню та виправленню помилок для заданого твірного поліному БЧХ. Зняти 10 результатів виконання циклічного кодування-декодування при внесенні спотворень згідно таблиці 2.
* У вхідних даних коду БХЧ: n – довжина закодованого повідомлення, s – кількість помилок, що виправляються, P(x) – твірний поліном. Кількість контрольних бітів визначається із залежності: n = k + m, а запис твірного полінома, представленого у вигляді вісімкових цифр, перетворюється шляхом переводу кожної вісімкової цифри у двійкове число. Наприклад, P(x) = 2467. Цифрі 2 відповідає двійкове число 010, цифрі 4 – 100, цифрі 6 – 110, а цифрі 7 – 111, і остаточно – 10100110111 ( ).
№ п/п
Параметри циклічного коду БЧХ
1
n = 7; k = 4; s = 1; P(x) = 13
2
n = 15; k = 11; s = 1; P(x) = 23
3
n = 15; k = 7; s = 2; P(x) = 721
4
n = 15; k = 5; s = 3; P(x) = 2467
5
n = 31; k = 26; s = 1; P(x) = 45
6
n = 31; k = 21; s = 2; P(x) = 3551
7
n = 31; k = 16; s = 3; P(x) = 107657
8
n = 31; k = 11; s = 5; P(x) = 5423325
9
n = 31; k = 6; s = 7; P(x) = 313365047
10
n = 63; k = 57; s = 1; P(x) = 103
11
n = 63; k = 51; s = 2; P(x) = 12471
12
n = 63; k = 45; s = 3; P(x) = 1701317
13
n = 63; k = 39; s = 4; P(x) = 166623567
14
n = 63; k = 36; s = 5; P(x) = 1033500423
15
n = 63; k = 30; s = 6; P(x) = 157464165547
16
n = 63; k = 24; s = 7; P(x) = 17323260404441
17
n = 63; k = 18; s = 10; P(x) = 1363026512351725
18
n = 63; k = 16; s = 11; P(x) = 6331141367235453
19
n = 63; k = 10; s = 13; P(x) = 472622305527250155
20
n = 63; k = 7; s = 15; P(x) = 5231045543503271737
21
n = 7; k = 4; s = 1; P(x) = 13
22
n = 15; k = 11; s = 1; P(x) = 23
23
n = 15; k = 7; s = 2; P(x) = 721
24
n = 15; k = 5; s = 3; P(x) = 2467
25
n = 31; k = 26; s = 1; P(x) = 45
26
n = 31; k = 21; s = 2; P(x) = 3551
27
n = 31; k = 16; s = 3; P(x) = 107657
28
n = 31; k = 11; s = 5; P(x) = 5423325
29
n = 31; k = 6; s = 7; P(x) = 313365047
30
n = 63; k = 57; s = 1; P(x) = 103
Рис. 5.1. Кінцевий вигляд програми
Таблиця 2.Перелік спотворень
№
п/п
1) без спотворень; 2) спотворився молодший розряд закодованого повідомлення F_X; 3) спотворився старший розряд; 4) спотворилися два молодших розряди; 5) спотворилися два старших розряди; 6-10 набори спотворень вибираються з таблиці згідно № п/п та № групи.
Група 1
Група 2
Група 3
1
6) 0, 2, 3; 7) 4, 5, 6;
8) 4, 5; 9) 1; 10) 2;
6) 1, 3, 5; 7) 3, 5, 6;
8) 2, 3; 9) 3; 10) 1;
6) 0, 1, 5; 7) 1, 2, 6;
8) 1, 2; 9) 2; 10) 3;
2
6) 1, 5, 8; 7) 5, 7, 9;
8) 11, 12; 9) 5; 10) 6;
6) 4, 7, 9; 7) 2, 8, 11;
8) 2, 10; 9) 7; 10) 1;
6) 0, 5, 10; 7) 3,8, 13;
8) 4, 8; 9) 11; 10) 3;
3
6) 0, 2, 13; 7) 4, 5, 6;
8) 2, 8; 9) 11; 10) 5;
6) 1, 3, 11; 7) 3, 5, 6;
8) 8, 10; 9) 8; 10) 6;
6) 0, 1, 9; 7) 1, 2, 6;
8) 8, 13; 9) 4; 10) 9;
4
6) 5,6,7,8; 7) 1,2,3;
8) 7, 8; 9) 11; 10) 12;
6) 6,7,8,9; 7) 3,4,5;
8) 4, 8; 9) 10; 10) 2;
6) 2,3,4,5; 7) 1,3,8;
8) 8, 9; 9) 4; 10) 12;
5
6) 1,12, 5; 7) 0, 2, 9;
8) 2, 25; 9) 15; 10) 6;
6) 2,8,26; 7) 1, 8, 12;
8) 7, 21; 9) 12; 10) 7;
6) 8,15,24; 7) 4,9,20;
8) 3, 26; 9) 14; 10) 5;
6
6) 5, 6, 25; 7) 1,6,15;
8) 5, 15; 9) 24; 10) 8;
6) 2,15,24; 7) 1,8,21;
8) 3, 21; 9) 22; 10) 6;
6) 3,14,20; 7) 1,9,19;
8) 5, 18; 9) 8; 10) 25;
7
6) 1,3,5,6; 7) 0, 2, 9;
8) 2, 25; 9) 15; 10) 6;
6) 2,7,8,9; 7) 1,8,12;
8) 7, 21; 9) 12; 10) 7;
6) 3,4,8,9; 7) 4,9,20;
8) 3, 26; 9) 14; 10) 5;
8
6) 0,5,6,7,18,29; 7) 1,6,7,8,9,15; 8) 5, 15, 16, 17; 9) 24; 10) 8;
6) 2,15,16,17,18,22; 7) 1,8,9,11,16; 8) 3, 4,21; 9) 22; 10) 6;
6) 3,14,15,17,19,21; 7) 1,9,19,21,25; 8) 5, 6,7,18; 9) 8; 10) 25;
9
6) 1,2,3,4,5,6,7,18; 7) 0,2,9,11,12,25;
8) 2, 25; 9) 15; 10) 6;
6) 1,2,7,8,9,12,21,27; 7) 1,8,12,13,15,19;
8) 7, 21; 9) 12; 10) 7;
6) 0,1,2,3,6,7,18,24; 7) 4,9,20,21,23,26;
8) 3, 26; 9) 14; 10) 5;
10
6) 1,12,35; 7) 0,2,49;
8) 2, 25; 9) 15; 10) 6;
6) 2,8,56; 7) 1,48,52;
8) 7, 21; 9) 12; 10) 7;
6) 8,15,54; 7) 4,9,50;
8) 3, 26; 9) 14; 10) 5;
11
6) 5,16,55; 7) 1,6,52;
8) 5, 15; 9) 24; 10) 8;
6) 2,15,54; 7) 1,8,51;
8) 3, 21; 9) 22; 10) 6;
6) 3,44,50; 7) 1,9,59;
8) 5, 18; 9) 8; 10) 25;
12
6) 1,3,5,6; 7) 0, 2, 9;
8) 2, 25; 9) 15; 10) 6;
6) 2,7,8,9; 7) 1,8,12;
8) 7,...