Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

C _Учебник_МОНУ

.pdf
Скачиваний:
199
Добавлен:
12.05.2015
Размер:
11.12 Mб
Скачать

Програмування базових алгоритмів

119

Приклад 4.27 Визначити за введеною датою день тижня, на який ця дата припадає. Для обчислення користуватися формулою

 

13m 1

y

 

c

 

 

 

d

 

 

y

 

 

 

 

 

2c 777 mod7

,

5

 

 

 

 

 

4

 

4

 

 

 

де d – день місяця;

m – номер місяця, починаючи рахунок від березня, як це робили у Стародавньому Римі (березень – 1, квітень – 2 , …, лютий – 12);

y – рік у столітті;

c – кількість століть.

Квадратні дужки у формулі означають, що слід взяти лише цілу частину від значення у дужках. Обчислене за формулою значення визначає день тижня: 1 – понеділок, 2 – вівторок, …, 6 – субота, 0 – неділя.

Текст програми для консольного додатка:

#include <vcl.h> #pragma hdrstop #include <iostream.h> #include <conio.h>

//-----------------------------------------------------------

#pragma argsused

int main(int argc, char* argv[]) {int day,month,year; // день, місяць, рік

int c, y;

// сторіччя і рік у сторіччі

int m;

// місяць за римським календарем

int d;

// день тижня

puts("Введіть дату: день місяць рік.");

puts("Наприклад, 24 04 2009 "); puts(" ->");

scanf("%i %i %i",&day,&month,&year); if(month==1||month==2)year--;//січень і лютий належать до минулого року

m = month-2;

//рік розпочинається з березня

if(m<=0)m+=12;

//для січня і лютого

c = year/100;

 

y = year - c*100;

d = (day+(13*m-1)/5+y+y/4+c/4-2*c+777)%7; switch(d)

{case 1: puts("Понеділок 1"); break; case 2: puts("Вівторок 2"); break; case 3: puts("Середа 3"); break; case 4: puts("Четвер 4"); break; case 5: puts("П'ятниця 5"); break; case 6: puts("Субота 6"); break;

case 0: puts("Неділя 7");

}

printf("\n Для завершення натисніть <Enter> \n"); getch(); return 0;

}

120

Розділ 4

4.4 Програмування циклічних алгоритмів

4.4.1 Циклічні алгоритми

Обчислювальний процес називається циклічним, якщо він неодноразово повторюється, допоки виконується певна задана умова. Блок повторюваних операторів називають тілом циклу. Існують три різновиди операторів циклу:

оператор циклу for;

оператор циклу з передумовою while;

оператор циклу з післяумовою do-while.

Всі оператори циклу неодмінно містять такі складові частини:

присвоювання початкових значень (ініціалізація);

умова продовження циклу;

тіло циклу;

зміна параметра циклу.

4.4.2 Оператор циклу з параметром for

Цей оператор зазвичай використовується, коли є заздалегідь відома кількість повторювань, або коли умова продовження виконання циклу записується коротким виразом. За приклади використання даного оператора можуть слугувати обчислення сум заданої кількості доданків, пошук мінімального (максимального) елемента послідовності чисел, зчитування рядків Memo, сортування елементів масиву за збільшенням (за зменшенням) тощо.

Синтаксис оператора:

for (<ініціалізація>; <умова>; <модифікації>) <тіло циклу>;

Конструктивно цей оператор складається з трьох основних блоків, розміщених у круглих дужках і відокремлених один від одного крапкою з комою (;), та команд (тіла циклу), які мають багаторазово виконуватись у цьому циклі. На початку виконання оператора циклу одноразово у блоці ініціалізації задаються початкові значення змінних (параметрів), які керують циклом. Потім перевіряється умова і, якщо вона виконується (true чи має ненульове значення), то виконується команда (чи група команд в операторних дужках {}) тіла циклу. Модифікації змінюють параметри циклу і, в разі істинності умови, виконування циклу триває. Якщо умова не виконується (false чи дорівнює нулю), відбувається вихід із циклу і керування передається на оператор, який слідує за оператором for. Суттєвим є те, що перевірка умови виконується на початку циклу.

Це означає, що тіло циклу може не виконуватись жодного

 

 

разу, якщо умова спочатку є хибна. Кожне повторення

s = 0

(крок) циклу називається ітерацією.

 

 

 

 

10

Простий приклад для обчислення суми S i проі-

i 1

люструє використання оператора for:

int s = 0;

for(int i = 1; i <= 10; i++) s += i;

i 1,10

s = s + i

Програмування базових алгоритмів

121

Цей оператор можна прочитати так: “виконати команду s += i 10 разів (для значень і від 1 до 10 включно, де і на кожній ітерації збільшується на 1)”. У наведеному прикладі є два присвоювання початкових значень: s=0 і i=1, умова продовження циклу: (і<=10) і змінення параметра: і++. Тілом циклу є команда s += i.

Порядок виконання цього циклу комп‟ютером є такий:

1)присвоюються початкові значення (s=0, i=1);

2)перевіряється умова (i<=10);

3)якщо умова є істинна (true), виконується команда (чи команди) тіла циклу: до суми, обчисленої на попередній ітерації, додається нове число;

4)параметр циклу збільшується на 1.

Далі повертаємось до пункту 2. Якщо умову у пункті 2 не буде виконано (false), станеться вихід із циклу.

В операторі можливі конструкції, коли є відсутній той чи інший блок: ініціалізація може бути відсутня, якщо початкове значення задати попередньо; умова – якщо припускається, що умова є завжди істинна, тобто слід неодмінно виконувати тіло циклу, допоки не зустрінеться оператор break; а модифікації – якщо приріст параметра здійснювати в тілі циклу чи взагалі це є непотрібне. Тоді сам вираз блока пропускається, але крапка з комою (;) неодмінно має залишитись. Можливою є наявність порожнього оператора (оператор є відсутній) у тілі циклу. Приміром, суму з попереднього прикладу можна обчислити в інший спосіб:

for(int s = 0, i = 1; i <= 10; s += i++);

У цьому прикладі є відсутній оператор, а блок ініціалізації вмістить два оператори, розділених операцією “кома”, які задають початкові значення змінних s та i.

Розглянемо приклади циклів for.

1)Виведення до компонента Memo чисел від 1 до 10 з їхніми квадратами:

for(int i=1; i<11; i++)

Memo1->Lines->Add(IntToStr(i)+ " " + IntToStr(i*i));

Цикл виконується за i = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10. Після цього i набуде значення 11, умова (11<11) не виконується (false) і відбувається вихід з циклу.

2) Виведення додатних непарних цілих від 1 до 100 з їхніми квадратами. Цикл записується аналогічно до попереднього, але параметр збільшуватиметься на 2, тобто цикл виконуватиметься для значень і = 1, 3, 5, 7, …, 97, 99.

for(int i=1; i<100; i+=2) Memo1->Lines->Add(IntToStr(i)+ " " + IntToStr(i*i));

3) Обчислення факторіала F=n! (нагадаємо, що факторіал обчислюється за формулою n! = 1∙2∙3...(n–2)(n–1)n, наприклад: 4! = 1∙2∙3∙4 = 24). Наведемо три аналогічні за дією форми запису оператора for:

1)int F=1, n=5; for(int i=1; i<=n; i++) F *= i;

2)int F, i, n=5; for(F=1, i=1; i<=n; F *= i++);

3)int F=1, i=1, n=5; for( ; i<=n; ) F *= i++;

122

Розділ 4

Для завчасного початку чергової ітерації циклу можна використати оператор переходу до наступної ітерації continue (див. п. 4.4.5), наприклад:

for(i = 0; i < 20; i++)

{if(array[i] == 0) continue; array[i] = 1/array[i]; }

Для завчасного виходу з циклу застосовують оператори break (вихід з конструкції) (див. п. 4.4.5), goto (безумовний перехід) (див. п. 4.3.2) чи return (вихід з поточної функції) (див. підрозд. 8.1).

Деякі варіанти застосування оператора for підвищують його гнучкість за рахунок можливості використання декількох змінних-параметрів циклу.

Наприклад:

int main ( )

{int top, bot;

char string[100], temp;

for ( top=0, bot=98 ; top<bot ; top++, bot--) { temp = string[top];

string[top] = string[bot]; string[bot] = temp;

}

return 0;

}

У цьому прикладі для реалізації записування рядка символів у зворотному порядку параметрами циклу є дві змінні top та bot, значення яких рухаються назустріч один одному. Зауважимо, що у блоці ініціалізації оператора for задаються через кому початкові значення відразу обох змінних (параметрів). Так само через кому записано модифікацію цих змінних після умовного виразу.

Наведемо ще один варіант оператор циклу for, в якому задається початкове значення параметра і, його модифікація, проте в умовному виразі ця змінна фігурує лише як індекс елемента масиву:

for (i=0; t[i]=>0; i++) ;

У цьому операторі параметр циклу і набуде значення номера першого у масиві від‟ємного елемента масиву t. Отже, такий цикл може використовуватись, приміром, для пошуку елементів за певним значенням.

Іншим цікавим варіантом застосування оператора for є нескінчений цикл. Для організації такого циклу можна записати пустий умовний вираз, а для виходу з циклу скористатись умовним оператором if разом з оператором break.

Наприклад:

for ( ; ; ) { . . .

if ( <деяка умова> ) break;

. . .

}

Розглянемо кілька прикладів розв‟язування задач, в яких є доцільне використання оператора циклу for. Для усіх програм розроблено алгоритмічні схе-

Програмування базових алгоритмів

123

ми (блок-схеми), які визначають порядок виконування дій, і наведено форми з результатами обчислень.

Приклади проектів програм з оператором циклу for в С++ Builder

7

x

k 1

Приклад 4.28 Обчислити суму s

 

, значення х ввести з екрана.

2k

 

k 1

k

Розв‟язок. Щоби впевнитися, що сума обчислюватиметься з усіх семи доданків, спочатку виведемо кожен з них, після чого виведемо вже саму суму.

Текст програми:

void __fastcall TForm1::Button1Click(TObject *Sender)

{float u, s = 0, x;

x = StrToFloat(Edit1->Text); Memo1->Clear();

for(int k = 1; k <= 7; k++)

{ u = pow(x, k+1)/(pow(2, k)+k); Memo1->Lines->Add(IntToStr(k)+ ": "+ FormatFloat("0.000", u)); s = s + u;

}

Memo1->Lines->Add("s = " +

FormatFloat("0.000", s));

}

4

(k 1)(k 5)

Приклад 4.29 Обчислити добуток z

k(k 6)

k 2

Початок

Введення

х

S = 0

k 1,7

u xk 1 2k k

Виведення k, u

S S u

Виведення

S

Кінець

. При виконуванні об-

числень не слід враховувати ті множники, в яких чисельник чи знаменник дорівнюють нулю.

Розв‟язок. При обчисленні добутку змінна k почергово набуває таких значень: –2, –1, …, 3, 4. За значення k = –1 утворюється нуль у чисельнику, а отже, весь добуток перетворюється на нуль, а за k = 0 – утворюється нуль у знаменнику. Тому, щоб вилучити ці множники, слід застосувати умовний оператор if, який можна організувати у два способи:

if(k != –1 && k != 0)

z *= (float)(k+1)*(k–5)/(k*(k+6));

або

if(k==0 || k==–1) continue;

else z *= (float)(k+1)*(k–5)/(k*(k+6));

124

Розділ 4

Умову if(k!=0) можна записати простіше,

if(k),

оскільки ненульове

значення розцінюється як true.

 

 

 

 

 

Початок

 

 

 

z = 1

 

 

k 2, 4

Текст програми:

 

Ні

 

void __fastcall TForm1::Button1Click

 

k0, k 1

 

Так

(TObject *Sender)

 

(k 1)(k 5)

{int k;

 

z z

 

 

float p, z = 1;

 

k(k 6)

 

 

for(k = –2; k <= 4; k++)

 

 

 

if(k != –1 && k != 0)

 

 

 

z *= (float)(k+1)*(k–5)/(k*(k+6));

 

 

z

Edit1->Text = "z="+FormatFloat("0.0000",z);

 

 

 

}

 

 

Кінець

 

 

 

Приклад 4.30 Увести десять цілих чисел і визначити кількість непарних. Розв‟язок. Уводитимемо числа до компонента Memo.

Текст програми:

// Кнопка “Розв‟язок”.

void __fastcall TForm1::Button1Click(TObject *Sender) { int i, x, k=0;

int N=Memo1->Lines->Count; // Кількість чисел у Memo1 if(N<10).

{ ShowMessage("Не всі 10 чисел уведено"); return; } for(i=0; i<10; i++)

{ x=StrToInt(Memo1->Lines->Strings[i]); // Зчитування чисел

if(x%2==1) k++;

// і обчислення кількості непарних.

}

 

//Виведення кількості непарних чисел.

Edit1->Text=IntToStr(k);

}

//-----------------------------

// Кнопка “Вихід”.

void __fastcall TForm1:: Button2Click (TObject *Sender)

{ Close();

}

Програмування базових алгоритмів

125

Приклад 4.31 Увести цілі числа у Memo і обчислити середнє арифметичне ненульових одноцифрових чисел.

Розв‟язок. Спочатку у циклі обчислимо суму та кількість ненульових одноцифрових чисел, а вже за циклом розділимо цю суму на кількість.

Для зчитування чисел з Memo використовуватимемо змінну х, для суми – зміннуsum, для кількості – змінну k і для середнього арифметичного – aver.

Текст програми:

void __fastcall TForm1::Button1Click(TObject *Sender)

{ float aver, sum=0;

int x, k=0, i, n;

n=Memo1->Lines->Count;

// n – кількість рядків у Memo1

if(n==0)

// Якщо чисел у Memo1 нема, припинити обчислення

{ShowMessage ("Введіть числа в Memo1"); return;}

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

// Повторити n разів (послідовно для кожного числа)

{x=StrToInt(Memo1->Lines->Strings[i]); //Зчитати число з Memo1

if(x>-10 && x<10 && x!=0)

// Якщо x – ненульове одноцифрове число,

{sum+=x; k++; }

// додаємо його до суми sum і збільшуємо кількість на 1

}

 

 

if(k!=0)

// Якщо такі числа є,

{ aver=sum/k;

// обчислити середнє арифметичне,

Edit1->Text=FormatFloat("0.00",aver);

}

 

 

else

// інакше – вивести повідомлення

{Edit1->Clear();

ShowMessage("Ненульових одноцифрових чисел нема");

}}

Приклад 4.32 Увести цілі в Memo і визначити, чи є серед них від‟ємні парні числа. Результат вивести у вигляді повідомлення.

Розв‟язок. Для того щоб визначити, чи є в Memo від‟ємні парні числа, можна обчислити їхню кількість, як це було зроблено у попередньому прикладі, і якщо ця кількість є більше за 0, можна стверджувати, що є як мінімум одне таке число, інакше – таких чисел немає. Однак, якщо відшукали перше від‟ємне парне число, немає потреби у перевірці решти чисел з Memo1, можна одразу вивести повідомлення про результат і зупинити виконання програми за допомогою

126

Розділ 4

команди return. Якщо жодного від‟ємного парного числа не віднайдено, то по завершенні циклу виконуватиметься наступна команда, яка виведе повідомлення про відсутність шуканих елементів.

Текст програми:

void __fastcall TForm1::Button1Click(TObject *Sender) { int x, i, n=Memo1->Lines->Count;

if(n==0) {ShowMessage ("Нема чисел у Memo1"); return;} for(i=0; i<n; i++)

{ x=StrToInt(Memo1->Lines->Strings[i]);

if(x<0 && x%2==0) // Якщо x – від‟ємне парне число,

{ ShowMessage("Від’ємне парне число є!"); // вивести повідомлення return; // і зупинити виконування Button1Click.

} }

ShowMessage("Від’ємного парного числа нема!");

}

Приклад 4.33 Скласти програму табулювання функції y = f(x) при змінюванні х від А до B з кроком h, коли f(x) = 3 cos2 x .

Розв‟язок. Досить часто при дослідженні функціональних залежностей виникає потреба побудови графіка y = f(x) чи обчислення значень y = f(x) на заданому проміжку х [А, B] з кроком h.

Для побудови графіка функції розташуємо на формі компонент Chart, розміщений на закладці Additional. Для налагодження компонента Chart слід двічі клацнути на зображенні цього компонента. У діалоговому вікні, яке з‟явиться, слід клацнути по кнопці Add. З додаткового діалогового вікна оберемо тип графіка Line. Для збільшення розміру графіка на формі можна вилучити зображення “легенди”, для чого слід перейти на закладку Legend, в позиції Visible вилучити “галочку”. З аналогічною метою можна перейти на закладку Titles і видалити надпис TChart, а можна просто змінити надпис графіка, наприклад на “Графік функції”.

У наведеному нижче прикладі програми табулювання заданої функції початковими даними, які слід ввести із компонентів Edit1, Edit2 та Edit3, є початкове А і кінцеве В значення х, а також крок змінювання х – h.

Програмування базових алгоритмів

127

У циклі, починаючи з x=А і допоки буде істинна умова x<=B+0.1*h, обчислюється значення функції у і виводиться її числове значення до компонента Memo1 і на графік Series1, після чого x збільшується на значення кроку x+=h. Незначна величина 0.1*h, яка не перевищує величини кроку, в умові використовується з тієї причини, що при обчисленні існує так зване накопичення похибки обчислень, наприклад, коли 4 3,9999(9). У такому разі останнє значення х та y не виводились би на форму. Виведення точок на графік здійснюється за допомогою методу AddXY(x,y,"",clRed). Чотири параметри в дужках для цього методу задають параметри точки, що виводиться: перше значення x – координата по горизонтальній осі, друге значення y – координата по вертикальній осі, третій параметр задає параметри відображення числових значень на осях (двоє порожніх лапок " " означають, що підписи формуватимуться автоматично), четвертий параметр задає колір точки. Колір (color) записують після символів cl з великої літери; так, clRed задає червоний колір, clBlue – синій, clGreen – зелений тощо.

Текст програми:

void __fastcall TForm1::Button1Click(TObject *Sender)

{ float A, B, h, x, y; Memo1->Clear(); Series1->Clear(); A = StrToFloat(Edit1->Text);

B = StrToFloat(Edit2->Text);

h = StrToFloat(Edit3->Text);

for (x = A; x <= B + 0.1 * h; x += h)

{y = pow(pow(cos(fabs(x)), 2), (float)1./ 3); Memo1->Lines->Add(FormatFloat("0.00",x)+" "+

FormatFloat("0.0000",y));

Series1->AddXY(x, y, "", clRed);

}

}

128

Розділ 4

Приклад 4.34 Написати програму обчислення напруги ланцюга R(t), яка змінюється упродовж певного часу t за законом:

e t n cos nt R t

e tn 1 sin n 1 t

якщо t змінюється на проміжку клавіатури.

Текст програми:

за

0 t

 

;

 

 

 

2

 

за

 

t .

2

[0, π] з кроком h = π/20. Параметр n ввести з

void __fastcall TForm1::Button1Click(TObject *Sender)

{Memo1->Clear(); Series1->Clear(); int n=StrToInt(Edit1->Text); float t, R, h=M_PI/20;

for(t=0; t<=M_PI+0.01*h; t+=h)

{if (t>=0 && t<M_PI/2) R=exp(-t/n)*cos(n*t); else

if (t<=M_PI) R=exp(-t/(n+1))*sin((n-1)*t); Memo1->Lines->Add(FormatFloat("0.000", t)+" " +

FormatFloat("0.0000", R));

Series1->AddXY( t, R, "", clRed);

}

}

//------------------------------------------------------------

void __fastcall TForm1::Button2Click(TObject *Sender) { Edit1->Clear(); Memo1->Clear(); Series1->Clear(); }

//------------------------------------------------------------

void __fastcall TForm1::Button3Click(TObject *Sender) { Close(); }

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]