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

Информатика.ЛБ

.pdf
Скачиваний:
15
Добавлен:
14.04.2015
Размер:
950.97 Кб
Скачать

17.Задано два масиви X(10) і Y(10), обчислити Z( i,j) = Xi+Yj, де j,j=10..1.

18.Знайти максимальний елемент головної діагоналі матриці Х (5,5).

19.Обчислити кількість від‘ємних елементів, що знаходяться вище головної діагоналі матриці М (5,5).

20.Знайти максимальний елемент у третьому рядку матриці Р(5,5) і його

індекс.

21.Поміняти місцями елементи першого і третього рядка матриці Q(3,5).

22.Знайти мінімальний елемент і його індекс серед елементів, що знаходиться вище головної діагоналі матриці К (5,5).

23.Поміняти місцями елементи першого і другого стовпців матриці С(5,4).

24.Розділити всі елементи матриці Р(4,4) на суму додатних елементів її головної діагоналі.

25.Помножити всі елементи матриці М(5,5) на суму додатних елементів, що знаходяться на її головній діагоналі.

41

3 ВИРІШУВАННЯ ЗАДАЧ З ВИКОРИСТАННЯМ ДАНИХ СИМВОЛЬНОГО ТИПУ

3.1 Ціль роботи

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

3.2 Методичні рекомендації з організації самостійної роботи студентів

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

В усіх попередніх роботах використовувалися числові типи даних. Однак ефективність мови С++ багато в чому визначається наявністю в ньому розвитих засобів для обробки символьної інформації. У стандартній бібліотеці С++ передбачено багато функцій , що виконують прості дії із символьними даними. Тому ця мова найкраще підходить для системної роботи: написання компіляторів, інтерпретаторів, операційних систем, редакторів тексту і т.п.

У мові С++ розрізняють символьні константи і рядки.

Символьна константа — це одиночний символ, укладений в апострофи. Керуючі послідовності розглядаються як одиночний символ, наприклад: ‗ ‗ — проміжок, ‗а‘— літера а, ‗\‘ — зворотна коса риса.

Тип char використовується для зображення символу. Значенням об'єкта типу char є код у наборі символів персонального комп'ютера, що відповідає даному символу. Тип char за замовчуванням інтерпретується як однобайтова ціла величина зі знаком (діапазон значень перемінної від -128 до 127). Змінна типу unsigned char може запам'ятовувати значення в діапазоні від 0 до 255.

Рядок — це послідовність символів, укладена в лапки ("), наприклад: "Це рядок". Він зберігається в послідовній області пам'яті, у кінець якої компілятором додається нульовий символ (‗\0‘), що подається керуючою послідовністю ‗\0‘ і є символьним масивом. Рядки мають тип char [ ]. Число елементів масиву дорівнює числу символів у рядку плюс 1, тому що нульовий символ також є елементом масиву. Рядки можуть розташовуватися на декількох рядках. У цьому випадку ставиться зворотна дробова риса і натискається клавіша ENTER. Зворотна риса із символом нового рядка ігнорується компілятором, і наступний рядок вважається продовженням поточного.

3.2.1 Організація символьного введення - виведення

42

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

Мова С++ сприймає все введення-виведення як потоки символів. Потік символів може бути організований: із клавіатури, файлу, модему і т.д. Операційна система забезпечує стикування пристроїв, а С++ може використовувати ті самі функції для введення - виведення, наприклад, як із клавіатури, так і з модему. От чому таке велике значення приділяється обробці символьних типів даних. Для обслуговування операцій над рядками використовується файл <string.h> . При організації введення-виведення в мові С++ завжди передбачається, що введення буде здійснюватися з stdin, що означає стандартний пристрій введення (звичайно клавіатура), а виведення здійснюється на стандартний пристрій виведення (звичайно дисплей) з ім'ям stdout. Ці потоки можна перепризначити на роздрук — ім'я stdprn, послідовний порт — ім'я stdaux, повідомлення про помилки – ім'я stderr. Оператор cout здійснює виведення на екран тільки тому, що більшість комп'ютерів за замовчуванням stdout направляє виведення на екран, а оператор cin здійснює введення з клавіатури за тою же причиною, тому що клавіатура є стандартним пристроєм введення (stdin).

Розглянемо порядок дій при перепризначенні потоку виведення даних на принтер :

підключення файлу заголовка ofstream ;

виконання перепризначення виведення на принтер за допомогою операторів

ofstream prn ("PRN");

prn << " Виведення до роздруку повідомлення "<< endl; prn << name1 << name2 ... <<endl;

Такий порядок дій застосовується при компіляції як задача DOS і нижче приведена його програмна реалізація .

Приклад 3.1 Вивести дані (прізвище й ім'я) на принтер.

// P3_1.СPP виведення прізвища й імені на принтер

#include < fstream> #include < iostream> using namespace std;

main ( )

{

char fio [15]; char name [10];

cout << "Введіть прізвище "; cin >> fio;

cout << "Введіть ім'я ";

43

cin >> name;

// Посилка імен fio і name на принтер ofstream prn ("PRN");

prn << " Виведення імені і прізвища " << endl; prn << name << fio << endl;

return 0;

}

Для організації символьного введення - виведення використовуються функції буферизированого (get ( ) і put ( )) і небуферизированого (getch ( ) і (putch ( )) введення – виведення, формати цих функцій наступні:

device . get (char_var);

 

device . put (char_var);

,

де device може бути будь-яким стандартним пристроєм введення– виведення.

Як видно з форматів функцій вони вводять або виводять по одному символу зі стандартних пристроїв. Функція get( ) припиняє виконання програми, сприймає один символ, що попадає спочатку в буфер і після натискання ENTER передає вміст буфера в програму. Функція getch( ) при одержанні символу, що вводиться, не виводить його на екран. Для відображення їх на екрані використовують функцію getche ( ). У функціях get( ) і put ( ) може бути перепризначений пристрій введення - виведення. Так для відкриття модему як пристрою введення - виведення і читання з нього треба використовувати заголовний файл ifstream.

Приклад 3.2 Скласти програму, що реалізує введення п'яти символів і збереження їх у вигляді масиву .

//P3_2.CPP робота з масивами символів

//Використання функції getch( ) і put ( )

#include < fstream>

#include < iostream> using namespace std;

#include < conio.h >

main ( )

{

int str;

char slovo [5];

cout << "Введіть 5 символів " << endl;

44

for ( str = 0; str < 5; str++)

{

slovo [str] = getch ( )

}

// Посилка масиву символів на принтер ofstream prn ("PRN");

prn << " Виведення масиву символів‖ << endl; for( str = 0; str < 5 ; str++)

{

prn.put ( slovo [str] );

}

return 0;

}

У цій програмі використовується файл заголовка <conio.h>, у якому описані getch ( ) і put( ) і програма буде працювати після компіляції її в DOS.

3.2.2 Рядки як символьні масиви

У мові Сі і ранніх версіях мови С++ рядки розглядалися як символьні масиви і вся робота з ними ґрунтувалася на використанні цих масивів. Розроблена бібліотека функцій <string.h> містить могутні засоби для роботи зі строковими масивами .

Для опису рядка використовуються звичайні засоби опису масивів, наприклад: char str [25];. Індексування такого масиву, як і будь-якого іншого, починається з нуля. Символьні послідовності, розділені тільки проміжками, розглядаються як один рядок, тобто запис:

 

" У той рік осіння

 

погода"

ідентична рядку

" У той рік осіння погода".

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

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

char st [] = "Слово"; char st [6] = "Слово";

char st [6] = {'С' 'л' 'о' 'в' 'о' '\0'};

якщо рядок використовується для ініціалізації покажчика типу char*, адреса першого символу рядка буде початковим значенням покажчика, наприклад:

45

char *pst = "Слово";

,

тут описується змінна - покажчик pst , що одержує початкове значення,

рівне адресі першого елемента (символ С);

 

якщо рядок використовується у виразі

(там, де дозволяється

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

char *pst;

 

pst = " Перший символ";

,

тут pst одержує адресу букви "П", тобто при виконанні операції

присвоювання в комірку пам'яті,

відведену для покажчика pst, записується не

масив символів, а тільки покажчик на його початок, тобто адреса першого символу рядка.

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

char st [20];

st = " Петров"; // запис невірний, тому що не можна змінити значення st

Використання елементів масиву здійснюється через індекси або через покажчики. Для доступу до будь-якого символу рядка використовується індекс масиву char, наприклад, якщо описана змінна char str[3], то третім елементом масиву можна скористатися, записавши: str[3] або *(str+3).

При роботі з елементами масивів рядків, тобто двовимірним масивом, варто використовувати або індекси масиву, або індекси покажчиків, наприклад, якщо описаний список прізвищ

char spis [5] [15]; ,

то для використання символу масиву варто записати: spis [i] [j] або *(spis [i] + j).

Аналогічно при оголошенні масивів покажчиків char *str [5] (указує на 5 елементів, кожний з який указує на рядок), а доступ до символу рядка можна здійснити, записавши *(str [i]+j).

3.2.3 Введення-виведення символьних масивів

46

Рядки можна вводити різними способами, найбільш розповсюдженими з яких є:

введення шляхом ініціалізації при оголошенні строкових масивів:

char st [5] = " Стіл"; char st [] = " Стіл"; char *pst = " Стіл";

у цьому випадку двовимірні масиви можна ініціалізувати одним з наступних засобів:

char str [5] [20] = {"Іванов И.И. ", "Сидоров С.С. ", . . . ,}; char str [ ] [20] = {"Іванов И.И. ", "Сидоров С.С. ", . . . ,}; char *pst [5] = {"Іванов И.И. ", "Сидоров С.С. ", . . . ,}; char *pst [ ] = {"Іванов И.И. ", "Сидоров С.С. ", . . . ,};

введення за допомогою оператора cin >> , якщо в рядку немає проміжків, тому що символ проміжок є роздільником вводу даних, наприклад:

char

st [5];

cin

>> st;

char *pst;

cin >> *pst

char

str [5] [20];

cin

>> str [i];

char *pst [5];

cin

>> ( pst [i] );

посимвольне уведення за допомогою функції get( ), наприклад

get(st[i]);

 

за допомогою функції cin.get (str [i], size, endl) ;

,

де size - кількість символів, що читаються;

 

уведення за допомогою функції cin.getline ( str [i], sizeof ( str [i] ) ); ,

де sizeof( ) - функція визначення розміру рядка.

Виводити строкові дані можна використовуючи наступні записи:

cout << st;

printf ( ―% s‖,st ); // або ( sprintf ) puts ( st ); cout . write ( st , size ); і ін.

Приклад 3.3

Список

рядків

( прізвища

і ініціали Ф.И.О.)

оголошений як масив покажчиків.

Скласти

програму

, що реалізує введення

масиву по рядках і посимвольне виведення цього масиву.

47

// P3_3.СРР список рядків оголошений як масив покажчиків

#include <stdio.h> void main (void)

{

char *psp[ ] = { "Авдєєв А.А.'',

"Петров П.П.", "Лисиця Л.Л. ", NULL };

char **ptr =psp;

// Виведення масиву по рядках while (*ptr)

puts (*ptr++); ptr=psp;

// Виведення цього масиву посимвольне while (*ptr)

{

while (**ptr)

{ putchar(**ptr); (*ptr)++; } ptr++

}

}

Під час використання заголовного файлу stdio.h можна також

застосувати, наприклад, такі функції:

 

для введення рядків

для виведення рядків

 

puts(st) ; і printf(%s, st);

gets( st);

cout.width(w);

scanf (―% s‖,st) ;

cout.precision (d);

 

setw(w);

 

setprecision(d);

3.2.4 Основні функції обробки символьних типів

У ранніх версіях С++ рядки розглядалися як символьні масиви і робота з ними ґрунтувалася на використанні цих масивів. Розроблена бібліотека функцій

48

<string.h> містить могутні засоби для роботи зі строковими масивами. Згодом була розроблена стандартна бібліотека шаблонів Standard Template Library (STL) , що надає ще більш могутні засоби роботи з рядками, об'єднані в клас string. Цей клас включається як заголовний файл , тобто:

#include <string> // без літери h

Для обробки символьних типів даних бібліотека функцій <string.h> має велику кількість вбудованих функцій, що збільшують продуктивність праці програмістів і скорочують час на розробку програм. Ця бібліотека містить такі функції, як наприклад:

функції перевірки символів; функції перетворення символів; функції перевірки рядків; функції маніпулювання рядками.

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

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

Копіювання рядків

char strcpy (s, *st); копіює байти рядка st у рядок s, (включаючи "\0"; повертає s), наприклад:

char str [50];

strcpy (str, "Сьогодні гарна погода ");

char *strdup (const char *str); копіює рядок str і повертає покажчик на рядок – копію, наприклад:

char *st1 = " Прийшла весна"; char *st2;

st2= strdup (st1); // Копіюється st1 у st2

char * strnсpy (char *st1,const char *st2, int n); копіює n символів з рядка st2 у st1, рядок st1 повинний бути більше чи дорівнювати st2, інакше виникне помилка, наприклад:

char st1[]= "Паскаль ";

char st2[] = "Привіт з далека ";

strnсpy (st1,st2,3); // Тепер у st1 "Прикаль"

49

Конкатенація слів

 

 

 

 

 

 

char *strcat (char *st1, const char *st2); поєднує st1 і

st2

і

повертає st1, наприклад:

 

 

 

 

 

 

char string [100];

 

 

 

 

 

strcpy (string, "Borland

");

 

 

 

strcat (string, " C++5");

,

 

 

 

получаємо рядок string = "Borland C++ 5"

;

 

 

char *strncat (char *st1, const char * st2, int n); додає

до рядка st1 n

символів рядка st2 і повертає в st1,

наприклад :

 

 

 

сhаr st1 [90] = "Привіт " ;

 

 

 

char st2 [50] = " Сашко і Маша";

 

 

 

strncat (st1, st2, 5);

 

 

 

 

 

st1 ="Привіт Сашко ".

 

 

 

 

Порівняння рядків

 

 

 

 

 

 

int strcmp ( char *st1, char *st2); - порівнює рядки st1 і st2

і

повертає цілу величину, рівну:

 

 

 

 

 

 

< 0

якщо

st1 <

st2;

 

 

 

= 0

якщо

st1 =

st2;

 

 

 

> 0

якщо

st1 >

st2;

,

 

 

наприклад:

 

 

 

 

 

 

 

char st1[] = "Слово " ;

 

 

 

 

char st2 [] = "слово";

 

 

 

 

int k;

 

 

 

 

 

 

k = strcmp (st1, st2);

//

k < 0;

 

 

 

int stricmp (const char *st1, const char *st2); виконує порівняння рядків не зважаючи на регістр символів; повертає цілу величину як і в попередньому випадку (див. функцію strcmp() ), наприклад:

char st1[] = "Слово " ;

 

char st2 [] = "слово";

 

 

int k;

 

 

 

 

k = stricmp (st1, st2);

k=0;

int strncmp (char *st1, char

*st2, int n); виконує порівняння рядків c

заданою кількістю символів n у st1 і st2 і повертає цілу величину:

< 0

якщо

st1

<

st2;

= 0

якщо

st1

=

st2;

> 0

якщо

st1

>

st2;

50