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

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

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

Масиви в С++

199

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

void print(int **А, int m, int n)

{for (int i=0; i<m; i++)

{for (int j=0; j<n; j++) cout << ' ' << А[i][j]; cout << '\n';

}}

Виклик такої функції матиме вигляд:

int **х=new int*[3];

for (i=0; i<3; i++) х[i]=new int[4]; print(х,3,4);

Приклад 5.21 Розробити програму для введення матриці розмірністю 5 5 цілих чисел, обчислення суми елементів зі значенням понад 7 і замінити у вихідній матриці ці елементи на значення 10 та обчислити нову суму елементів матриці зі значенням понад 7.

Вхід до sum( )

 

s = 0

Вхід до zamina()

 

i 0,4

i 0,4

 

j

0,4

j 0,4

 

Ні

 

Ні

 

matrij >7

matrij >7

Так

 

Так

 

 

s = s + matrij

matrij = 10

 

Вихід

Вихід

 

а

 

б

Блок-схеми функцій:

а – sum( ); б – zamina( )

Початок

i 0,4

j 0,4

pij

s=sum(p,n)

s

zamіna(p,n)

i 0, n 1

j 0, n 1

pij

s=sum(p,n)

s

Кінець

Блок-схема основної програми (кнопка “Розв‟язок”)

200

Розділ 5

Тексти функцій і програми для командної кнопки “Розв‟язок”: int sum(int matr[5][5])

{int i, j, s=0;

for (i=0; i<5; i++) for (j=0; j<5; j++)

if (matr[i][j] > 7) s += matr[i][j];

return s;

}

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

void zamіna(int matr[5][5])

{for (int i=0; i<5; i++)

for (int j=0; j<5; j++) if (matr[i][j] > 7) matr[i][j] = 10;

}

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

void __fastcall TForm1::Button1Click(TObject *Sender)

{int i, j, s, p[5][5]; for (i=0; i<5; i++)

for (j=0; j<5; j++) p[i][j]=StrToInt(SG1->Cells[j][i]); s=sum(p);

Edit1->Text=IntToStr(s); zamіna(p);

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

for (j=0; j<5; j++) SG2->Cells[j][i]=IntToStr(p[i][j]); s=sum(p);

Edit2->Text=IntToStr(s);

}

Приклад 5.22 Розробити схему алгоритму та програмний проект для:

обчислення елементів матриці

розмірністю 4 4 за формулою

Аij = sin(i) + ln(j2), де i

 

 

 

 

 

0,4

, j 0,4 ;

 

обчислення елементів вектора добутків елементів головної діагоналі матриці на елементи другого рядка;

переставляння елементів неголовної діагоналі й останнього стовпчика

матриці.

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

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

 

 

 

 

 

 

Масиви в С++

201

 

 

 

 

 

 

 

 

 

 

Вхід до New_Matr()

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Вхід до Matr()

 

 

 

 

 

i 0,3

 

 

 

 

 

 

Вхід до Vector()

 

 

 

 

 

 

 

i 0,3

 

 

 

 

 

 

 

 

tmp=A[i][3-i]

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

i 0,3

 

 

 

 

 

 

 

j 0,3

 

 

 

 

 

 

 

 

A[i][3-i]=A[i][3]

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2

 

V[i]=A[i][i]*A[1][i]

 

 

 

 

 

 

 

 

Аij=sin(i+1)+ln(j+1)

 

 

 

 

 

 

A[i][3]=tmp

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Вихід

а

а –

Вихід

Вихід

б

в

Блок-схеми функцій:

 

Matr(); б – Vector(); в – New_Matr()

 

 

Початок

Початок

Виклик

 

Vector()

функції

i 0,3

 

i 0,3

i 0,3

 

Виведення

Виведення

V[i]

А[i][j]

Кінець

Кінець

 

б

а

Блок-схеми для кнопок:

а – Button1 та Button3; б – Button2

Тексти функцій і програм для усіх командних кнопок:

int i, j; float A[4][4], V[4];// Глобально оголошені змінні //-----------------------------------------------------------------

void Matr() // Функція обчислення елементів матриці

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

for (j=0; j<4; j++) A[i][j]=sin(i+1)+log((j+1)*(j+1));

}

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

void Vector() // Функція обчислення елементів вектора

{ for (i=0; i<4; i++) V[i]=A[i][i]*A[1][i];

}

202

Розділ 5

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

// Функція переставляння елементів неголовної діагоналі й останнього стовпчика матриці void New_Matr()

{float tmp;

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

{tmp = A[i][3-i]; A[i][3-i] = A[i][3];

A[i][3] = tmp;

}

}

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

void __fastcall TForm1::Button1Click(TObject *Sender)//Обчислити матрицю

{ Matr(); // Виклик функції for (i=0; i<4; i++)

for (j=0; j<4; j++) StringGrid1->Cells[j][i]=FormatFloat("0.000", A[i][j]);

}

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

void __fastcall TForm1::Button2Click(TObject *Sender)//Обчислити вектор

{ Vector(); // Виклик функції for (i=0; i<4; i++)

StringGrid2->Cells[i][0]=FormatFloat("0.000", V[i]);

}

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

// Обміняти місцями неголовну діагональ і останній стовпчик

void __fastcall TForm1::Button3Click(TObject *Sender) { New_Matr(); // Виклик функції

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

StringGrid3->Cells[j][i]=FormatFloat("0.000", A[i][j]);

}

Приклад 5.23 Розробити програму для введення матриці цілих чисел розмірністю 6 3 і обчислення елементів вектора середніх арифметичних непарних елементів парних рядків.

Розв‟язок організуємо в окремій функції Vektor(). Для обчислення елементів вектора спочатку слід організувати цикл для переміщення по парних рядках (2, 4, 6). У кожному з парних рядків, рухаючись по стовпчиках, підсумовуємо тільки парні елементи та їхню кількість. Перед обчисленням середнього арифметичного, тобто перед діленням, перевіряємо можливість відсутності в даному парному рядку непарних елементів, тобто виключаємо поділ на нуль. Змінна k є потрібна для послідовного формування індексів вектора, оскільки їхня нумерація не збігається з нумерацією рядків у матриці.

Масиви в С++

203

Текст функції та програми для командної кнопки: void Vektor(int M[6][3], float X[3])

{int i, j, kol, k = 0; for(i=1; i<6; i+=2)

{X[k] = kol = 0; for(j=0; j<3; j++)

if(M[i][j] % 2 == 1)

{X[k] += M[i][j]; kol++;

}

if(kol) X[k] /= kol ; else X[k] = 0;

k++;

}

}

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

void __fastcall TForm1::BitBtn1Click (TObject *Sender) { int i, j, A[6][3]; float V[3];

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

 

for(j=0; j<3; j++)

 

A[i][j] = StrToInt(SG1->Cells[j + 1][i + 1]);

Vektor(A, V);

// Виклик функції

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

SG2->Cells[0][i + 1] = FloatToStr(V[i]);

}

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

void __fastcall TForm1::FormCreate(TObject *Sender)

{int i, j;

for(i=1; i<=6; i++) SG1->Cells[0][i]=IntToStr(i)+"-й рядок"; for(j=1; j<=3; j++) SG1->Cells[j][0]=IntToStr(j)+"-й стовпчик"; SG2->Cells[0][0] = "Вектор";

randomize(); for(i=1; i<=6; i++)

for(j=1; j<=3; j++) SG1->Cells[j][i]=IntToStr(50-random(100));

}

204

Розділ 5

Питання та завдання для самоконтролю

1)Дайте означення масиву у програмуванні?

2)В який спосіб задають розмірність масиву?

3)Яке призначення індексів масиву? Змінні яких типів можна використовувати для індексів? В який спосіб записують індекси масиву?

4)Які з наведених оголошень одновимірного масиву з 10-ти елементів помилкові і чому?

а) int A[1..10];

в) int A[9];

б) float A[10];

г) float A[0, 9];

5)Запишіть оголошення одновимірного масиву з 25-ти дійсних чисел.

6)Наведіть оператор, який присвоює першому елементу масиву A з 20ти цілих чисел нульове значення.

7)Запишіть оголошення одновимірного констант-масиву з послідовності символів Вашого прізвища.

8)Які компоненти C++ Builder для введення елементів одновимірних масивів на форму Ви знаєте?

9)Запишіть оператор оголошення символьного масиву S з 10-ти елеме-

нтів.

10) Запишіть оператори виведення масиву W з 17-ти дійсних чисел до трьох різних компонентів.

11) Оберіть правильні твердження:

а) якщо список ініціалізації містить початкових значень менше за розмірність масиву, це є помилка;

б) оголошення int A[23]; резервує пам‟ять під масив А з 23 елементів цілого типу;

в) оголошення float A = {-1, 2.2, 5}; резервує пам‟ять для трьох елементів масиву A типу float;

г) масив може зберігати дані різних типів.

12) В яких випадках при оголошенні масиву можна не задавати його розмірність?

13)Віднайдіть і розтлумачте помилки у твердженнях: а) індекси масиву можуть бути якого завгодно типу;

б) при оголошенні масиву програма автоматично ініціалізує його нульовими значеннями;

в) щоб звернутися до конкретного елемента масиву, слід записати ім‟я масиву і значення цього елемента;

г) кількість елементів масиву завжди збігається з кількістю займаних ним байтів оперативної пам‟яті.

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

а) s1=0;

б) s2=1;

в) s3=0;

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

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

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

s1 += a[i];

s2 *= a[i];

if(a[i]>0) s3++;

 

Масиви в С++

 

205

15) Запишіть ім‟я змінної, значенням якої є кількість додатних елементів

масиву в наведених трьох фрагментах програм:

 

 

а) S1=0;

б) S2=1;

в) S3=0;

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

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

 

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

S1 += a[i];

S2 *= a[i];

 

if(a[i]>0) S3++;

16) Запишіть ім‟я змінної, значенням якої є максимальний з елементів ма-

сиву в наведених трьох фрагментах програм:

 

 

а) S1=0;

б) S2=a[0];

 

в) S3=0;

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

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

 

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

S1 += a[i];

if(a[i]>S2)S2=a[i];

if(a[i]>0)S3=S3+1;

17) Які з наведених оголошень двовимірних масивів неправильні й чому?

а) int С[1..5, 1..5];

в) float С[1..5][1..5];

б) float C[5][5];

г) int C: [5][5];

18)В який спосіб розміщуються елементи двовимірних масивів в оперативній пам‟яті?

19)Запишіть фрагмент програми для введення з компонента StringGrid1 елементів матриці W з 3-х рядків і 5-ти стовпчиків цілих чисел.

20)Задайте при оголошенні матриці цілих чисел z з 3-х рядків і 2-х стовпчиків початкові значення її елементам.

21)Запишіть оператор оголошення символьної матриці S розміром 7 3.

22)Під яким номером записано оператор, що обчислює суму елементів

головної діагоналі матриці A цілих чисел розміром 5 5?

а) for(i=0, s=0; i<5; i++) s++;

б) for(i=0, s=0; i<5; i++) s+=A[i][i];

в) for(i=0, s=0; i<5; i++) for(j=0; j<5; j++) s+=A[i][j]; г) for(i=0, s=0; i<5; i++) A[i][i]=0;

23)Запишіть фрагмент програми обчислення кількості елементів масиву A

з10-ти цілих чисел, значеннями яких є двоцифрові числа.

24)Запишіть фрагмент програми для обчислення середнього арифметич-

ного, максимального і мінімального елементів масиву Z з 15-ти цілих чисел.

25)Оберіть правильні оголошення масивів:

а) mas[7]={1,3,0,-2,0,1,9}; б) char s[10];

в) const int m=9; int A[m]; г) float C[5]={12,4,82};

д) int B[]={1,20,3,0,-1};

е) int W[5]={-1,2,40,8,20,9};

26) Оберіть номер правильного оператора виведення на екран у консольному режимі масиву mas з 7-ми цілих чисел:

а) cout << mas;

б) for(int i=0; i<7; i++) cout << mas[i]; в) for(int i=0; i<=7; i++) cout << mas[i]; г) for(int i=1; i<7; i++) cout << mas[i]; д) for(int i=1; i<=7; i++) cout << mas[i];

206

Розділ 5

27) Віднайдіть і розтлумачте помилки у фрагментах програм для int s, i, a[10];:

а) for(s=0, i=0; i<10; i++) { cin >> a[i]; s += a[i];} cout << "Середнє арифметичне введених чисел =" << s/10;

б) for(i=0; i<10; i++) { cin >> a[i]; s += a[i];} cout << "Сума елементів масиву = " << s;

в) for(s=0, i=0; i<5; i+=2) { cin >> a[i]; s += a[i];} cout << "Сума непарних елементів масиву =" << s/5.;

г) for(s=0, i=0; i<5; i++) { cin >> a[i]; s *= a[i];} cout << "Добуток елементів масиву = " << s;

27)Запишіть фрагмент програми обчислення остачі від ділення максимального на мінімальний елемент масиву з 10-ти цілих чисел.

28)Запишіть фрагмент програми упорядкування за спаданням масиву з 20-ти цілих чисел.

29)Чи можна виконувати опрацювання двовимірного масиву, організувавши зовнішній цикл по стовпчиках, а внутрішній – по рядкам?

30)Чи варто організовувати вкладені цикли для опрацювання лише головної діагоналі квадратної матриці?

Розділ 6

Вказівники. Динамічна пам'ять

6.1 Вказівники

Пам‟ять комп‟ютера являє собою сукупність комірок для зберігання інформації, кожна з яких має власний номер. Ці номери називаються адресами. Розмір однієї комірки пам‟яті становить 1 байт. При оголошенні змінної в пам‟яті виділяється ділянка обсягом, відповідним до типу змінної, наприклад 4 байти для типу int. Ця ділянка пам‟яті пов‟язується з іменем змінної. Можна сказати, що адреса змінної – це адреса першої комірки цієї ділянки. Існують спеціальні змінні – вказівники, в яких можна зберігати адреси комірок пам‟яті, тобто адреси змінних.

Слід звернути увагу на те, що адреса і значення змінної – це зовсім різні поняття. Зазвичай адреси змінних не є важливими, найголовніше – значення цих змінних. Вказівники використовуються для прямого доступу до даних у пам‟яті.

Адреса

Значення

 

комірки

змінної

 

пам‟яті

в пам‟яті

 

1000

 

Комірки з адресами 1000-1003

 

зберігають значення 45016,

 

 

1001

 

яке є адресою іншої комірки

 

 

 

45016

 

1002

 

 

1003

 

 

1004

 

 

 

 

1005

 

 

 

 

1006

 

 

 

 

 

 

 

 

.

 

 

.

 

 

.

 

 

Пам‟ять

Вказівник оголошується за допомогою *:

<тип> *<ім‟я>;

Тут тип – це базовий тип вказівника, котрим може бути який завгодно тип. Ім‟я є ідентифікатором змінної-вказівника. Слід звернути увагу на те, що тип – це не тип вказівника, а тип даних, адресу яких буде записано у вказівнику.

Наприклад, вказівник на пам‟ять, в якій зберігатиметься ціле число: int *А;

Вказівник на дійсне число:

208

Розділ 6

float *В;

При цьому змінна А – це адреса ділянки пам‟яті, в якій розташоване ціле число, B – адреса ділянки пам‟яті, в якій розташоване дійсне число. Обидві змінні – А та B – є вказівниками, тобто їхніми значеннями є адреси. Окрім того, адреси змінних типу int та float займають у пам‟яті однакову кількість байтів. Але насправді змінні А та В мають різний тип: А – вказівник на ціле, B – вказівник на дійсне.

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

Вказівникові можна присвоїти лише адресу змінної відповідного типу, оскільки С++ не виконує автоматичного перетворення типів вказівників. Тому такі команди є помилковими:

A = B; // Не можна переприсвоювати один одному вказівники на різні типи;

А= 10; // не можна присвоювати числа вказівникам.

Умові С++ визначено дві операції для роботи з вказівниками: 1) * розадресація, чи розіменування вказівника;

2) & адресація, тобто отримання адреси змінної.

Для прикладу у програмі оголосимо цілу змінну Х зі значенням 7: int Х = 7;

тоді, щоб її адресу записати до вказівника А, слід записати команду:

А = &Х; // Значенням змінної А є адреса змінної Х.

Якщо пам‟ять, у якій зберігається змінна Х, починається з комірки під номером 2000, тоді змінній А після цієї команди буде присвоєно значення 2000.

Тепер до значення 7, яке зберігається у змінній X, можна звернутися не лише за ім‟ям X, але й через вказівник. При цьому слід застосувати операцію розадресації вказівника (вона позначається символом “*”), наприклад: . Цей запис означає: “значення, яке зберігається за адресою, записаною у змінній A”. Щоб збільшити на 2 оголошену раніше змінну X, можна записати так:

X = X + 2; /*За ім‟ям X комп‟ютер визначить адресу ділянки пам‟яті, в якій вона розташована, візьме значення, що зберігається у пам‟яті за цією адресою, збільшить його на 2 і запише назад у ту ж саму ділянку пам‟яті */

чи так:

*A = (*A) + 2;/* Комп‟ютер з ділянки пам‟яті за адресою, записаною у змінній A, візьме значення, яке зберігається в ній, збільшить це значення на 2 і запише в ту ж саму ділянку */

У першому разі відбувається звертання до змінної з ім‟ям X, у другому – до змінної через її адресу, яку записано у змінній-вказівнику A.

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