- •Елементи мови с.Основні символи
- •Ключові слова
- •Ідентифікатори
- •Константи
- •Лексеми
- •Коментарі
- •Умовні оператори. Логічні вирази
- •Форми оператора if
- •Оператор вибору switch
- •Перерахування типів
- •Перетворення типів
- •Оператори циклу
- •Оператор while
- •Оператор for
- •Оператор do-while
- •Оператори переходу
- •Cтруктури
- •Об'єднання (суміші)
- •Робота з структурами.
- •Ініціалізація структур
- •Робота з обєднаннями
- •Визначення об'єктів та типів
- •Методи доступу до елементів масивів
- •Покажчики на багатовимірні масиви
- •Операції з вказівниками
- •Робота з покажчиками.
- •Покажчики на структуру
- •Масиви структур
- •Динамічне розміщення масивів
- •Робота з динамічними масивами
- •Робота з непрямою адресацією
- •Робота з покажчиками як параметрами функцій
- •Використання вказівників
- •Операції з вказівниками
- •Використання вказівників в програмі
- •Робота з файлами
- •Відкриття файлу
- •Обробка відкритого файлу
- •Перевірка ознаки кінця файлу
- •Закриття файлу
- •Функції введення-виведення
- •Робота з текстовими файлами
- •Функція форматованого виведення printf ()
- •Основні формати
- •Модифікації форматів
- •Функція форматованого введення scanf ()
- •Робота функції scanf ()
- •Призначеня функцій бібліотеки введення-виведення
- •Макрокоманди
- •Потокові інтерфейси введення-виведення
- •Ближні покажчики (near)
- •Дальні покажчики (far)
- •Покажчики huge
- •Функції для роботи з рядками
- •Динамічні рядки, клас string
- •Визначення поточної робочої директорії
- •Визначення поточного каталогу диска
- •Визначення / встановленн поточного диска
- •Пошук файлу
- •Створення, видалення, зміна директорій
- •Приклад програми для роботи з директоріями
- •Перегляд каталогу диска
- •Параметри структури ffblk
- •Робота з клавіатурою
- •Робота з файлами
- •Послідовний доступ до елементів двійкових файлів
- •Організація довільного доступу до елементів двійкових файлів
- •Робота динамічних структур даних.
- •Функції управління пам'яттю
- •Атрибути файлів.
- •Параметри
- •Динамічні структури даніх
- •Лінійні списки
- •Стек. Загальні поняття.
- •Приклад використання стеку
- •Основні визначення
- •Приклад використання дерев
Динамічне розміщення масивів
При динамічному розподілі пам'яті для масивів слід описати відповідний покажчик і привласнювати йому значення за допомогою функції calloc. Одновимірний масив a [10] з елементів типу float можна створити наступним чином
float * a;
a = (float *) (calloc (10, sizeof (float));
Для створення двовимірного масиву спочатку потрібно розподілити пам'ять для масиву покажчиків на одномірні масиви, а потім розподіляти пам'ять для одновимірних масивів. Нехай, наприклад, потрібно створити масив a [n] [m], це можна зробити за допомогою наступного фрагменту програми:
# Include
main ()
{Double ** a;
int n, m, i;
scanf ("% d% d", & n, & m);
a = (double **) calloc (m, sizeof (double *));
for (i = 0; i <= m; i + +)
a [i] = (double *) calloc (n, sizeof (double));
. . . . . . . . . . . . }
Аналогічним чином можна розподілити пам'ять і для тривимірного масиву розміром n, m, l. Варто тільки пам'ятати, що непотрібну для подальшого виконання програми пам'ять слід звільняти за допомогою функції free.
# Include
main ()
{Long *** a;
int n, m, l, i, j;
scanf ("% d% d% d", & n, & m, & l);
/ * -------- Розподіл пам'яті -------- * /
a = (long ***) calloc (m, sizeof (long **));
for (i = 0; i <= m; i + +)
{A [i] = (long **) calloc (n, sizeof (long *));
for (j = 0; i <= l; j + +)
a [i] [j] = (long *) calloc (l, sizeof (long));
}
. . . . . . . . . . . .
/ * --------- Звільнення пам'яті ---------- * /
for (i = 0; i <= m; i + +)
{For (j = 0; j <= l; j + +)
free (a [i] [j]);
free (a [i]);
}
free (a); }
Робота з динамічними масивами
Розглянемо ще один цікавий приклад, в якому пам'ять для масивів розподіляється в викликається функції, а використовується в викликаній. У такому випадку в викликувану функцію потрібно передавати покажчики, яким будуть присвоєні адреси виділюваної для масивів пам'яті.
Приклад:
# Include
main ()
{Int vvod (double ***, long **);
double ** a; / * покажчик для масиву a [n] [m] * /
long * b; / * покажчик для масиву b [n] * /
vvod (& a, & b);
.. / * В функцію vvod передаються адреси покажчиків, * /
.. / * А не їх значення * /
.. }
int vvod (double *** a, long ** b)
{Int n, m, i, j;
scanf ("% d% d", & n, & m);
* A = (double **) calloc (n, sizeof (double *));
* B = (long *) calloc (n, sizeof (long));
for (i = 0; i <= n; i + +)
*a[i]=(double *)calloc(m,sizeof(double));
..... }
Відзначимо також ту обставину, що покажчик на масив не обов'язково повинен показувати на початковий елемент деякого масиву. Він може бути зрушене так, що початковий елемент буде мати індекс відмінний від нуля, причому він може бути як позитивним так і негативним.
Приклад:
# Include
int main ()
{Float * q, ** b;
int i, j, k, n, m;
scanf ("% d% d", & n, & m);
q = (float *) calloc (m, sizeof (float));
/ * Зараз покажчик q показує на початок масиву * /
q [0] = 22.3;
q-= 5;
/ * Тепер початковий елемент масиву має індекс 5, * /
/ * А кінцевий елемент індекс n-5 * /
q [5] = 1.5;
/ * Зсув індексу не призводить до перерозподілу * /
/ * Масиву в пам'яті і зміниться початковий елемент * /
q [6] = 2.5; / * - це другий елемент * /
q [7] = 3.5; / * - це третій елемент * /
q + = 5;
/ * Тепер початковий елемент знову має індекс 0, * /
/ * А значення елементів q [0], q [1], q [2] дорівнюють * /
/ * Відповідно 1.5, 2.5, 3.5 * /
q + = 2; / * Тепер початковий елемент має індекс -2, * /
/ * Наступний -1, потім 0 і т.д. по порядку * /
q [-2] = 8.2;
q [-1] = 4.5;
q-= 2;
/ * Повертаємо початкову індексацію, три перших * /
/ * Елементу масиву q [0], q [1], q [2], мають * /
/ * Значення 8.2, 4.5, 3.5 * /
q -;
/ * Знову змінимо індексацію. * /
/ * Для звільнення області пам'яті в якій розміщений * /
/ * Масив q використовується функція free (q), але оскільки * /
/ * Значення покажчика q зміщено, то виконання * /
/ * Функції free (q) призведе до непередбачуваних наслідків. * /
/ * Для правильного виконання цієї функції * /
/ * Покажчик q повинен бути повернений в початкове * /
/ * Стан * /
free (+ + q);
/ * Розглянемо можливість зміни індексації та * /
/ * Звільнення пам'яті для двовимірного масиву * /
b = (float **) calloc (m, sizeof (float *));
for (i = 0; i <m; i + +)
b [i] = (float *) calloc (n, sizeof (float));
/ * Після розподілу пам'яті початковим елементом * /
/ * Масиву буде елемент b [0] [0] * /
/ * Виконаємо зрушення індексів так, щоб початковим * /
/ * Елементом став елемент b [1] [1] * /
for (i = 0; i <m; i + +) - b [i];
b -;
/ * Тепер привласнимо кожному елементу масиву суму його * /
/ * Індексів * /
for (i = 1; i <= m; i + +)
for (j = 1; j <= n; j + +)
b [i] [j] = (float) (i + j);
/ * Зверніть увагу на початкові значення лічильників * /
/ * Циклів i та j, він починаються з 1 а не з 0 * /
/ * Повернемося до колишньої індексації * /
for (i = 1; i <= m; i + +) + + b [i];
b + +;
/ * Виконаємо звільнення пам'яті * /
for (i = 0; i <m; i + +) free (b [i]);
free (b);
...
return 0; }
Як останній приклад розглянемо динамічний розподіл пам'яті для масиву покажчиків на функції, що мають один вхідний параметр типу double і повертають значення типу double.
приклад:
# include
# include
double cos (double);
double sin (double);
double tan (double);
int main ()
{Double (* (* masfun)) (double);
double x = 0.5, y;
int i;
masfun = (double (* (*)) (double))
calloc (3, sizeof (double (* (*)) (double)));
masfun [0] = cos;
masfun [1] = sin;
masfun [2] = tan;
for (i = 0; i <3; i + +);
{Y = masfun [i] (x);
printf ("\ n x =% g y =% g", x, y);
}
return 0; }
Питання для контролю:
1.Як відбувається динамічне розміщення масивів?
2. Як створити одновимірний масив з елементами типу int?
3.Як створити вказівник на початок масиву?
Література:
1.Шилдт Г.: Пер. с англ. –М.: Издательский дом “Вильямс”, 2002. –704с. –стор 137-140
Урок №28
(згідно робочої навчальної програми)
Тема: Подвійна непряма адресація, покажчики як параметри функції
Питання:
1.Робота з непрямою адресацією
