Студопедия

КАТЕГОРИИ:


Архитектура-(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 3 страница




for (a=1; a<size; a++)

for (b=size-1; b>=a; b--) {

if (tMas[b-1]> tMas[b]) { // Елементи неврегульовані.

// Міняємо елементи місцями.

t = tMas[b-1];

tMas[b-1] = tMas[b];

tMas[b] = t;

}

} // Кінець бульбашкового сортування.

 

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

cout << "Відсортований масив: ";

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

cout << "\n";

 

getch (); return 0;

}

Хоча алгоритм бульбашкового сортування придатний для невеликих масивів, для масивів великого розміру він стає неефективним. Більш універсальним вважають алгоритм Quicksort. У стандартну бібліотеку мови програмування C++ включена функція qsort (), яка реалізує одну з версій цього алгоритму[18]. Але, перш ніж використовувати її, Вам необхідно вивчити більше засобів мови програмування C++.

5.2. Побудова символьних рядків

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

Рядок – це символьний масив, який завершується нульовим символом.

5.2.1. Оголошення рядкового літерала

Оголошуючи масив strMas, що призначається для зберігання 10-символьного рядка, потрібно використовувати таку настанову:

char strMas[11];

Заданий тут розмір (11) дає змогу зарезервувати місце для нульового символу в кінці рядка.

Як ми вже зазначали вище, мова програмування C++ дає змогу визначати рядкові літерали. Пригадаємо, що рядковий літерал – це перелік символів, поміщений в подвійні лапки. Ось декілька прикладів:

"Привіт"

"Мені подобається мова програмування C++"

"#$%@@#$"

""

Рядок, наведений останнім (""), називається нульовим. Він складається тільки з одного нульового символу (ознаки завершення рядка). Нульові рядки використовуються для представлення порожніх рядків.

Програмісту не потрібно вручну добавляти в кінець рядкових констант нульові символи. С++-компілятор робить це автоматично. Отже, рядок "Привіт" в пам'яті розміщується так, як це показано на цьому рисунку:

5.2.2. Зчитування рядків з клавіатури

Найпростіше зчитувати рядок з клавіатури, створивши масив, який прийме цей рядок за допомогою настанови cin. Зчитування рядка, введеного користувачем з клавіатури, відображено у наведеному нижче коді програми.

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

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

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

 

int main ()

{

char strMas[80];

cout << "Введіть рядок: ";

cin >> strMas; // Зчитуємо рядок з клавіатури.

cout << "Ось Ваш рядок: ";

cout << strMas;

 

getch (); return 0;

}

Хоча ця програма формально коректна, однак вона не позбавлена недоліків. Розглянемо такий результат її виконання:

Введіть рядок: Це перевірка

Ось Ваш рядок: Це

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

gets (ім'я_масиву);

Якщо у програмі необхідно зчитувати рядок з клавіатури, то викличте функцію gets (), а як аргумент передайте ім'я масиву, не вказуючи індексу. Після виконання цієї функції заданий масив міститиме текст, введений з клавіатури. Функція gets () зчитує символи, що вводяться користувачем, доти, доки він не натисне на клавішу < Enter >. Для виклику функції gets () у програму необхідно включити заголовок < cstdio >.

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

Код програми 5.5. Демонстрація механізму використання функції gets() для зчитування рядка з клавіатури

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

#include <cstdio> // Для підтримки системи введення-виведення

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

 

int main ()

{

char strMas[80];

cout << "Введіть рядок: ";

gets (strMas); // Зчитуємо рядок з клавіатури.

cout << "Ось Ваш рядок: ";

cout << strMas;

 

getch (); return 0;

}

Цього разу після запуску нової версії програми на виконання і введення з клавіатури тексту "Це простий тест" рядок зчитується повністю, а потім так само повністю і відображається:

Введіть рядок: Це простий тест

Ось Ваш рядок: Це простий тест

У цій програмі звернемо Вашу увагу на таку настанову:

cout << strMas;

У цьому записі (замість звичного літерала) використовують ім'я рядкового масиву. І хоча причина такого використання настанови cout нам стане зрозумілою після вивчення ще декількох розділів цього навчального посібника, поки що стисло зазначимо, що ім'я символьного масиву, який містить рядок, можна використовувати скрізь, де допустимо застосування рядкового літерала. При цьому майте на увазі, що ні оператор "<<", ні функція gets () не виконують граничної перевірки (на відсутність порушення меж масиву). Тому, якщо користувач введе рядок, довжина якого перевищує розмір масиву, то можливі неприємності, про які згадувалося вище. Із сказаного виходить, що обидва описаних тут варіанти зчитування рядків з клавіатури є потенційно небезпечними. Проте, після докладного розгляду С++-можливостей введення-виведення в розд. 19, ми дізнаємося про способи, що дають змогу обійти цю проблему.

5.3. Застосування бібліотечних функцій для оброблення рядків

Мова програмування C++ підтримує багато функцій для оброблення рядків. Найпо­ши­ре­ні­ши­ми з них є такі: strерy(), strcpy(), strlen(), strcmp().

Для виклику всіх цих функцій у програму необхідно включити заголовок < cstring >. Тепер познайомимося з кожною функцією окремо.

5.3.1. Використання функції strcpy()

Загальний формат виклику функції strcpy () є таким:

strcpy (to, from);

Функція strcpy () копіює вміст рядка from в рядок to. Необхідно пам'ятати, масив, який використовують для зберігання рядка to, повинен бути достатньо великим, щоб в нього можна було помістити рядок з масиву from. Інакше масив to переповниться, тобто відбудеться вихід за його межі, що може призвести до руйнування програми.

Використання функції strcpy () продемонстровано у наведеному нижче коді програми, яка копіює рядок "Привіт" в рядок strMas:

Код програми 5.6. Демонстрація механізму використання функції strcpy()

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

#include <cstring> // Для роботи з рядковими типами даних

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

 

int main ()

{

char strMas[80];

strcpy (strMas, "Привіт");

cout << strMas;

 

getch (); return 0;

}

5.3.2. Використання функції strcpy()

Звернення до функції strcpy () має такий формат:

strcpy (s1, s2);

Функція strcpy () приєднує рядок s2 до кінця рядка s1; при цьому рядок s2 не змінюється. Обидва рядки повинні завершуватися нульовим символом. Результат виклику цієї функції, тобто остаточний рядок s1 також завершуватиметься нульовим символом. Використання функції strcpy () продемонстровано у наведеному нижче коді програми, яка повинна вивести на екран рядок "Привіт усім!".

Код програми 5.7. Демонстрація механізму використання функції strcpy()

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

#include <cstring> // Для роботи з рядковими типами даних

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

 

int main ()

{

char s1[20], s2[10];

strcpy (s1, "Привіт");

strcpy (s2, " усім!");

strcpy (s1, s2);

cout << s1;

 

getch (); return 0;

}

5.3.3. Використання функції strcmp()

Звернення до функції strcmp () має такий формат:

strcmp (s1, s2);

Функція strcmp () порівнює рядок s2 з рядком s1 і повертає значення 0, якщо вони однакові. Якщо рядок s1 лексикографічно (тобто відповідно до алфавітного порядку) більший від рядка s2, то повертається позитивне число. Якщо рядок s1 лексикографічно менший від рядка s2, то повертається негативне число. Використання функції strcpy () продемонстровано у наведеному нижче коді програми, яка слугує для перевірки правильності пароля, введеного користувачем (для введення пароля з клавіатури і його верифікації слугує функція password ()).

Код програми 5.8. Демонстрація механізму використання функції strcmp()

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

#include <cstring> // Для роботи з рядковими типами даних

#include <cstdio> // Для підтримки системи введення-виведення

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

 

bool password ();

 

int main ()

{

if (password ()) cout << "Вхід дозволено.\n";

else cout << "У доступі відмовлено.\n";

 

getch (); return 0;

}

 

// Функція повертає значення true, якщо пароль прийнятий, і

// значення false інакше.

bool password ()

{

char sMas[80];

cout << "Введіть пароль: ";

gets (sMas);

if (strcmp (sMas, "пароль")) { // Рядки різні.

cout << "Пароль недійсний.\n";

return false;

}

// Порівнювані рядки збігаються

 

return true;

}

Під час застосування функції strcmp () важливо пам'ятати, що вона повертає число Про (тобто значення false), якщо порівнювані рядки однакові. Отже, якщо Вам необхідно виконати певні дії за умови збігу рядків, то програміст повинен використовувати оператор НЕ (!). Наприклад, у процесі виконання наведеної нижче програми запит вхідних даних продовжується доти, доки користувач не введе слово "Вихід".

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

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

#include <cstdio> // Для підтримки системи введення-виведення

#include <cstring> // Для роботи з рядковими типами даних

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

 

int main ()

{

char sMas[80];

for (;;) {

cout << "Введіть рядок: ";

gets (sMas);

if (! strcmp ("Вихід", sMas)) break;

}

getch (); return 0;

}

5.3.4. Використання функції strlen()

Загальний формат виклику функції strlen () є таким:

strlen (s);

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

Код програми 5.10. Демонстрація механізму використання функції strlen()

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

#include <cstdio> // Для підтримки системи введення-виведення

#include <cstring> // Для роботи з рядковими типами даних

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

 

int main ()

{

char strMas[80];

cout << "Введіть рядок: ";

gets (strMas);

cout << "Довжина рядка дорівнює: " << strlen (strMas);

 

getch (); return 0;

}

Якщо користувач введе рядок "Привіт усім!", програма виведе на екрані число 12. При підрахунку символів, з яких складається заданий рядок, ознака завершення рядка (нульовий символ) не враховується.

А у процесі виконання цієї програми рядок, введений з клавіатури, буде відображено на екрані в зворотному порядку. Наприклад, під час введення слова "привіт" програма відобразить слово тівирп. Необхідно пам'ятати, що рядки є символьні масиви, які дають змогу посилатися на кожен елемент (символ) окремо.

Код програми 5.11. Демонстрація відображення рядка в зворотному порядку|ладі|

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

#include <cstdio> // Для підтримки системи введення-виведення

#include <cstring> // Для роботи з рядковими типами даних

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

 

int main ()

{

char strMas[80];

int i;

cout << "Введіть рядок: ";

gets (strMas);

for (i= strlen (strMas)-1; i>=0; i--) cout << strMas[i];

 

getch (); return 0;

}

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

Код програми 5.12. Демонстрація механізму використання всіх чотирьох рядкових функцій

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

#include <cstdio> // Для підтримки системи введення-виведення

#include <cstring> // Для роботи з рядковими типами даних

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

 

int main ()

{

char s1[80], s2[80];

cout << "Введіть два рядки: ";

gets (s1);

gets (s2);

cout << "Їх довжини дорівнюють: " << strlen (s1);

cout << " " << strlen (s2) << "\n";

if (! strcmp (s1, s2))

cout << "Рядки однакові\n";

cout << "Рядки не однакові\n";

strcpy (s1, s2);

cout << s1 << "\n";

strcpy (s1, s2);

cout << s1 << " і " << s2 << " ";

cout << "тепер однакові\n";

 

getch (); return 0;

}

Якщо запустити цю програму на виконання і на пропозицію ввести рядки "привіт" і "усім", то вона відобразить на екрані такі результати:

Їх довжини дорівнюють: 6 4

Рядки не однакові

привіт усім

всім і всім тепер однакові

Останнє нагадування: не забувайте, що функція strcmp () повертає значення false, якщо рядки однакові. Тому, якщо Ви перевіряєте рівність рядків, необхідно використовувати оператор "!" (НЕ), щоб реверсувати умову (тобто змінити її на зворотне), як було показано в попередній програмі.

5.3.5. Використання ознаки завершення рядка

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

Код програми 5.13. Демонстрація перетворення символів рядка в їх прописні еквіваленти

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

#include <cstring> // Для роботи з рядковими типами даних

#include <cctype> // Для роботи з символьними аргументами

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

 

int main ()

{

char strMas[80];

int i;

strcpy (strMas, "test");

for (i=0; strMas[i]; i++) strMas[i] = toupper (strMas[i]);

cout << strMas;

 

getch (); return 0;

}

Ця програма у процесі виконання виведе на екран слово TEST. Тут використовується бібліотечна функція toupper (), яка повертає прописний еквівалент свого символьного аргументу. Для виклику функції toupper () необхідно приєднати до програми заголовок < cctype >.

Звернемо Вашу увагу на те, що як умову завершення циклу for використано масив strMas, індексований змінній i, що керує (strMas[i]). Такий спосіб керування циклом цілком прийнятний, оскільки за дійсне значення у мові програмування C++ приймається будь-яке ненульове значення. Згадаймо, що всі друкарські символи представляються значеннями, не дорівнюють нулю, і тільки символ, що завершує рядок, дорівнює нулю. Отже, цей цикл працює доти, доки індекс не вкаже на нульову ознаку кінця рядка, тобто поки значення strMas[i] не стане нульовим. Оскільки нульовий символ відзначає кінець рядка, цикл зупиняється точно там, де потрібно. При подальшій роботі з цим навчальним посібником Ви побачите багато прикладів, у яких нульова ознака кінця рядка використовують так само.

Варто знати! Окрім функції toupper (), стандартна бібліотека мови програмування C++ містить багато інших функцій оброблення символів. Наприклад, функцію toupper () доповнює функція tolower (), яка повертає рядковий еквівалент свого символьного аргументу. Часто використовують такі функції, як isalpha (), isdigit (), isspace () і ispunct (), які приймають символьний аргумент і визначають, чи належить він до відповідної категорії. Наприклад, функція isalpha () повертає значення ІСТИНА, якщо її аргументом є буква (елемент алфавіту).

5.4. Дво- та багатовимірні масиви

5.4.1. Двовимірні масиви

У мові програмування C++ можна використовувати двовимірні масиви. Двовимірний масив, по суті, є списком одновимірних масивів. Щоб оголосити двовимірний масив цілочисельних значень розміром 10´20 з іменем twod, достатньо записати таке:

int twod[10][20];

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

Щоб отримати доступ до елемента масиву twod з координатами 3´5, необхідно використовувати запис twod[3][5]. У наведеному нижче прикладі в двовимірний масив поміщаються послідовні числа від 1 до 12.

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

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

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

 

int main ()

{

int t, i, num[3][4];

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

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

num[t][i] = (t*4)+i+1;

cout << num[t][i] << " ";

}

cout << "\n";

}

getch (); return 0;

}

У наведеному прикладі елемент масиву num[0][0] набуде значення 1, елемент num[0][1] – значення 2, елемент num[0][2] – значення 3 і т.д. Значення елемента num[2][3] буде дорівнювати числу 12. Схематично цей масив можна представити так, як це показано на рис. 5.1.

У двовимірному масиві позиція будь-якого елемента визначається двома індексами. Якщо представити двовимірний масив у вигляді таблиці даних, то один індекс означає рядок, а другий – стовпець. З цього виходить, якщо доступ до елементів масиву надати в порядку, у якому вони реально зберігаються в пам'яті, то правий індекс змінюватиметься швидше, ніж лівий.

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

Рис. 5.1. Схематичне представлення масиву num

Для визначення кількості байтів пам'яті, займаної двовимірним масивом, використовують така формула:

кі-сть байтів = кі-сть рядків ´ кі-сть стовпців ´ розмір типу в байтах

Отже, двовимірний цілочисельний масив розмірністю 10´5 займає в пам'яті 10´5´2, тобто 100 байт (якщо цілочисельний тип має розмір 2 байт).

5.4.2. Багатовимірні|багатомірні| масиви

У мові програмування C++, окрім двовимірних, можна визначати масиви трьох і більш вимірів. Ось як оголошується багатовимірний масив:

тип ім'я [ розмір1 ][ розмір2 ]...[ розмірN ];

Наприклад, за допомогою такого оголошення створюється тривимірний цілочисельний масив розміром 4´10´3:

int multidim[4][10][ 3 ];

Як ми вже зазначали вище, пам'ять, виділена для зберігання всіх елементів масиву, використовується протягом всього часу наявності масиву. Масиви з числом вимірювань, що перевищує три, використовуються нечасто, хоча б тому, що для їх зберігання потрібен великий об'єм пам'яті. Наприклад, зберігання елементів чотиривимірного символьного масиву розміром 10´6´9´4 займе 2 160 байт. А якщо кожну розмірність збільшити в 10 разів, то займана масивом пам'ять зросте до 21 600 000 байтів. Як бачимо, великі багатовимірні масиви здатні "з'їсти" великий об'єм пам'яті, а програма, яка їх використовує, може дуже швидко наштовхнутися на проблему браку пам'яті.

5.5. Ініціалізація масивів

5.5.1. Ініціалізація "розмірних" масивів

У мові програмування C++ передбачено можливість ініціалізації масивів. Формат ініціалізації масивів подібний до формату ініціалізації інших змінних:

тип ім'я_масиву [ розмір ] = [ список_значень ];

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

Наприклад, в такому прикладі 10-елементний цілочисельний масив ініціалізувався числами від 1 до 10:

int tMas[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

Після виконання цієї настанови елемент tMas[0] набуде значення 1, а елемент tMas[9] –значення 10.

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

char ім'я_масиву [ розмір ] = " рядок ";

Наприклад, такий фрагмент коду програми ініціалізує масив strMas фразою "привіт".

char strMas[7] = "привіт";

Це рівнозначно поелементній ініціалізації:

char strMas[7] = {'п', 'p', 'и', 'в'|, 'і', 'т', '\0'};

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

Багатовимірні масиви ініціалізуються за аналогією з одновимірними. Наприклад, такий фрагмент коду програми масив sqrMas ініціалізувався числами від 1 до 10 і квадратами цих чисел.

int sqrMas[10][ 2 ] = {

1, 1,

2, 4,

3, 9,

4, 16,

5, 25,

6, 36,

7, 49,

8, 64,

9, 81,

10, 100

};

Тепер розглянемо, як елементи масиву sqrMas розташовуються в пам'яті (рис. 5.2).

Рис. 5.2. Схематичне представлення ініціалізованого масиву sqrMas

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

int sqrMas[10][ 2 ] = {

{1, 1),

{2, 4},

{3, 9},

{4, 16},

{5, 25},

{6, 36},

{7, 49},

{8, 64},

{9, 81},

{10, 100}

};

Під час використання підгруп ініціалізацій відсутні члени підгрупи ініціалізуються нульовими значеннями автоматично.

У наведеному нижче коді програми масив sqrMas використовують для пошуку квадрата числа, введеного користувачем. Програма спочатку виконує пошук заданого числа в масиві, а потім виводить відповідне йому значення квадрата.

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

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

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

 




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


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


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



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




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