Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Auto, extern, register, static, mutable 2 страница




}

Розглянемо while -вираз з попередньої програми. Можливо, Вас здивувало, що він складається всього тільки з однієї змінної ch. Але "скринька" тут відкривається просто. Оскільки змінна ch має тут тип unsigned char, то вона може містити значення від 0 до 255. Якщо її значення дорівнює 255, то після інкрементування воно "скидається" в нуль. Отже, факт рівності значення змінної ch нулю слугує зручним способом завершити while -цикл.

Подібно до циклу for, умовний вираз перевіряється під час входу в цикл while, а це означає, що тіло циклу (при помилковому результаті обчислення умовного виразу) може не виконатися жодного разу. Ця властивість циклу усуває необхідність окремого тестування до початку виконання циклу. Наступна програма виводить рядок, що складається з крапок. Кількість виведених крапок дорівнює значенню, яке вводить користувач. Програма не дає змогу виводити рядки, якщо їх довжина перевищує 80 символів. Перевірка на допустимість кількості крапок, що виводяться, виконується усередині умовного виразу циклу, а не зовні.

Код програми 4.13. Демонстрація виведення рядка, що складається з крапок

#include <iostream> // Для потокового введення-виведення

using namespace std; // Використання стандартного простору імен

 

int main ()

{

int len;

cout << "Введіть довжину рядка (від 1 до 79): ";

cin >> len;

while (len>0 && len<80) {

cout << '.';

len--;

}

getch (); return 0;

}

Тіло while -циклу може взагалі не містити жодної настанови. Ось приклад:

while (rand ()!= 100);

Цей цикл виконується доти, доки випадкове число, що генерується функцією rand (), не виявиться таким, що дорівнює числу 100.

4.4.2. Ітераційна настанова do-while

Цикл do-while – це єдиний цикл, який завжди робить ітерацію хоч би один раз.

На відміну від циклів for і while, у яких умова перевіряється під час входу, цикл do-while перевіряє умову при виході з циклу. Це означає, що цикл do-while завжди виконується хоч би один раз. Його загальний формат має такий вигляд:

do {

настанови;

} while (вираз);

Хоча фігурні дужки є необов'язковими, якщо елемент настанови складається тільки з однієї настанови, то вони часто використовують для поліпшення читабельності конструкції do-while, не допускаючи тим самим плутанини з циклом while. Цикл do-while виконується доти, доки залишається істинним елемент вираз, який є умовним виразом.

У наведеному нижче коді програми цикл do-while виконується доти, доки користувач не введе число 100.

Код програми 4.14. Демонстрація механізму використання настанови організації циклу do-while

#include <iostream> // Для потокового введення-виведення

using namespace std; // Використання стандартного простору імен

 

int main ()

{

int num;

do {

cout << "Введіть число (100 – для виходу): ";

cin >> num;

} while (num!= 100);

 

getch (); return 0;

}

Використовуючи цикл do-while, ми можемо ще більше удосконалити програму "Вгадай магічне число". Цього разу програма "не випустить" Вас з циклу вгадування, поки Ви не вгадаєте це число.

Код програми 4.15. Демонстрація програми "Вгадай магічне число": третє удосконалення

#include <iostream> // Для потокового введення-виведення

#include <cstdlib> // Для використання бібліотечних функцій

using namespace std; // Використання стандартного простору імен

 

int main ()

{

int magic; // Магічне число

int guess; // Варіант користувача

magic = rand (); // Отримуємо випадкове число.

do {

cout << "Введіть свій варіант магічного числа: ";

cin >> guess;

if (guess == magic) {

cout << "** Правильно ** ";

cout << magic << " і є те саме магічне число.\n";

}

else {

cout << "Дуже шкода, але Ви помилилися.";

if (guess > magic)

cout << "Ваш варіант перевищує магічне число.\n";

cout << "Ваш варіант менше магічного числа.\n";

}

} while (guess!= magic);

 

getch (); return 0;

}

4.4.3. Використання настанови переходу continue

Настанова continue дає змогу негайно перейти до виконання наступної ітерації циклу.

У мові програмування C++ існує засіб "дострокового" виходу з поточної ітерації циклу. Цим засобом є настанова continue. Вона примусово виконує перехід до наступної ітерації, опускаючи виконання коду програми, що залишився, в поточній. Наприклад, у наведеному нижче коді програми настанову continue використовують для "прискореного" пошуку парних чисел в діапазоні від 0 до 100.

Код програми 4.16. Демонстрація механізму використання настанови переходу continue

#include <iostream> // Для потокового введення-виведення

using namespace std; // Використання стандартного простору імен

 

int main ()

{

int x;

 

for (x=0; x<=100; x++) {

if (x%2) continue;

cout << x << " ";

}

 

getch (); return 0;

}

У цій програмі виводяться тільки парні числа, оскільки внаслідок виявлення непарного числа відбувається передчасний перехід до наступної ітерації, і cout -настанова опускається.

У циклах while і do-while настанова continue передає керування безпосередньо настанові, що перевіряє умовний вираз, після чого циклічний процес триває. А в циклі for після виконання настанови continue спочатку обчислюється інкрементний вираз, а потім – умовний. І тільки після цього циклічний процес буде продовжено.

4.4.4. Використання настанови break для виходу з циклу

Настанова break дає змогу негайно вийти з циклу.

За допомогою настанови break можна організувати негайний вихід з циклу, знехтувавши виконанням коду програми, що залишився в його тілі, і перевірку умовного виразу. Завдяки виявленню усередині циклу настанови break цикл завершується, а керування передається настанові, що є наступною після циклу. Розглянемо простий приклад.

Код програми 4.17. Демонстрація механізму використання настанови break для виходу з циклу

#include <iostream> // Для потокового введення-виведення

using namespace std; // Використання стандартного простору імен

 

int main ()

{

int t;

// Цикл працює для значень t від 0 до 9, а не до 100!

for (t=0; t<100; t++) {

if (t==10) break;

cout << t << " ";

}

 

getch (); return 0;

}

Ця програма виведе на екран числа від 0 до 9, а не до 100, оскільки настанова break при значенні t, що дорівнює 10, забезпечує негайний вихід з циклу.

Настанова break зазвичай використовується в циклах, у яких під час створення особливих умов необхідно забезпечити негайне їх завершення. Такий фрагмент містить приклад ситуації, коли після натиснення клавіші виконання циклу зупиняється:

for (i=0; i<1000; i++) {

// Якісь дії.

if (kbhit()) break;

}

Настанова break призводить до виходу з самого внутрішнього циклу. Розглянемо приклад.

Код програми 4.18. Демонстрація механізму використання настанови break для
виходу з внутрішнього циклу

#include <iostream> // Для потокового введення-виведення

using namespace std; // Використання стандартного простору імен

 

int main ()

{

int t, pm;

for (t=0; t<100; t++) {

pm = 1;

for (;;) {

cout << pm << " ";

pm++;

if (pm==10) break;

}

cout << "\n";

}

 

getch (); return 0;

}

Ця програма 100 разів виводить на екран числа від 0 до 9. Під час кожного виконання настанови break керування передається назад в зовнішній цикл for.

Варто знати! Настанова break, яка завершує виконання настанови switch, впливає тільки на настанову switch, а не на цикл, що містить її.

На прикладі попередньої програми Ви переконалися в тому, що у мові програмування C++ за допомогою настанови for можна організувати нескінченний цикл[16]. Для виходу з нескінченного циклу необхідно використовувати настанову break. Безумовно, настанову break можна використовувати і для завершення нескінченного циклу.

4.4.5. Організація вкладених циклів

Як було продемонстровано на прикладі попередньої програми, один цикл можна вкласти в іншій. У мові програмування C++ дозволено використовувати до 256 рівнів вкладення. Вкладені цикли використовуються для вирішення завдань найрізноманітнішого профілю. Наприклад, у наведеному нижче коді програми вкладений цикл for дає змогу знайти прості числа в діапазоні від 2 до 1000.

Код програми 4.19. Демонстрація виведення простих чисел у діапазоні від 2 до 1000

#include <iostream> // Для потокового введення-виведення

using namespace std; // Використання стандартного простору імен

 

int main ()

{

int i, j;

for (i=2; i<1000; i++) {

for (j=2; j<=(i/j); j++)

if (!(i%j)) break; // Якщо число має множник, значить|означає|

// воно не просте.

if (j>(i/j)) cout << i << " – просте число\n";

}

getch (); return 0;

}

Ця програма визначає, чи є простим число, яке міститься в змінній i, шляхом послідовного його ділення на значення, розташоване між числом 2 і результатом обчислення виразу i/j[17]. Якщо залишок від ділення i/j дорівнює нулю, то це означає, що число i не є простим. Але, якщо внутрішній цикл завершиться повністю (без дострокового завершення роботи з використанням настанови break), то це означає, що поточне значення змінної i дійсно є простим числом.

4.5. Використання настанови безумовного переходу goto

Настанова goto – це С++-настанова безумовного переходу.

Довгі роки ця настанова була непопулярною у програмістів, оскільки сприяла, із їхньої точки зору, створенню "спагетті-коду програми". Проте настанова goto, як і раніше, використовується, і іноді навіть дуже ефективно. У цьому навчальному посібнику не робиться спроба "реабілітації" цієї настанови як одної з форм керування програмою. Понад це, необхідно відзначити, що в будь-якій ситуації (у області програмування) можна обійтися без настанови goto, оскільки вона не є елементом, що забезпечує повноту опису мови програмування. Водночас, у певних ситуаціях її використання може бути дуже корисним. У цьому навчальному посібнику ми вирішили обмежити використання настанови goto межами цього розділу, оскільки, на думку більшості програмістів, вона вносить у програму тільки безлад і робить її практично нечитабельною. Але, оскільки використання настанови goto в деяких випадках може зробити намір програміста зрозумілішим, їй варто приділити певну увагу.

Настанова goto вимагає наявності у програмі мітки. Мітка – це дійсний у мові програмування C++ ідентифікатор, за яким поставлено двокрапку. У процесі виконання настанови goto керування програмою передається настанові, вказаній за допомогою мітки. Мітка повинна знаходитися в одній функції з настановою goto, яка посилається на цю мітку.

Мітка – це ідентифікатор, за яким знаходиться двокрапка.

Наприклад, за допомогою настанови goto і мітки можна організувати такий цикл на 100 ітерацій:

х = 1;

loop1:

x++;

if (x < 100) goto loopl;

Іноді настанову goto варто використовувати для виходу з глибоко вкладених настанов циклу. Для розуміння сказаного розглянемо такий фрагмент коду програми:

for (...) {

for (...) {

while (...){

if (...) goto stop;

...

}

}

}

stop:

cout << "Помилка у програмі.\n";

Щоб замінити настанову goto, довелося б виконати ряд додаткових перевірок. У цьому випадку настанова goto істотно спрощує програмний код. Простим застосуванням настанови break тут не обійшлося, оскільки вона забезпечила б вихід тільки з самого внутрішнього циклу.

Варто знати! Настанову goto необхідно застосовувати обмежено (як сильнодіючі ліки). Якщо без неї Ваш код програми буде менш читабельним або для Вас важлива швидкість виконання програми, то в таких випадках використання настанови goto допустиме.

4.6. Приклад використання настанов керування

Наведений нижче приклад є останньою версією програми "Вгадай магічне число". У ній використано багато засобів С++-програмування, представлених у цьому розділі. Пропонуємо, перш ніж переходити до наступного розділу, переконатися у тому, що добре розумієте всі розглянуті тут елементи мови програмування C++. Цей варіант програми дає змогу згенерувати нове число, зіграти в гру і вийти з програми.

Код програми 4.20. Демонстрація програми "Вгадай магічне число": остання версія

#include <iostream> // Для потокового введення-виведення

#include <cstdlib> // Для використання бібліотечних функцій

using namespace std; // Використання стандартного простору імен

 

void play(int m);

 

int main ()

{

int option;

int magic;

 

magic = rand ();

 

do {

cout << "1. Отримати нове магічне число\n";

cout << "2. Зіграти\n";

cout << "3. Вийти з програми\n";

do {

cout << "Введіть свій варіант: ";

cin >> option;

} while (option<1 || option>3);

switch (option) {

case 1: magic = rand ();

break;

case 2: play(magic);

break;

case 3: cout << "До побачення!\n";

break;

}

} while (option!= 3);

 

getch (); return 0;

}

 

// Зіграємо в гру.

void play(int m)

{

int t, x;

for (t=0; t<100; t++) {

cout << "Вгадайте магічне число: ";

cin >> x;

if (x==m) {

cout << "** Правильно **\n";

return;

}

if (x<m) cout << "Замало.\n";

else cout << "Забагато.\n";

}

cout << "Ви використали всі шанси вгадати магічне число. "

<< "Спробуйте знову.\n";

}

 


Розділ 5. Масиви та рядки – засоби групування взаємопов'язаних між собою змінних

Масив (array) – це перелік змінних однакового типу, звернення до яких відбувається із застосуванням імені, загального для всіх його елементів. У мові програмування C++ масиви можуть бути одно-, дво- та багатовимірними, хоча в основному використовуються одновимірні масиви. Масиви є зручними засобами для групування взаємопов'язаних між собою змінних.

Поряд з числовими найчастіше використовуються символьні масиви, у яких зберігаються рядки. Як ми вже зазначали вище, у мові програмування C++ не визначено вбудованого типу даних для зберігання рядків. Тому рядки реалізуються як масиви символів. Такий підхід до реалізації рядків дає С++-програмісту більше "важелів" керування порівняно з тими мовами, у яких використовується окремий рядковий тип даних.

5.1. Одновимірні|одномірні| масиви

Одновимірний масив – це перелік взаємопов'язаних між собою змінних. Для оголошення одновимірного масиву використовують така форма запису:

тип ім'я_масиву[розмір];

У цьому записі за допомогою елемента запису тип оголошується базовий тип масиву. Базовий тип визначає тип даних кожного елемента, з яких складається масив. Кількість елементів, які зберігатимуться в масиві, визначається елементом розмір. Наприклад, у процесі виконання наведеної нижче настанови оголошується int -масив (що складається з 10 елементів) з іменем sMas:

int sMas[10];

Індекс у прямокутних дужках після імені масиву вказує на конкретний елемент масиву.

Доступ до окремого елемента масиву здійснюється за допомогою індексу, який описує позицію елемента усередині масиву. У мові програмування C++ перший елемент масиву має нульовий індекс. Оскільки масив sMas містить 10 елементів, то його індекси змінюються від 0 до 9. Щоб отримати доступ до елемента масиву за індексом, достатньо вказати потрібний номер елемента в квадратних дужках. Так, наприклад, першим елементом масиву sMas є sMas[0], а останнім – sMas[9]. Розглянемо наведену нижче програму, яка ініціалізує масив sMas квадратами чисел від 1 до 10.

Код програми 5.1. Демонстрація ініціалізації елементів одновимірного масиву

#include <iostream> // Для потокового введення-виведення

using namespace std; // Використання стандартного простору імен

 

int main ()

{

int sMas[10]; // Ця настанова резервує область

// пам'яті для 10 елементів типу int.

int t;

 

// Поміщаємо в масив значення.

for (t=0; t<10; ++t) sMas[t] = (t+1)*(t+1);

 

// Відображається масив.

for (t=0; t<10; ++t) cout << sMas[t] << " ";

 

getch (); return 0;

}

У мові програмування C++ всі масиви займають суміжні елементи пам'яті. Іншими словами, елементи масиву в пам'яті розташовані послідовно один за одним. Клітина з найменшою адресою належить до першого елемента масиву, а з найбільшою – до останнього. Наприклад, після виконання цього фрагмента коду програми

int tMas[7];

int j;

for (j=0; j<7; j++) tMas[j] = j*j;

масив tMas виглядатиме так:

Для одновимірних масивів загальний розмір масиву в байтах обчислюється так:

всього байтів = розмір типу елемента в байтах ´ кількість елементів.

Масиви часто використовують під час програмування, оскільки дають змогу легко обробляти велику кількість взаємопов'язаних між собою змінних. Наприклад, у наведеному нижче коді програми створюється масив з десяти елементів, кожному елементу присвоюється випадкове число, а потім на екрані відображаються мінімальне і максимальне його значення.

Код програми 5.1. Демонстрація оброблення елементів одновимірного масиву

#include <iostream> // Для потокового введення-виведення

#include <cstdlib> // Для використання бібліотечних функцій

using namespace std; // Використання стандартного простору імен

 

int main ()

{

int i, min, max;

int listMas[10];

for (i=0; i<10; i++) listMas[i] = rand ();

 

// Знаходимо|находимо| мінімальне значення.

min = listMas[0];

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

if (min > listMas[i]) min = listMas[i];

cout << "Мінімальне значення: " << min << "\n";

 

// Знаходимо|находимо| максимальне значення.

max = listMas[0];

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

if (max < listMas[i]) max = listMas[i];

cout << "Максимальне значення: " << max << "\n";

 

getch (); return 0;

}

У мові програмування C++ не можна присвоїти один масив іншому. У наведеному нижче коді програми, наприклад, присвоєння aMas = bMas; неприпустимо:

int aMas[10], bMas[10];

//...

aMas = bMas; // Помилка!!!

Щоб помістити вміст одного масиву в інший, необхідно окремо виконати присвоєння кожного значення:

int aMas[10], bMas[10], i;

//...

for (i=1; i<10; i++) aMas[i] = bMas[i]; // Правильно!

//...

5.1.1. На межах масивів "прикордонної застави" немає

У мові програмування C++ не виконується ніякої перевірки "порушення кордонів" масивів, тобто нічого не може перешкодити програмісту звернутися до масиву за його межами. Якщо це відбувається у процесі виконання настанови присвоєння, то можуть бути змінені значення в елементах пам'яті, виділених деяким іншим змінним або навіть Вашій програмі. Іншими словами, звернення до масиву (розміром у N елементів) за межею N-ro елемента може призвести до руйнування програми за відсутності яких-небудь зауважень з боку компілятора і без видачі повідомлень про помилки під час роботи програми. Це означає, що вся відповідальність за дотримання "кордонів" масивів покладається тільки на програмістів, які повинні гарантувати коректну роботу з масивами. Іншими словами, програміст зобов'язаний використовувати масиви достатньо великого розміру, щоб в них можна було без ускладнень поміщати дані. Однак краще за все у програмі передбачити перевірку перетину "кордонів" масивів.

Наприклад, С++-компілятор "мовчки" скомпілює і дасть змогу запустити таку програму на виконання, хоча у ній відбувається вихід за межі масиву cMas.

Обережно! Не виконуйте наведений нижче приклад програми. Це може призвести до руйнування Вашої системи.

Код програми 5.2. Демонстрація некоректного прикладу програми

int main ()

{

int cMas[10], i;

for (i=0; i<100; i++) cMas[i] = i;

 

return 1;

}

У цьому випадку цикл for виконає 100 ітерацій, хоча масив cMas призначений для зберігання тільки десяти елементів. У процесі виконання цієї програми можливий перезапис важливої інформації, що може призвести до аварійної зупинки програми.

Вас, можливо, дивує така "непередбачливість" мови програмування C++, яка виражається у відсутності вбудованих засобів динамічної перевірки на "недоторканність" меж масивів. Нагадаємо, проте, що мова програмування C++ призначена для професійних програмістів, і її завдання – надати їм можливість створювати максимально ефективний програмний код. Будь-яка перевірка коректності доступу засобами мови програмування C++ істотно уповільнює виконання програми. Тому такі дії залишено на розгляд програмістам. Як буде показано далі, у разі потреби програміст може сам визначити тип масиву і закласти у ньому перевірку непорушності меж.

5.1.2. Сортування масиву

Однією з найпоширеніших операцій, що виконуються над масивами, є сортування. Існує багато різних алгоритмів сортування. Широко застосовується, наприклад, сортування перемішуванням і сортування методом Шелла. Відомий також алгоритм Quicksort (швидке сортування з розбиттям початкового набору даних на дві половини так, що будь-який елемент першої половини впорядкований щодо будь-якого елемента другої половини). Проте найпростішим вважають алгоритм сортування методом бульбашок. Незважаючи на те, що бульбашкове сортування не відрізняється високою ефективністю (і справді, його продуктивність неприйнятна для сортування великих масивів), його цілком успішно можна застосовувати для сортування масивів малого розміру.

Алгоритм сортування методом бульбашок отримав свою назву від способу, використовуваного для впорядковування елементів масиву. Тут виконуються операції порівняння, що повторюються, і у разі потреби міняються місцями суміжні елементи. При цьому елементи з меншими значеннями поступово переміщаються до одного кінця масиву, а елементи з великими значеннями – до іншого. Цей процес нагадує поведінку бульбашок повітря в резервуарі з водою. Бульбашкове сортування виконується шляхом декількох проходів по масиву, під час яких у разі потреби здійснюється перестановка елементів, що опинилися "не на своєму місці". Кількість проходів, що гарантують отримання відсортованого масиву, дорівнює кількості елементів у масиві, зменшеному на одиницю.

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

Код програми 5.3. Демонстрація механізму використання методу бульбашок для сортування елементів масиву

#include <iostream> // Для потокового введення-виведення

#include <cstdlib> // Для використання бібліотечних функцій

using namespace std; // Використання стандартного простору імен

 

int main ()

{

int tMas[10];

int a, b, t;

int size;

 

size = 10; // Кількість елементів, що підлягають сортуванню.

 

// Поміщаємо в масив випадкові числа.

for (t=0; t<size; t++) tMas[t] = rand ();

 

// Відображаємо початковий масив.

cout << "Початковий масив: ";

for (t=0; t<size; t++) cout << tMas[t] << " ";

cout << "\n";

 

// Реалізація методу бульбашкового сортування.




Поделиться с друзьями:


Дата добавления: 2014-11-29; Просмотров: 461; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.173 сек.