У попередньому прикладі, в програмі контролю ваги, множинний вибір був реалізований за допомогою вкладених одна в іншу інструкцій if. Такий підхід не завжди зручний, особливо в тому випадку, якщо кількість варіантів ходу програми велике.
У мові Delphi є інструкція case, яка дозволяє ефективно реалізувати множинний вибір. У загальному вигляді вона записується в такий спосіб:
case Селектор of спісок1: begin {Інструкції 1} end; спісок2: begin {Інструкції 2} end; спісокМ: begin {Інструкції N} end; else begin {Інструкції) end; end;
де:
- Селектор – вираз, значення якого визначає подальший хід виконання програми (т. е. послідовність інструкцій, яка буде виконана);
- Список N – список констант. Якщо константи представляють собою діапазон чисел, то замість списку можна вказати першу і останню константу діапазону, розділивши їх двома точками. наприклад, список 1, 2, 3, 4, 5, 6 може бути замінений діапазоном 1..6.
Виконується інструкція case наступним чином:
- спочатку обчислюється значення виразу-селектора.
- Значення виразу-селектора послідовно порівнюється з константами зі списків констант.
- Якщо значення виразу збігається з константою зі списку, то виконується відповідна цьому списку група інструкцій. На цьому виконання інструкції САSЕ завершується.
- Якщо значення виразу-селектора не збігається з жодною константою з усіх списків, то виконується послідовність інструкцій, наступна за else.
Синтаксис інструкції case дозволяє не писати else і відповідну послідовність інструкцій. В цьому випадку, якщо значення виразу не збігається з жодною константою з всіх списків, то виконується наступна за case інструкція програми.
На рис. 2.7 наведено алгоритм, реалізований інструкцією case.
Рис. 2.7. Алгоритм, реалізований інструкцією case Нижче наведені приклади інструкції case.
case n_day of 1,2,3,4,5: day: = 'Робочий день. '; 6: day: = 'Cyббoтa!'; 7: day: = 'Воскресіння!'; end; case n_day of 1..5: day: = 'Робочий день.'; 6: day: = 'субота!'; 7: day: = 'Воскресіння!'; end; case n_day of 6: day: = 'субота!'; 7: day: = 'Воскресіння!'; else day: = 'Робочий день.'; end;
Як приклад використання інструкції case розглянемо програму, яка перераховує вагу з фунтів в кілограми. Програма враховує, що в різних країнах фунт “важить” по різному. Наприклад, в Росії фунт дорівнює 409,5 грамів, в Англії – 453,592 грами, а в Німеччині, Данії та Ісландії фунт важить 500 грамів.
У діалоговому вікні програми, зображеному на рис. 2.8, для вибору країни використовується список Країна.
Рис. 2.8. Діалогове вікно програми Приклад використання case
Для вибору назви країни використовується список – компонент ListBox. Значок компонента ListBox знаходиться на вкладці Standard (рис. 2.9). Додається список до форми додатка точно так же, як і інші компоненти, наприклад, командна кнопка або поле редагування. У табл. 2.5 наведені властивості компонента ListBox.
Табліца2.5. Властивості компонента ListBox
Властивість | Визначає |
Name | Ім’я компонента. В програмі використовується для доступу до властивостей компонента |
Items | Елементи списку |
Itemindex | Номер вибраного елемента списку. Номер першого елемента списку дорівнює нулю |
Left | Відстань від лівої межі списку до лівої межі форми |
Top | Відстань від верхньої кордони списку до верхньої межі форми |
Height | Висоту поля списку |
Width | Ширину поля списку |
Font | Шрифт, використовуваний для відображення елементів списку |
Parent-Font | Ознака успадкування властивостей шрифту батьківської форми |
Найбільший інтерес представляють властивості Items і Itemindex. Властивість items містить елементи списку.
Властивість itemindex задає номер обраного елемента списку. Якщо жоден з елементів не обраний, то значення властивості рівне мінус одиниці.
Список може бути сформований під час створення форми або під час роботи програми.
Для формування списку під час створення форми треба у вікні Object Inspector вибрати властивість items і клацнути на кнопці запуску редактора списку рядків (рис. 2.10).
Рис. 2.10. Кнопка запуску редактора списку
У діалоговому вікні String List Editor (рис. 2.11) потрібно ввести список, набираючи кожного елемент списку в окремому рядку. Після введення чергового елемента списку для переходу до нового рядка необхідно натиснути клавішу & lt; Enter & gt ;. після введення останнього елемента клавішу ” Enter “натискати не треба. Завершивши введення списку, слід клацнути на кнопці ОК.
У табл. 2.6 перераховані компоненти форми додатка, а в табл. 2.7 наведені значення властивостей компонентів.
Таблиця 2.6. Компоненти форми
Компонент | Призначення |
ListBoxl | Для вибору країни, для якої треба виконати перерахунок |
Editl | Для введення ваги у фунтах |
Label1, Label2, Label3 | Для виведення пояснювального тексту про призначення полів введення |
Label4 | Для виведення результату перерахунку |
Button1 | Для активізації процедури перерахунку ваги з фунтів в кілограми |
Таблиця 2.7. Значення властивостей компонентів
Властивість | Значення |
Form1 .Caption | Приклад використання case |
Editl. Text | |
Label1. Caption | Виберіть країну, введіть кількість фунтів і клацніть на кнопці Обчислити |
Label2 .Caption | Країна |
Label3. Caption | Фунтів |
Button1. Caption | Обчислити |
Процедура перерахунку, яка виконується в результаті клацання на командній кнопці Обчислити, примножує вага в фунтах на коефіцієнт, що дорівнює кількості кілограмів в одному фунті. значення коефіцієнта визначається за номером обраного зі списку елемента.
У лістингу 2.3 приведений текст програми перерахунку ваги з фунтів в кілограми.
Лістинг 2.3. Перерахунок ваги з фунтів в кілограми
unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = Class (TForm) Label2: TLabel; Editl: TEdit; // поле введення ваги у фунтах Button1: TButton; // кнопка Обчислити Label1: TLabel; LabelS: TLabel; ListBox1: TListBox; // список країн Label4: TLabel; // поле виведення рез-та - ваги в кілограмах procedure FqrmCreate (Sender: TObject); procedure ButtonlClick (Sender: TObject); private { Private declarations} public {Public declarations} end; var Form1: TForml; implementation {$ R * .DFM} procedure TForml.FormCreate (Sender: TObject); begin { ListBox1.items.add ( 'Росія'); ListBox1.items.add ( 'Австрія'); ListBox1.iterns.add ( 'Англія'); ListBox1.items.add ( 'Німеччина'); ListBox1.iterns.add ( 'Данія'); ListBoxl.iterns.add ( 'Ісландія'); ListBox1.iterns.add ( 'Італія'); ListBox1.items.add ( 'Нідерланди'); } ListBox1.itemindex: = 0; end; procedure TForm1.ButtonlClick (Sender: TObject); var funt: real; // вагу в фунтах kg: real; // вагу в кілограмах k: real; // коефіцієнт перерахунку begin case ListBoxl.Itemindex of 0: k: = 0.4095; // Росія 1: k: = 0.453592; // Англія 2: k: = 0.56001; // Австрія 3..5,7: k: = 0.5; // Німеччина, Данія, Ісландія, Нідерланди 6: k: = 0.31762; // Італія end; funt: = StrToFloat (Editl.Text); kg: = k * funt; label4.caption: = Editl.Text + 'Ф. - це ' + FloatToStrF (kg, ffFixed, 6,3) + 'кг.'; end; end.
Слід звернути увагу на процедуру обробки події FormCreate, яке відбувається в момент створення форми (форма створюється автоматично при запуску програми). Цю процедуру можна використовувати для ініціалізації змінних програми, в тому числі і для додавання елементів в список. У наведеному тексті програми інструкції створення списку закоментовані, т. к. список був створений за допомогою редактора рядків під час створення форми.
Розглянемо ще один приклад використання інструкції case. При виведенні числової інформації з поясняющим текстом виникає проблема узгодження виведеного значення і закінчення поясняющего тексту.
Наприклад, в залежності від числового значення пояснювальний текст до грошової величиною може бути: “рубль”, “ рублів“ або “рубля “ (123 рубля, 120 рублів, 121 рубль). Очевидно, що закінчення поясняющего слова визначається останньою цифрою числа, що відображено в табл. 2.8.
Таблиця 2.8. Залежність закінчення тексту від останньої цифри числа
Цифра | Пояснювальний текст |
0, 5, 6, 7, 8, 9 | рублів |
1 | Рубль |
2,3,4 | Рубля |
Наведене в таблиці правило має виняток для чисел, що закінчуються на 11, 12, 13, 14. Для них пояснювальний текст повинен бути “рублів”.
Діалогове вікно програми наведено на рис. 2.12, а текст – в лістингу 2.4. Пояснювальний текст формує процедура обробки події onKeyPress.
Рис. 2.12. Діалогове вікно програми
Лістинг 2.4. формування поясняющего тексту
unit. rub_l; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = Class (TForm) Label1: TLabel; Editl: TEdit; Label2: TLabel; procedure EditlKeyPress (Sender: TObject; var Key: Char); private {Private declarations} public {Public declarations} end; var Form1: TForm1; implementation {$ R * .dfm} // натискання клавіші procedure TForm1.Edit1KeyPress (Sender: TObject; var Key: Char) var n : Integer; // число r : Integer; // залишок від ділення n на 10 text: string [10]; // формується пояснювальний текст begin if Key = chr (VK_RETURN) then begin n : = StrToInt (Editl.Text); if n & gt; 100 then n: = n mod 100; if (N & gt; = 11) and (n & lt; = 14) then text: = ' рублів ' else begin r: = n mod 10; case r of 1: text: = 'рубль'; 2 .. 4: text: = 'рубля'; else text: = 'рублів'; end; end; Label2.Caption : = IntToStr (n) + text; end; end; end.
Розглянемо фрагмент програми (лістинг 2.5), яка обчислює дату наступного дня, використовуючи сьогоднішню дату, представлену трьома змінними: day (день), month (місяць) і year (рік).
Спочатку за допомогою інструкції сазе перевіряється, чи є поточний день останнім днем місяця. якщо поточний місяць – лютий і якщо поточне число – 28, то додатково виконується перевірка, чи є рік високосним. Для цього обчислюється залишок від ділення року на 4. Якщо залишок дорівнює нулю, то рік високосний, і число 28 не є останнім днем місяця.
Якщо з’ясовується, що поточний день – останній день місяця, то наступне число – перше. Потім перевіряється, чи не є поточний місяць груднем. Якщо немає, то збільшується номер місяця, а якщо так, то збільшується номер року, а номером місяці присвоюється значення 1.
Лістинг 2.5. Обчислення дати наступного дня (фрагмент)
// обчислення дати наступного дня var day: integer; // день month: integer; // місяць year: integer; // рік last: boolean; // якщо день - останній день місяця, // то last = True r: integer; // якщо рік не високосний, то залишок // від ділення year на 4 не дорівнює нулю begin {Змінні day, month і year містять сьогоднішню дату} last : = False; // нехай день - не останній день місяця case month of 4,6,9,11: if day = 30 then last: = True; 2: if day = 28 then begin r: = year mod 4; if r & lt; & gt; 0 then last: = True; end; else: if day = 31 then last: = True; end; if last then begin // останній день місяця day: = 1; if month = 12 then begin // останній місяць month: = 1; year: = year + 1; end else month: = month + 1; end else day: = day + 1; // змінні day, month і year // містять завтрашню дату end;