C _Учебник_МОНУ
.pdfПрограмування базових алгоритмів |
99 |
(чи обидва) з них дорівнює 1, то відповідний біт результату встановлюється в 1, інакше – біт результату дорівнює 0. Наприклад, 10102 | 10012 = 10112.
Операція побітове логічне “виключне АБО” (^) порівнює кожен біт першого операнда з відповідним бітом другого операнда і, якщо обидва опрацьовувані біти мають однакове значення, результат дорівнює 0, у решті випадків –
1. Наприклад, 10102 ^ 10012 = 00112.
Наведемо приклади виконування побітових логічних операцій.
short i=0x45FF, |
// i= 0100 0101 1111 1111 |
|
r, |
j=0x00FF; |
// j= 0000 0000 1111 1111 |
r = |
i ^ j; |
// r=0x4500 = 0100 0101 0000 0000 |
r = |
i | j; |
// r=0x45FF = 0100 0101 0000 0000 |
r = i & j |
// r=0x00FF = 0000 0000 1111 1111 |
|
short n, i = 0xAB00, j = 0xABCD; |
||
n = i & j; |
// У результаті n = AB00 (шістнадцяткове) |
|
n = i | j; |
// У результаті n = ABCD (шістнадцяткове) |
|
n = i ^ j; |
// У результаті n = CD (шістнадцяткове) |
Операції побітового зсуву >> і << виконують зсув бітів лівого операнда на кількість розрядів, зазначену правим операндом, відповідно праворуч чи ліворуч. Значення бітів, яких бракує, доповнюються нулями. При виконанні операції зсуву можуть втрачатися старші чи молодші розряди:
>> – побітовий зсув праворуч на задану кількість бітів (65 >> 2 = 16, оскільки число 65 = 4116 = 0100 00012 після зсуву праворуч становить 0001 00002 = = 1016 = 16). Операція є еквівалентна до цілочисельного поділу на 2 у відповідному степені (65 / 4 = 16);
<< – побітовий зсув ліворуч (13 << 2 = 20, оскільки число 13 = D16 = 11012 після зсуву ліворуч становить 11 01002 = 3416 = 52). Операція є еквівалентна до цілочисельного множення на 2 у відповідному степені (13 * 4 = 52). Слід пам‟ятати, що при цьому є можливе втрачання старших розрядів.
Наведемо кілька прикладів роботи операцій зсуву.
int с = |
12, m, n; |
|
m = c >> |
2; |
// m=6 |
n = c << |
2; |
// n=24 |
c = n >> |
3 |
// c=24/23=24/8=3 |
int i = |
0x1234, j, k ; |
|
k = i << |
4; |
// k=0x0234 |
j = i << |
8; |
// j=0x3400 |
i = j >> |
8; |
// i=0x0034 |
unsigned |
int x = 0x00AA, y = 0x5500, z; |
z = (x << 8) + (y >> 8);
В останньому прикладі x зсувається ліворуч на 8 позицій, а y – праворуч на 8 позицій. Результати зсувів додаються, утворюючи величину 0xAA55, котра присвоюється z.
Застосовування операцій >> та << почергово до однієї й тієї самої змінної може спричинити змінення її значення через втрату розрядів.
Перетворювання, виконувані операціями зсуву, не забезпечують опрацювання ситуацій переповнення і втрати знаків. Знак першого операнда після ви-
100 |
Розділ 4 |
конання операції зберігається. Результат операції зсуву є невизначений, якщо другий операнд буде від‟ємний.
Побітові операції є зручні для організації зберігання у стислому вигляді інформації про стан on/off (ввімкнено/вимкнено). В одному байті можна зберігати 8 таких “прапорців”. Якщо змінна ch є сховищем таких “прапорців”, то перевірити, чи є “прапорець” третього біту у стані on, можна у такий спосіб:
if (ch & 4) . . .
Ця перевірка базується на двійковому поданні числа 4 = 0000 0100.
Зауважимо, що вираз a ^ a завжди повертає значення 0, а вираз a ^ b ^ a
– значення b. Ці закономірності часто застосовуються у растровій графіці.
4.3.4 Пріоритет логічних операцій
Обчислення в логічних виразах виконуються зліва направо у відповідності з таким пріоритетом операцій:
1)~ , !;
2)>>, <<;
3)<, <=, >, >=;
4)= =, !=;
5)& (побітове “І”);
6)^ (побітове “виключне АБО”);
7)| (побітове “АБО”);
8)&& (“І”);
9)|| (“АБО”).
Вирази у круглих дужках виконуються першочергово.
4.3.5 Пріоритети операцій і порядок обчислень
З урахуванням вищенаведеного пріоритету логічних операцій та пріоритету арифметичних операцій, наведеного в підрозд. 3.5, наведемо загальний пріоритет для всіх операцій мови С в табл. 4.3. Операції с вищими пріоритетами обчислюються першими.
|
|
|
|
Таблиця 4.3 |
|
|
Пріоритет і порядок виконування операцій |
|
|
|
|
|
|
|
Пріоритет |
|
Знак операції |
Тип операції |
Порядок |
|
виконування |
|||
|
|
|
|
|
1 |
::, (), [], ., –> |
вираз |
зліва направо |
|
2 |
–, ~, !, *, &, ++, --, |
унарні |
справа наліво |
|
|
sizeof, (<тип>) |
|
|
|
3 |
*, |
/, % |
мультиплікативні |
|
4 |
+, |
– |
адитивні |
|
5 |
<<, >> |
зсув |
зліва направо |
|
6 |
<, >, <=, >= |
відношень |
|
|
7 |
==, != |
відношень (порівнянь) |
|
|
Програмування базових алгоритмів |
101 |
|
|
|
|
Продовження табл. 4.3 |
|
|
|
|
|
|
|
Пріоритет |
Знак операції |
Тип операції |
Порядок |
|
виконування |
|
|||
|
|
|
|
|
8 |
& |
побітове “І” |
|
|
9 |
^ |
побітове “виключне АБО” |
|
|
10 |
| |
побітове “АБО” |
зліва направо |
|
11 |
&& |
логічне “І” |
|
|
|
|
|||
12 |
|| |
логічне “АБО” |
|
|
13 |
? : |
умовна |
|
|
14 |
=, *=, /=, %=, +=, –=, |
просте і складені |
справа наліво |
|
|
&=, |=, >>=, <<=, ^= |
присвоювання |
|
|
15 |
, |
послідовне обчислення |
зліва направо |
|
4.3.6 Умовний оператор if
Оператор if має дві форми: скорочену та повну.
Скорочена форма має вигляд: if (<умова>) <оператор>;
Якщо значення логічного виразу в умові є ненульове, тобто умова є істинна, то виконується оператор чи група операторів в операторних дужках {}, інакше відбудеться перехід на наступний оператор.
Ні
Умова? Так
Оператор
Повна форма цього оператора: |
Умова? |
Ні |
|
|
|
|
|
if (<умова>) <оператор1>; |
Так |
|
|
else <оператор2>; |
|
|
|
Оператор1 |
|
Оператор2 |
|
Якщо значення логічного виразу в умові |
|
||
|
|
|
|
|
|
|
|
є ненульове, тобто умова є істинна, то викону- |
|
|
|
ється оператор1 чи група операторів в операторних дужках {}, інакше – виконується оператор2, після чого відбудеться перехід на наступний оператор. Зауважимо, що обчислюється лише один з операторів, а не обидва.
Наприклад, обчислення значення виразу
|
1 b |
x |
за |
x b; |
||
|
|
|
||||
y x b |
за |
x b |
||||
|
|
|
|
|
||
|
|
|
|
|||
b x |
|
|
можна реалізувати чи то двома операторами if скороченої форми, чи одним оператором if повної форми:
1)if(x == b) y = 1 + pow(b, x); if(x != b) y = (x + b)/(b – x);
2)if(x == 0) y = 1 + pow(b, x); else y = (x + b)/(b – x);
102 |
Розділ 4 |
Зауважимо, що умову (х 0) можна записати чи то як (х != 0), чи як (х). І, навпаки, для того щоб перевірити, чи дорівнює нулю певне число х, умова може мати вид (x==0) чи (!x).
Окрім того, слід розрізняти вирази в умовах типу if(х = = 5) . . .;
та
if(х = 5) . . .;
Обидва ці оператори є працездатними, оскільки в С++ будь-який вираз, який має певне числове значення, може використовуватися в умовних операторах. Але, якщо у першому випадку значення логічного виразу може бути як істинним, так і хибним, залежно від значення змінної х, то у другому випадку значення логічного виразу завжди є істинне, оскільки в результаті присвоювання значення х = 5 – ненульове.
Наведемо кілька прикладів використання умовного оператора if.
1) Обчислити частку від ділення двох дійсних чисел, якщо це є можливо.
if(y!=0) |
// Якщо знаменник не 0, можна обчислити. |
r = x / y; |
|
Це приклад скороченої форми умовного оператора (без гілки “інакше”). 2) Обчислити квадратний корінь числа, якщо це є можливо.
if(x>=0) |
// Якщо під коренем додатне число, можна обчислити, |
y = sqrt(x); |
|
else |
// інакше – виводимо повідомлення, що обчислити неможливо. |
ShowMessage("Обчислити неможливо!");
Це приклад повної форми умовного оператора (з гілкою “інакше”).
3) Якщо змінні x та y є однаковими, обчислити їхній добуток, інакше – обчислити модуль їх різниці.
if(x == y) r = x * y; else r = fabs(x - y);
4) Якщо модуль змінних x та y є менше за 10, збільшити їх удвічі; інакше – зменшити їх удвічі.
if(fabs(x)<10 && fabs(y)<10) { x=x*2;
y=y*2;
}
else
{x=x/2;
y=y/2;
}
У цьому прикладі, оскільки за істинності умови має виконуватись набір з двох команд, ці команди слід записати в операторних дужках {}.
Команди в операторних дужках {} називаються блоком команд.
Умовні оператори можуть бути необмежено вкладеними один в одного. У деяких випадках складно розібратися, в якій послідовності виконуються такі вкладені оператори. Вельми часто зустрічається використовування конструкції
Програмування базових алгоритмів |
103 |
if – else – if. Приміром, щоб визначити знак змінної x (вона може бути додатною, від‟ємною чи нулем), можна використовувати три простих незалежних команди if:
if(x>0) ShowMessage("positive"); if(x<0) ShowMessage("negative"); if(x==0) ShowMessage("zero");
чи оператор if – else вкладеної конструкції:
if (x>0) ShowMessage("positive"); else
if (x<0) ShowMessage("negative"); else ShowMessage("zero");
Тут, якщо спрацював перший else, це означає, що x є від‟ємним числом чи нульовим. Тому слід перевірити обидві гілки за допомогою ще однієї команди if.
Обчислення функції
sin( x a)
cos x 2 y
arctg2 ax
1
за x 2;
за 2 x 3;
за x 3, a 0;
за x 3, a 0,
аналогічно до попереднього прикладу, можна реалізувати чи то за допомогою чотирьох операторів if скороченої форми, чи оператором if – else вкладеної конструкції:
1) if (x <= –2) y = sin(x + a);
if (x > –2 && x <= 3) y = cos(pow(x – M_PI, 2)); if (x > 3 && a != 0) y = pow(atan(x / a), 2); if (x > 3 && a = = 0) y = 1;
2)if (x <= –2) y = sin(x + a); else
if (x <= 3) y = cos(pow(x – M_PI, 2)); else
if (a != 0) y = pow(atan(x / a), 2); else y = 1;
Уконструкціях if – else – if умови операторів if перевіряються зверху донизу. Тільки-но якась з умов набуває ненульового значення, одразу виконуватиметься оператор, який слідує за цією умовою, а останню частину конструкції буде проігноровано.
Слід записувати подібні вкладені оператори максимально наочно, використовуючи відступи з пропусків, уникати заплутаних складових і великого рівня вкладеності.
104 |
Розділ 4 |
Приклади створювання проектів програм з розгалуженою структурою, організованих за допомогою оператора if
|
|
x2 |
8 |
за |
x 4; |
|
|||||
Приклад 4.11 Ввести х та обчислити |
|
|
|
за |
4 x 0; |
|
|||||
y 3x 2 |
|
||||||||||
|
|
2 x |
|
за |
x 0. |
|
|||||
|
|
|
|
|
|
|
|
|
|
|
|
Розв‟язок. Робочий вигляд |
Початок |
|
|
|
|
|
|
|
|
|
|
форми і блок-схема: |
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
х |
|
|
|
|
|
|
|
|
|
|
|
|
Так |
|
|
|
|
|
|
|
|
|
|
x 4 |
|
y = x2 – 8 |
|
|
n = 1 |
||||
|
|
|
|
|
|
|
|||||
|
Ні |
|
Так |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
4 x 0 |
|
|
|
|
|
|
|
||
|
|
y = 3x – 2 |
|
|
|
n = 2 |
|||||
|
|
|
|
|
|
||||||
|
Ні |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
y = 2 – x |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
n = 3 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
y, n
Кінець
Текст програмного коду:
void __fastcall TForm1::Button1Click(TObject *Sender)
{int n; double y, x = StrToFloat(Edit1–>Text); if(x <= –4) { y = x*x – 8; n = 1;}
else |
|
|
if(–4 < x && x < 0) |
{ y = 3*x – 2; n = 2;} |
|
else |
{ y = 2 – |
x; n = 3;} |
Edit2–>Text = "Виконано умову №" + IntToStr(n) +
" y="+FloatToStr(y);
}
Приклад 4.12 Ввести значення координат (х, у) точки площини і визначити, до якої чверті площини належить ця точка.
Програмування базових алгоритмів |
105 |
Текст програми:
void __fastcall TForm1::Button1Click(TObject *Sender) {float x = StrToFloat(Edit1->Text);
float y = StrToFloat(Edit2->Text); int nomer;
if((x==0)||(y==0)) {ShowMessage("Точка лежить на осі");
Edit3->Clear(); return;
}
else
if(x>0 && y>0) nomer = 1; else
if(x<0 && y>0) nomer = 2; else
if(x<0 && y<0) nomer=3; else
nomer = 4; Edit3->Text = IntToStr(nomer);
}
Функція ShowMessage(); – призначена для виведення на екран діалогового вікна з текстом відповідного повідомлення та однією командною кнопкою ОК, при натисканні на яку вікно повідомлення зникає.
Приклад 4.13 Перевести оцінку по 100-бальній системі до 5-бальної за алгоритмом: оцінка менша за 60 відповідає незадовільній оцінці “2”; в межах від 60 до 79 – оцінці “3”; від 80 до 94 – “4”; розпочинаючи з 95 і до 100 – “5”.
Зауважимо, що в різних вузах можливі незначні відмінності від наведеного алгоритму.
Текст програми:
void __fastcall TForm1::Button1Click(TObject *Sender)
{int m100, m5; m100=StrToInt(Edit1->Text); if(m100>=95) m5=5; if(m100>=80 && m100<95) m5=4;
if(m100>=60 && m100<80) m5=3; if(m100<60) m5=2; Edit2->Text=IntToStr(m5);
}
106 |
Розділ 4 |
Аналогічна програма із вкладеною конструкцією if – else – if: void __fastcall TForm1::Button1Click(TObject *Sender)
{int m100, m5; m100=StrToInt(Edit1->Text); if(m100>=95) m5=5;
else
if(m100>=80) m5=4; else
if(m100>=60) m5=3; else m5=2;
Edit2->Text=IntToStr(m5);
}
У цьому варіанті програми немає потреби перевіряти праву межу інтервалів.
Приклад 4.14 Створити програмний проект для обчислення опору електричного кола, яке складається з двох з‟єднаних опорів, залежно від виду їхнього з‟єднання: паралельне чи послідовне (формули див. у прикладі 4.7).
Розв‟язок. Тобто вдосконалимо розв‟язок прикладу 4.4. Обирання виду
з‟єднаних опорів сформуємо за допомогою компонента RadioGroup , який дозволяє обирати лише одне зі значень списку, “вмикаючи” відповідну радіокнопку напроти елемента списку. Значення усіх елементів списку (видів з‟єднаних опорів) слід записати до властивості Items. Кількість елементів списку визначає кількість радіокнопок. Номер обраного елемента (нумерація починаючи з нуля) записується до властивості ItemIndex. Деталі роботи з компотнентом RadioGroup наведено також у табл. 2.2 та прикладі 4.24.
Текст програми:
void __fastcall TForm1::Button1Click(TObject *Sender)
{float r1, r2, R;
r1=StrToFloat(Edit1->Text); r2=StrToFloat(Edit2->Text); if(RadioGroup1->ItemIndex==0)
R=r1*r2/(r1+r2); else R=r1+r2;
Edit3->Text=FloatToStr(R);
}
Програмування базових алгоритмів |
107 |
Приклад 4.15 Створити програмний проект для обчислення коренів квадратного рівняння ax2 bx c 0. Передбачити перевірку наявності можливих коренів, тобто перевірку, чи є дискримінант додатним.
Текст програми:
void __fastcall TForm1::Button1Click(TObject *Sender) {double a, b, c, D, x1, x2; a=StrToFloat(Edit1->Text); b=StrToFloat(Edit2->Text); c=StrToFloat(Edit3->Text);
D=b*b-4*a*c; if(D<0)
{Edit4->Clear(); Edit5->Clear();
ShowMessage("Коренів немає!");
}
else
{x1=(-b+sqrt(D))/(2*a); x2=(-b-sqrt(D))/(2*a); Edit4->Text=FloatToStr(x1);
Edit5->Text=FloatToStr(x2);
}
}
Приклад 4.16 Створити програмний проект для визначення координат та координатної чверті (квадранта) точки, яку задаватиме користувач.
Розв‟язок. Посеред форми розташуємо два компоненти Bevel (закладка Additional) як координатні осі, для яких слід змінити значення властивості Shape на значення bsBottomLine та bsRightLine, щоби вони набули вигляду горизонтальної та вертикальної ліній. За допомогою компонента StatusBar1 (закладка Win32) внизу форми у першій панелі цього компонента виводитимуться динамічно змінювані координати переміщення курсора. Точку користувач зможе поставити, просто клацнувши мишею. При цьому на другій панелі компонента StatusBar1 виводитимуться її координати та квадрант. Зображення точки задамо компонентом Shape1, встановивши для властивості Shape значення stCircle, а її розмір у 10 пікселів – властивостями Width та Height.
108 |
Розділ 4 |
Текст програми:
int x, y, Xt, Yt; |
// Координати курсура і точки |
|
//----------- |
Подія форми на пересування миші ------------------ |
void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift, int X, int Y)
{// Координати пов‟язуємо з центром форми x=X-Form1->Width/2; y=Form1->Height/2-Y;
// Виведення динамічно змінюваних координат переміщення курсора
StatusBar1->Panels->Items[0]->Text=" X="+IntToStr(x)+
" Y="+IntToStr(y);
Xt=X; Yt=Y;
}
//----------- Подія форми на клацання миші --------------------
void __fastcall TForm1::FormClick(TObject *Sender)
{ Shape1->Left=Xt - Shape1->Width/2;// Горизонтальна координата точки Shape1->Top=Yt - Shape1->Height/2;// Вертикальна координата точки
Shape1->Visible = 1; |
// Увімкнення видимості точки |
String s; |
|
if(x>0 && y>0) s="1 чверть"; |
// Визначення квадранта точки |
if(x<0 && y>0) s="2 чверть"; |
|
if(x<0 && y<0) s="3 чверть"; |
|
if(x>0 && y<0) s="4 чверть"; |
|
// Виведення координат точки у другій панелі компонента StatusBar1
StatusBar1->Panels->Items[1]->Text="Координати точки: X="+IntToStr(x)+" Y="+IntToStr(y)+" "+s;
}
Приклад 4.17 Обчислити силу струму І на ділянці електричного ланцюга довжиною L за формулою
|
2 |
|
|
|
|
|
2 L |
|
|
|
|
|
|
|
1 |
|
|
||||
sin |
|
LT cos |
|
|
|
за |
0 L |
|
|
; |
|||||||||||
|
|
|
|
||||||||||||||||||
|
|
|
|
|
|
|
|
T |
|
|
|
|
|
|
|
3 |
|
||||
|
2 |
T |
|
|
2 |
1 |
|
|
|
1 |
|
|
2 |
|
|||||||
I sin |
|
|
|
cos |
|
|
|
|
за |
|
|
|
|
L |
|
|
; |
||||
|
|
|
|
|
|
|
|
|
|
||||||||||||
|
|
|
L |
|
|
|
TL |
|
3 |
|
3 |
|
|||||||||
|
sin 2 |
1 |
cos2 LT |
|
|
|
2 |
L 1. |
|||||||||||||
eLT |
за |
|
|
||||||||||||||||||
|
|
|
|
||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
TL |
|
|
|
|
|
|
|
3 |
|
|
|
|
Значення періоду T та довжини L ввести з клавiатури.
Текст програми:
void __fastcall TForm1::Button1Click(TObject *Sender)
{float I, T=StrToFloat(Edit1->Text), L=StrToFloat(Edit2->Text);
//Обчислення сили струму за умовою
if ((L>=0)&&(L<=1./3)) I=sin(L*T)-cos(L/T); else
if (L<=2./3) I=sin(T/L)+cos(1./(T*L)); else
if (L<=1) I=exp(L*T)*(pow(sin(1./(T*L)),2)-pow(cos(L*T),2));
Edit3->Text = FloatToStr(I); // Виведення сили струму І
}