asyan.org | 1 Тема: Вкладені цикли. Багатомірні масиви. Масиви покажчиків Ціль роботи: вивчити конструкції мови С и оператори для обробки багатомірних масивів із застосуванням оператора циклу for. Обладнання: ПК,ПО Borland C++ Теоретичні відомості Масиви і покажчики, індексні вираження Ідентифікатор масиву є покажчиком на перший елемент цього масиву. По визначенню, оператор індексування [ ] інтерпретується таким чином, що А[У] еквівалентно *(А+У). Відповідно до правил перетворення, що виконуються при операції "+", якщо А є ім'ям масиву (ім'я масиву є покажчиком на тип елементів масиву), те індексне вираження А[У] указує на В-ий елемент масиву А. У є індексом масиву і має цілий тип (int). Індексування є комутативною операцією, тому припустимі записи В[А], *(У+А). А[ ][ ][ ][ k] У випадку використання багатомірних масивів інтерпретація індексного вираження наступна. Якщо А[i][j][кi][k] являє собою n-мірним масив з рангом i*j *...*k, те, якщо A зустрічається у вираженні, він розглядається як вектор, що містить i (n -1)-мірних масивів з рангом j*...*k. Ім'я масиву A є покажчиком на цей вектор. Якщо до покажчика застосовується оператор (*) у явному чи в неявному виді (як результат індексування), то результат буде вказувати на елемент (n-1)-мірного масиву. Розглянемо, наприклад масив int x[N][M] - масив цілих чисел розмірності N* M. Масиви в мові Зі зберігаються построчно (останній індекс змінюється швидше), а перший індекс (N) в оголошенні масиву дозволяє визначити обсяг необхідної для масиву пам'яті, але не грає ніякої ролі в обчисленні зсуву покажчика при доступі до елемента масиву – х[i][j]. Даний елемент розташований фактично в i+1 рядку, j+1 стовпці, тому що індекси в масиві починаються з нульового. Масив розглядається як одномірний (вектор), що містить N елементів, кожний з який є масивом (у даному випадку) з М елементів типу int. Ім'я масиву x є покажчиком на нульовий елемент масиву . Розглянемо елемент даного масиву x[i][j]. У вираженні *x[i], що еквівалентно * (x+i), x – покажчик на нульовий елемент масиву. Для доступу до i-того елемента i збільшується на довжину об'єкта, на який указує покажчик, а саме на довжину масиву (рядка) з М елементів типу int, тобто (i*М*sizеof(int)). У результаті індексної операції виходить покажчик, що адресує нульовий елемент i-го одномірного масиву (рядка) х[i][o]. Для другого індексу знову застосовується той же алгоритм.. Покажчик зміщається на величину (j* sizеof(int)), після чого відбувається разіменування. Цього разу результат буде мати тип int. Елемент масиву можна представити також у виді *(*(х+i)+j). Таким чином, загальний зсув у байтах покажчика на нульовий елемент масиву X[N][M] при доступі x[i][j] обчислюється по формулі((i*M+j)* sizеof(int)). Для тривимірного масиву float х3D[N][M][K] величина зсуву в байтах для доступу до елемента х3D[i][j][k] обчислюється по формулі i*(M+K)+j*R+k)* sizеof (float). Для доступу до елемента масиву 4х3D[i][j][k] можна також використовувати вираження *(*(*(х3D+i)+j)+k). Приклад /* ЗАНЯТТЯ N 13 Розробив Петров Ю.В. Оголосити масиви різної розмірності, виконати їхню ініціалізацію с застосуванням покажчиків і масиву покажчиків. Одержати доступ до елементам масивів з використанням різних синтаксичних конструкцій */ #include #include #include #include enum en{K=2,N=3,M=4};//Аналогічно #define K 5 #define N 5 #define M 4 typedef int mas1_int[N*M];//Оголошення типу 1-мірний масив (вектор) typedef int mas2_int[N][M];//Оголошення типу 2-мірний масив //(масив 1-мірних масивів) елементів типу int typedef int mas3_int[K][N][M]; //Оголошення типу 3-мірний масив //(вектор 2-мірних масивів) елементів типу int int * matrix(int n_str, int m_stolb);//Функція ініціалізації масиву //с застосуванням покажчиків і виділенням пам'яті для масиву в "купі" void main() { int d,a,b,i,j,k; int *pi, *para, *c[N]; mas1_int mas1; mas2_int mas2; mas3_int mas3; clrscr(); randomize(); for(i=0;i printf("\nинициализация одномірного масиву:\n"); for(i=0;i { mas1[i]=random(10); printf("mas1[%d]=%2d ",i,mas1[i]); if ((i+1)%5==0) printf("\n"); } printf("\nвведите індекс елемента одномірного масиву і scanf("%d",&і); pi=mas1; printf("mas1[%d]=%2d зсув: %2d байт\n",і,*(pi+і),і*sizeof(int)); getch(); randomize(); printf("Ініціалізація двовимірного масиву\n"); printf("c використанням масиву покажчиків:\n"); for(i=0;i for(j=0;j { *(c[i]+j)=random(10); printf("c[%d][%d]=%2d ",i,j,*(c[i]+j)); if ((j+1)%M==0) printf("\n"); } printf("\nвведите індекси елемента двовимірного масиву і scanf("%d %d",&і,&j); printf("mas2[%d][%d]=%2d зсув: %2d байт \n",і,j,mas2[і][j],\ (і*M+j)*sizeof(int)); printf("Інші форми запису доступу до елементів двовимірного масиву:\n"); printf("*(*mas2+i*M+j)= %2d\n", *(*mas2+i*M+j)); printf("(*mas2)[i*M+j] = %2d\n", (*mas2)[i*M+j]); printf("*(*(mas2+i)+j)= %2d\n", *(*(mas2+i)+j)); printf("*(c[і]+j)= %2d\n", *(c[і]+j)); getch(); randomize(); printf("\nинициализация двовимірного масиву у функції\n"); printf("з виділенням пам'яті для масиву в \"купі\":\n"); para=matrix(N,M); for(i=0;i for(j=0;j { printf("mas2[%d][%d]=%2d ",i,j,*(para+i*M+j)); if ((j+1)%M==0) printf("\n"); } printf("\nвведите індекси елемента двовимірного масиву і scanf("%d %d",&і,&j); printf("mas2[%d][%d]=%2d зсув: %2d байт ",і,j,*(para+і*M+j),\ (і*M+j)*sizeof(int)); free(para); //Звільнення пам'яті, виділеної для масиву в "купі" getch(); randomize(); printf("\nинициализация тривимірного масиву:\n"); for(i=0;i for(j=0;j { for(k=0;k { mas3[i][j][k]=random(10); printf("mas3[%d][%d][%d]=%2d ",i,j,k,mas3[i][j][k]); if ((k+1)%4==0) printf("\n"); } if ((j+1)%N==0) printf("\n"); } printf("\nвведите індекси елемента тривимірного масиву і scanf("%d %d %d", &і, &j, &k); printf("mas3[%d][%d][%d]=%2d зсув: %2d байт\n",і,j,k,\ mas3[і][j][k],(і*M*N+j*M+k)*sizeof(int)); printf("Інші форми запису доступу до елементів тривимірного масиву:\n"); printf("*(**mas3+i*M*N+j*M+k)= %2d\n",*(**mas3+i*M*N+j*M+k)); printf("*(*(*(mas3+i)+j)+k)= %2d\n",*(*(*(mas3+i)+j)+k)); getch(); }//main int * matrix(int n, int m) { int i,j; randomize(); //Виділення пам'яті для масиву в "купі" int *pa=(int *)malloc(n*m*sizeof(int)); for(і=0;і for(j=0;j { *(pa+i*m+j)=random(51)-25; // printf("mas[%d][%d]=%2d ",i,j,pa[i*m+j]); // if ((j+1)%m==0) printf("\n"); } return pa; } /* Ініціалізація одномірного масиву: mas1[0]= 6 mas1[1]= 0 mas1[2]= 0 mas1[3]= 8 mas1[4]= 4 mas1[5]= 0 mas1[6]= 7 mas1[7]= 4 mas1[8]= 0 mas1[9]= 7 mas1[10]= 6 mas1[11]= 6 Введіть індекс елемента одномірного масиву і mas1[10]= 6 зсув: 20 байт Ініціалізація двовимірного масиву c використанням масиву покажчиків: c[0][0]= 7 c[0][1]= 0 c[0][2]= 0 c[0][3]= 1 c[1][0]= 3 c[1][1]= 8 c[1][2]= 6 c[1][3]= 3 c[2][0]= 6 c[2][1]= 9 c[2][2]= 6 c[2][3]= 1 Введіть індекси елемента двовимірного масиву і mas2[1][3]= 3 зсув: 14 байт Інші форми запису доступу до елементів двовимірного масиву: *(*mas2+i*M+j) = 3 (*mas2)[i*M+j]= 3 *(*(mas2+i)+j) = 3 *(c[і]+j) = 3 Ініціалізація двовимірного масиву у функції с виділенням пам'яті для масиву в "купі": mas2[0][0]= 7 mas2[0][1]=-1 mas2[0][2]=19 mas2[0][3]=15 mas2[1][0]=-6 mas2[1][1]=-15 mas2[1][2]= 2 mas2[1][3]=11 mas2[2][0]=-24 mas2[2][1]=24 mas2[2][2]=21 mas2[2][3]=-6 Введіть індекси елемента двовимірного масиву і mas2[2][0]=-24 зсув: 16 байт Ініціалізація тривимірного масиву: mas3[0][0][0]= 1 mas3[0][0][1]= 9 mas3[0][0][2]= 3 mas3[0][0][3]= 1 mas3[0][1][0]= 8 mas3[0][1][1]= 7 mas3[0][1][2]= 3 mas3[0][1][3]= 8 mas3[0][2][0]= 0 mas3[0][2][1]= 3 mas3[0][2][2]= 9 mas3[0][2][3]= 0 mas3[1][0][0]= 8 mas3[1][0][1]= 6 mas3[1][0][2]= 8 mas3[1][0][3]= 5 mas3[1][1][0]= 2 mas3[1][1][1]= 6 mas3[1][1][2]= 5 mas3[1][1][3]= 5 mas3[1][2][0]= 4 mas3[1][2][1]= 9 mas3[1][2][2]= 5 mas3[1][2][3]= 4 Введіть індекси елемента тривимірного масиву і mas3[1][2][2]= 5 зсув: 44 байт Інші форми запису доступу до елементів тривимірного масиву: *(**mas3+i*M*N+j*M+k)= 5 *(*(*(mas3+i)+j)+k)= 5 ^ Приклад програми на С++ Скласти програму для обробки багатомірних масивів з використанням циклів. Індивідуальні завдання приведені в таблиці 13.1.
#include void main() {int i,n; double p; cout<<"введите число элементов столбца\n"; cin>>n; double*x=new double[n]; cout<<"введите столбец\n"; for(i=0;i cin>>x[i]; p=1; for(i=0;i {if(x[i]>0) p=p*x[i]; } cout<<"p="< } ^ Хід роботи 1.Вивчити теоретичні відомості. 2.Відповідно до індивідуального завдання розробити алгоритм і програму з застосуванням покажчиків на масив і масив покажчиків для роботи з двовимірним і тривимірним масивом. 3.Показати використання різних видів синтаксичних конструкцій, включаючи індексні вираження і покажчики на тип елементів масиву для доступу до елементів масиву. 4.Набрати і налагодити програму на комп'ютері. 5.Вивчити роботу операторів. 6.Одержати результати. 7.Оформити звіт. 8.Підготуватися до захисту лабораторної роботи, вивчивши контрольні питання по даній темі. Вимоги до змісту звіту приведені в лабораторній роботі №1. Індивідуальне завдання Скласти програму для обробки багатомірних масивів з використанням циклів. Індивідуальні завдання приведені в таблиці 13.1. Таблиця 13.1 - індивідуальне завдання
^ Контрольні питання 1.Приведіть приклади оголошення масивів з різною розмірністю. Поясните організацію збереження елементів масиву. 2.Як відбувається масштабування при послідовному разіменування покажчика (імені масиву) у процесі доступу до елементів? Які синтаксичні конструкції можна використовувати для доступу до елементів масиву? 3.Приведіть загальну формулу для масиву Тип Ім'я [N][M][K] при доступі до заданого елемента Ім'я [i][j][k] і поясните її. 4.Як здійснюється ініціалізація багатомірних масивів? 5.Чи залежить ініціалізація масиву від класу пам'яті при оголошенні? 6.Як використовувати засіб typedef для оголошення типу масиву. 7.Який з індексів можна не вказувати при явній ініціалізації масивів? 8.Чи можна вказувати не всі елементи при ініціалізації? Як використовувати дужки при ініціалізації? 9.Який індекс не використовується при розрахунку величини зсуву покажчика в процесі доступу до елемента масиву? 10.Для чого використовується зазначений індекс? |