ВКАЗІВНИКИ І МАСИВИ В МОВІ С++
План.
Загальні відомості про вказівники.
Операції над вказівниками.
Вказівники і масиви.
Масив як параметр функції.
ЗАГАЛЬНІ ВІДОМОСТІ ПРО ВКАЗІВНИКИ.
Вказівник — це адреса поля пам’яті, займаного програмним
об'єктом.
Наприклад:
int a=5;
char с='G';
float r=1.2E8;
Ці величини розмістилися в пам'яті комп'ютера таким чином:
Операція & — адреса.
Застосування цієї операції до імені змінної дає в результаті її
адресу в пам'яті. Для змінних з даного вище прикладу:
&а рівне FFC0
&с - FFC2
&r - FFC3.
Опис вказівників. Для зберігання адрес використовуються
змінні типу «вказівник».
Формат опису таких змінних наступний:
тип *ім’я_змінної
Приклади опису вказівників:
int *pti;//змінна pti може приймати значення вказівника на
//величину цілого типу
char *ptc; // змінна ptc призначена для зберігання вказівника
//на величину типу char
float *ptf; //змінна ptf — на величину типу float.
Вказівникам можуть привласнюватися значення адрес об'єктів тільки того
типу, з яким вони описані. У нашому прикладі допустимі оператори
pti=&a; ptc=&c; ptf=&r;
В результаті вказівники приймуть наступні значення:
pti - FFC0, ptc - FFC2, ptf - FFC3
Значення вказівників можуть ініціалізуватися при описі.
Наприклад:
int a=5; int *pti=&a;
char c='G'; char *ptc=&c;
float r=1.2E8; float *ptf=&r;
У заголовному файлі stdio.h визначена константа — нульовий вказівник з
ім'ям NULL. Її значення можна привласнювати вказівнику. Наприклад:
ptf=NULL;
Не треба думати, що після цього покажчик ptf буде зсилатися на нульовий
байт пам'яті. Нульовий вказівник означає відсутність конкретної адреси
зсилки.
Використаний в описах вказівників символ * (зірочка) у даному
контексті є знаком операції розадресації. З її допомогою можна
зіслатися через вказівник на відповідну змінну.
Після приведених вище описів в записі виразів цієї програми
взаємозамінними стають
a і *pti, c і *ptc, r і *ptf.
Наприклад, два оператори
x=a+2; і x=*pti+2;
тотожні один одному.
В результаті виконання оператора
cout<<*pti<<a;
на екран виведеться 55.
ОПЕРАЦІЇ НАД ВКАЗІВНИКАМИ.
Записуючи вирази і оператори, що змінюють значення
вказівників, необхідно пам'ятати головне правило:
одиницею зміни значення вказівника є розмір відповідного
йому типу.
Наприклад:
pti=pti+1; або
pti++;//змінить значення вказівника pti на 2,
//прийме
значення FFC2.
pti--; //значення вказівника зменшиться на 2 і стане
//рівним FFBE.
ptc++; // збільшить значення вказівника на 1;
ptf++; // збільшить значення вказівника на 4.
ВКАЗІВНИКИ І МАСИВИ.
Ім'я масиву трактується як вказівник-константа на масив.
Наприклад:
int x[10];
х є покажчиком на нульовий елемент масиву в пам'яті комп'ютера. У зв'язку з
цим істинним є відношення
x==&x[0]
Звідси витікає, що для доступу до елементів масиву окрім індексованих імен
можна використовувати розадресовані вказівники за принципом:
ім'я[індекс] тотожне *(ім'я+індекс)
Наприклад, для описаного вище масиву х взаємозамінні наступні позначення
елементів:
x[5], або *(x+5), або *(5+x)
Тепер розглянемо двовимірні масиви.
Наприклад:
int p[5][10]; // матриця з п'яти рядків і десяти чисел
в
//кожному рядку
р є покажчиком-константою на масив, тобто на елемент p[0][0].
Індексоване ім'я p[і] позначає i-й рядок. Йому тотожньо наступне позначення
у формі розадресованного вказівника:
*(p+і*10)
Звернення до елементу масиву р[2][4] можна замінити на *(p+2*10+4) . У
загальному випадку еквівалентні позначення:
p[i][j] і *(p+i*10+j)
Тут двічі працює операція «квадратна дужка». Останній вираз можна записати
інакше, без явної вказівки на довжину рядка матриці р:
*(*(p+i)+j)
МАСИВ ЯК ПАРАМЕТР ФУНКЦІЇ.
Приклад 11.1. Дана дійсна матриця А[М][N]. Потрібно обчислити і вивести
евклідові норми рядків цієї матриці. Нормою Евкліда вектора називають
корінь квадратний з суми квадратів його елементів. Якщо рядок матриці
розглядати як вектор, то дану формулу треба застосувати до кожного рядка.
В результаті отримаємо M чисел.
Визначення функції обчислення норми довільного вектора:
double Norma(int n, double x[]) {
int i;
double s=0;
for(i=0;i<n;i++) s+=x[і]*x[і];
return sqrt(s); }
Заголовок цієї функції можна було записати і в такій формі:
double Norma(int n, double *x)
Розглянемо фрагмент основної програми, що використовує
дану функцію для обробки матриці розміром 5x10.
void main()
{ double A[5][10]; int і;
//Введення матриці
//обчислення і виведення норми рядків
for(i=0; i<5; i++)
cout<<"Hopмa"<<i<<"-го рядка=" <<Norma (10,
A[i]) ;
}
ПРИКЛАД 11.2. ЗАПОВНИТИ ДВОВИМІРНУ МАТРИЦЮ
ВИПАДКОВИМИ ЦІЛИМИ ЧИСЛАМИ В ДІАПАЗОНІ ВІД 0
ДО 99. ВІДСОРТУВАТИ РЯДКИ ОТРИМАНОЇ МАТРИЦІ ПО
ЗРОСТАННЮ ЗНАЧЕНЬ. ВІДСОРТОВАНУ МАТРИЦЮ
ВИВЕСТИ НА ЕКРАН.
#include <iostream.h>
#include <iomanip.h>
#include <conio.h>
#include <stdlib.h>
const n=5;//Глобальное объявление константы
//Прототипы функций
void Matr(int M[] [n]) ;
void Sort(int, int X[]);
//Основная программа
void main(){
int i,j, A[n][n] ;
clrscr();
cout<<"\n"<<"Maтрица до сортировки: "<<"\n";
Matr(A);
for(i=0;i<n;i++) Sort(n,A[i]);
cout<<"\n"<<"Матрица после сортировки:"<<"\n";
for(i=0; i<n; i++) {
for(j=0; j<n; j++)
cout<<setw(6)<<A[i] [j] ;
cout<<endl;}
getch();
}
// Функция сортировки вектора
void Sort(int k, int X[]) {
int i,j, Y;
for(i=0; i<k-1; i++)
for(j=0; j<k-i-1; j++)
if(X[j]>X[j+1]) {
Y=X[j];
X[j]=X[j+1];
X[j+1]=Y;} }
//Функция заповнення матриці і виведення на екран
void Matr(int M[][n]) {
int i,j;
randomize();
//Встановлення датчика випадкових чисел
for(i=0; i<n; i++) {
for(j=0; j<n; j++)
{ M[i] [j]=rand() %100;
cout<<setw (6)<<M [i][ j ]; }
cout<<endl; } }
|