Приклад 15.1. Обробити відомість успішності групи студентів, які здавали в сесію іспити з математики,фізики і програмування, та вивести відомість успішності з зазначенням середнього бала кожного студента з усіх предметів, середнього бала з кожного предмета, середнього бала групи з усіх предметів, відмінників, а також за запитом— інформації про студента.
Програмну реалізацію частини умов даного завдання на С++ наведено у прикладі 8.1(частина І).
Для розв’язання задачі в системі С++ Builder спочатку необхідно описати структуру, наприклад, таким чином:
struct stud
{ AnsiString fam;
int mat,fiz,prg;
float sb;
float sf( )
{ float s = (mat + fiz+prg)/3.0; return s; }
} ved[5];
де stud — ім’я типу структура;
fam — прізвище студента;
mat, fiz, prg — оцінки з математики, фізики, програмування;
sb — середній бал;
sf( ) — функція-метод для обчислення значення середнього бала;
ved — ім’я масиву типу структура, що обробляється.
Розташуємо на формі такі компоненти:
- Label1 — для виведення заголовка «Ведомость успеваемости»;
- Label2 — для виведення заголовка «Средний балл группы»;
- Label3 — для виведення заголовка «Отличники»;
- Label4 — для виведення прізвищ відмінників;
- Label5 — для підказки «Введите фамилию студента»;
- Edit1 — для введення прізвища студента і виведення його успішності;
- StringGrid — для введення даних і для виведення відомості успішності;
- Button1 — для створення відомості (для створення події «Создать»);
- BitBtn1 — для закриття додатка;
- BitBtn2 — для підтвердження введення прізвища студента.
Форма і програмний код мають такий вигляд:
#include <vcl.h> #pragma hdrstop #include <Dialogs.hpp> #include "UnStruct_1.h" #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; struct Tstud //--------------- описание структуры { AnsiString fam; int mat, fiz, prg; float sb; float sf() // функция для вычисления среднего балла { float s = (mat+fiz+prg)/3.0; return s; } } ved[30]; int i, k, kol; //описание глобалышх переменных //---------------------------------------------------------------------------------------------- Void_fastcall TForm1: :TForm1 (TComponent* Owner) : TForm(Owner) { } //---------------------------------- заполнение заголовка таблицы void_ fastcall TForm1::FormCreate(TObject *Sender) { Tb->Cells[0][0]="N"; Тb->Сеlls[1][0]="ФИО"; Tb->Cells[2] [0]="Математ."; Tb->Cells [3] [0]=" Физика "; Tb->Cells[4][0]="Прогр."; Тb->Сеlls[5][0]="Ср.балл"; } //------------------------------------------------------------------------ void_ fastcall TForm1::Button1Click(TObject *Sender) { float sbp, sbg; AnsiString str=InputBox("Ведомость успеваемости", "Введите кол-во студентов"," "); kol=StrToInt(str); /* создание массива структур, здесь данные из таблицы переносятся в массив типа структура */ for (і = 0; і < kol; i++) { ved[i].fam = Tb->Cells[l][i+1]; ved[i].mat = StrToInt(Tb->Cells[2][i+1]); ved[i].fiz = StrToInt(Tb->Cells[3] [i+1]); ved[i].prg = StrToInt(Tb->Cells[4][i+1]); ved[i].sb = ved[i].sf(); // вызов функции sf() Tb->Cells[5][i+l]=FloatToStrF(ved[i].sb,ffFixed,4,2); } //------------------------ подсчет ср. балла по каждому предмету Tb->Cells[1][kol+1] = " Ср.балл по предметам"; sbg = 0; //sbg — для подсчёта среднего балла группы for (k = 2; k <= 4; k++) { sbp=0; // средний балл по предмету for (і = 1; і <= kol; i++) sbp += StrToFloat(Tb->Cells[k][i]); Tb->Cells [k] [kol+1]=FloatToStrF( sbp/kol,ffFixed,5,2); sbg += sbp/kol; //средний балл группы } Labe12->Саption="Ср.балл группы="+ FloatToStrF ( sbg/3 .ffFixed ,5,2 ); //----------------------- определение и вывод фамилий отличников Label4->Caption=" "; k=0; for (і = 0; і < kol; і++) //---------------------------------------- определение отличников if (ved[i].mat==5 && ved[i].fiz==5 && ved[i].prg==5) { k++; Label4->Caption=LabeI4->Caption+IntToStr(k)+ ". "+ved[i].fam+'\n'; } //вывод отличников Edit1->SetFocus(); //передача фокуса компоненте Edit } //---------------------- вывод оценок студента заданной фамилии void_ fastcall TForm1::BitBtn2Click(TObject *Sender) { for (і = 1; і <= kol; i++) if (Tb->Cells[1][i]==Edit1->Text) //поиск заданной фамилии Edit1->Text=Tb->Cells[1][i] + ": Математ.-"+Тb->Сеlls[2][і]+ " Физика-" + Tb>Cells[3][i] + " npoгp.-"+Tb->Cells[4][i]; }
Головним компонентом тут є таблиця рядків, тобто компонент StringGrid. Він досить зручний для введення даних типу структура, а також для відображення кінцевого результату. При розміщенні цього компонента на формі бажано в Object Inspector задати такі значення його властивостям:
- Name = Tb; — ім’я таблиці;
- RowCount = 7; — кількість рядків;
- ColCount = 6; — кількість стовпців;
- FixedRows = 1; — кількість фіксованих (заголовних) рядків;
- FixedCols=0; — кількість фіксованих (заголовних) стовпців;
- DefaultRowHigh = 15; — висота рядків;
- DefaultColWidth = 25; — ширина стовпців;
- GridLineWidth = 1; — товщина ліній.
Крім того, у властивості Option треба установити такі значення параметрів:
- goEditing = true; — для ручного редагування таблиці;
- goTab = true; — для переходу по комірках за допомогою клавіші Tab;
- AlwaysShowEditor = true; — відображати редагування.
Для того, щоб мати можливість остаточно установити розміри рядків і колонок за допомогою мишки, треба присвоїти властивостям значення:
- GoRowSizing = true;
- GoColSizing = true;.
Після установки зазначених властивостей необхідно записати додаток на диск, створити оброблювач Form Created() для введення заголовків таблиці шляхом подвійного клацання мишею на формі і написати програмний код першого оброблювача. На зображенні форми видно кількість та призначення всіх рядків і стовпців таблиці. Заповнення таблиці здійснюється після запуску програми на виконання шляхом прямого введення інформації (прізвищ студентів і їхніх оцінок) у відповідних комірках. Стовпець«Ср. балл» і рядок «Ср. по предметам» залишаються порожніми. Вони заповнюються за допомогою програмних засобів після відповідних обчислень, що виконуються при натисканні кнопки «Создать». При цьому здійснюється також виведення прізвищ відмінників навчання.
Для виведення даних щодо успішності окремого студента треба в полі компонентаEdit1 з написом «Фамилия студента» написати прізвище студента і натиснути кнопку«Yes».
Кнопка «Close» припиняє роботу і закриває вікна додатка.
Таким чином, компонент StringGrid служить у даному прикладі як для введення даних, так і для виведення результатів їхньої обробки.
Слід дати пояснення щодо написання програмного коду додатка. Програмний код даного додатка складається з чотирьох оброблювачів подій. Перший з них — FormCreate— служить Для заповнення фіксованого рядка таблиці, що містить заголовки стовпців.
Ця подія виникає першою при запуску програми до натискання кнопки «Створити», завдяки чому до моменту заповнені ня таблиці даними (прізвища, оцінки) заголовки її колонок вже одержують свої значення відповідно до програмного коду»
Під час програмування цього оброблювача, як і інших, треба пам’ятати, що комірки (клітки) — це елементи масиву Cells, які є об’єктом таблиці. Вони починають індексуватися з нульових індексів (Cells [0],[0]), причому першим індексом у цьому масиві є номер стовпця, а другий — номер рядка. Поточні значення в таблиці заповнюються після запуску програми на виконання.
У даній програмі, щоб не писати StringGrid->Cells[ ][ ], імені таблиці присвоєне ім’яТb. Це здійснюється шляхом використання властивісті Name у редакторі Object Inspector.
Другий оброблювач — Button1Click( ) — організує виконання основних операцій з використанням даних, записаних до таблиці. У ньому за допомогою функції InputBox( )здійснюється введення кількості студентів у групі, а в циклі for (…) заповнюється масивVed, елементи якого є структурами. Цей масив, як і сама структура, а також змінні і, k,kol, описано в розділі глобальних даних після інструкції TForm1 *Form1; у заголовку програмного коду, оскільки вони мають бути доступними у всіх оброблювачах.
Структура, що розглядається, містить не тільки поля, але й функцію sf() підрахунку середнього бала студента. Ця функція застосовується в оброблювачі Button1Click( ) при заповненні стовпця «Ср.балл» за допомогою операторів:
ved [i].sb = ved [i].sf( );
Tb->Cells[5][i+1] = FloatToStrF(ved [i].cb, ffFixed, 4,2);.
Слід зауважити, що для підрахунку середнього бала spb з предметів використовуються не елементи масиву ved, а комірки таблиці, а для визначення відмінників — елементи масиву, тобто користувач сам вирішує, що йому зручніше застосовувати в кожному конкретному випадку.
Третій оброблювач служить для закриття додатка, а в четвертому — обробляється подія, що породжується кнопкою «Yes» і служить для виведення всіх оцінок студента, прізвище якого, виведене у вікні Edit.
Використання компонента StringGrid не завжди є оптимальним розв’язанням питання обробки даних типу структура.
Приклад 15.2. Ввести в пам’ять комп’ютера список абонентів телефону і вивести за завданням або весь цей список, або номер телефону заданого абонента та прізвище.
Для введення списку використати функції InputBox(), для виведення списку —компонент Меmо, а для введення прізвища заданого абонента і виведення номера його телефону — компонент Edit.
Розмістимо на формі наступні компоненти:
- Label — для виведення заголовка «Введите фамилию», якщо треба довідатися номер телефону абонента;
- Edit — для введення прізвища абонента і виведення номера його телефону;
- Меmо — для виведення списку абонентів цей компонент спочатку невидимий;
- дві кнопки-перемикачі RadioButton з іменами Rbl і Rb2 та написами відповідно — «Вывод телефона» і «Вывод списка»;
- кнопки Button1 і Button2 для створення подій «Ввод данных»і«Выполнить»;
- кнопка BitBtn — з написом «Close» для виходу з роботи додатка.
Вигляд робочої форми з результатами роботи і програмний код додатка наведено нижче:
У цьому додатку тип структури з ім’ям abonent і масив цього типу sp[n], а також змінна і та константа n описані як глобальні змінні, котрі повинні бути доступними у всіх оброблювачах додатка.
Перший оброблювач служить для реалізації події, що породжена кнопкою Button1 з написом «Ввод». Він містить цикл, що повторюється n разів і за допомогою функціїInputBox( ) здійснює введення прізвища абонента, а потім номер його телефону.
Другий оброблювач події служить для реалізації заданого виду роботи, що визначається за допомогою властивості Checked кнопок Rbl і Rb2. Якщо виконується умова Rbl->Checked (ввімкнена кнопка Rbl — «Вывод телефона»), то здійснюється підготовка компонента Edit1 для введення прізвища. При цьому на формі з’являється цей компонент і підказка, записана в компоненті Label1 — «Введите фамилию», завдяки присвоєнню властивості Visible цих компонентів значення «true». До цього ці компоненти не були видимі, оскільки при їхньому розміщенні на формі властивості Visible було присвоєне значення «false». Крім цього, компоненту Edit1 передається фокус.
Після введення прізвища в поле Edit1 і натискання клавіші Enter включається третій оброблювач KeyDown. У ньому розпізнається момент натискання цієї клавіші, після чого виконується цикл, у якому послідовно порівнюються прізвища раніше введених абонентів із прізвищем, введеним у поле Edit1. Коли вони будуть рівні, в поле Edit1 буде виведене прізвище потрібного абонента і його телефон. Якщо в списку такого прізвища не виявиться, буде виведено: «фамилии нет».
У випадку виконання умови Rb2->Checked (натиснута кнопка Rb2 — «Вывод списка») стане видимим поле виведення компонента Memo1, оскільки його властивостіVisible присвоюється значення «true», і в цьому компоненті виведуться прізвища всіх абонентів та їх телефони.
Радіокнопки Rbl і Rb2 мають таку властивість: коли одна з них вмикається — інша вимикається.
Таким чином, вибір компонентів при розв’язанні задач з використанням даних типу структура залежить від умови задачі і від можливостей користувача.