ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 23.12.2021
Просмотров: 121
Скачиваний: 2
ДИНАМІЧНІ АРИФМЕТИЧНІ МАСИВИ
Динамічний масив може бути будь-якій розмірності. За допомогою покажчиків можна формувати одновимірні і багатовимірні масиви з розміром, не заданим до виконання програми, і з даними будь-якого типу. При цьому розмір масиву визначається в процесі виконання програми, наприклад шляхом введення кількості його елементів з файлу з початковими даними або з клавіатури в режимі діалогу. Використовуючи тільки покажчик, можна обробляти значення одновимірних і багатовимірних масивів. Динамічні масиви арифметичних даних розглянемо на прикладах роботи з одновимірними і двовимірними масивами. Наприклад:
int *mi; // – покажчик на дані типу int
float *mf; // – покажчик на дані типу float
char *st; // – покажчик на дані типу char
Ці покажчики можна використовувати як для роботи з скалярними значеннями відповідного типу, так і з масивами наперед не певного розміру.
Приклад програми заповнення одновимірного динамічного масиву значеннями типу int представлений в лістингу 1. У ньому k – кількість елементів масиву визначається в режимі діалогу введенням з клавіатури. Після введення значення до за допомогою функції malloc виділяється ОП для масиву з до значень типу int. Потім i-елементи масиву заповнюються значеннями: 100* i. До i-елементу масиву можна використовувати звернення у вигляді *(а + i) або а[i].
Лістинг 1. Використання покажчика для роботи з одновимірним масивом
#include <stdio.h>
#include <alloc.h>
#include <conio.h>
void main()
{ int i, k, *a; /* k – кількість елементів масиву,
а – покажчик на масив */
clrscr(); // – очистити екран
printf("Введіть кількість елементів масива:\n");
scanf (" %d", &k); // – введення значення k
а = (int *) malloc( k * sizeof(int)); // – запит ОП
// Заповнення масиву:
for ( i = 0; i < k; i++ ) { * (а + i) = 100 * i;
// або: а[i]= 100 * i;
printf( "а[%d] = %4d\n", i, а[i]); }
free (a); // – звільнення ОП
printf ("\nДля завершення програми натисніть будь-яку клавишу\n");
getch(); // – натиснути будь-яку клавішу
}
Приклад програми для роботи з динамічним масивом даних типу int приведений в лістингу 2. У програмі спочатку вводиться k – кількість елементів одновимірного масиву, а потім самі значення елементів вводяться і виводяться.
Лістинг 2. Робота з одновимірним динамічним масивом: введення даних і виведення його значень.
#include <stdio.h>
#include <alloc.h>
#include <conio.h>
void main()
{ int i, k, *a; /* k – кількість елементів масиву, a – покажчик на масив */
clrscr(); // - очистити екран
printf("Введіть кількість елементів масива:\n");
scanf (" %d", &k); // - введення значення k
a=(int *) malloc(k*sizeof(int)); // - запрос ОП
// Заполнение массива:
for ( i = 0; i <k; i++ ) { * (a + i) = 100 * i;
// или: a[i] = 100 * i;
printf( "a[%d] = %4d\n", i, a[i] ); }
free (a); // - звільнення ОП
printf ("\nДля завершення програми натисніть будь-яку клавішу\n");
getch(); // - натиснути будь-яку клавішу
}
Початкові дані: 5 1 2 3 4 5
Результати виконання програми:
а[0] = 1 а[1] = 2 а[2] = 3 а[3] = 4 а[4] = 5
Аналогічно можна організувати роботу з масивами іншого типу, наприклад float, double або масиву структур.
У лістингу 3 приведений приклад програми для оголошення і роботи з одновимірним динамічним масивом даних типу int.
Лістинг 3. Робота з одновимірним динамічним масивом. Кількість і значення його елементів вводяться з клавіатури.
#include <stdio.h>
#include <conio.h>
#include <alloc.h>
void main ()
{ int i, k, *p; clrscr(); // - очистити екран
printf ("\nВведіть кількість елементів масиву : ");
scanf ( "%d", &k); // - введення k - кількості елементів масиву
printf("Кількість елементів масиву = %d\n", k);
p = (int*) malloc(k * sizeof(int)); // - запит на ОП k-елементам
for (i = 0; i <k; i++)
{ printf ("Введіть %d-e значення : ", i) ;
// Введення значення чергового елементу:
scanf ( "%d",(p+i)); }
// или: (р + i), или: &p[i] }
printf ("Введеня значення: \n");
//p = p - k; // - встановлення покажчика р на початок масиву
for ( i = 0; i < k; i++)
printf ( "%d ", *(p+i)); // або: *(p + i), або: p[i] printf("\n");
free(p); //- звільнення ОП
printf ("\nДля завершення програми натисніть будь-яку клавішу\n");
getch(); // - натиснути будь-яку клавішу
}
/* У випадках "або" покажчик р не змінювати: тобто прибрати оператор установки його на початок масиву і не змінювати його при звільненні ОП */
Результати виконання програми:
Введіть кількість елементів масиву : 3
Кількість елементів масиву = 3
Введіть 0-е значення 1
Введіть 1-е значення 2
Введіть 2-е значення 3
Введені значення:
1 2 3
У програмі лістингу 3 використовуються змінні: i – для перебору номерів елементів масиву; k – кількість елементів масиву; р – покажчик на дані типу int. У режимі діалогу з клавіатури вводиться значення k – кількості елементів масиву. Потім виділяється ОП для до значень типу int. Потім в режимі діалогу з клавіатури вводяться значення елементів масиву. Після введення всього масиву його значення виводяться на екран.
У лістингу 4 приведений приклад програми для оголошення, введення і виведення значень елементів динамічного двовимірного масиву значень типу int. Процес роботи з масивом аналогічний викладеному для масиву в лістингу 3.
Лістинг 4. Робота з двовимірним динамічним масивом. Кількість його рядків, стовпців і значення елементів вводяться з клавіатури.
#include <stdio.h>
#include <alloc.h>
#include <conio.h>
void main()
{ int *p, i, j, ik, jk; clrscr(); // - очистити екран
printf ("\nВведіть кількість рядків матриці : ");
scanf ("%d", &ik);
printf ("Кількість рядків матриці = %d", ik);
printf("\nВведіть кількість значень в рядку : ");
scanf("%d", &jk);
printf ("Кількість значень в рядку = %d", jk);
p = (int*) malloc(( ik * jk ) * sizeof (int));
for (i=0; i < ik; i++)
{ printf("\n Вводиться %d-й рядок\n", i + 1);
for (j = 0; j < jk; j++)
{ printf ("Введіть %d-e значення : ", j + 1);
scanf ( "%d", (p+jk*i+j) ); // або: p+i*jk+j або: &p[i*jk+j]
}
}
printf ("\nВведена матриця таких значень: \n");
// p позначає значення покажчика на 0-елемент 0-рядка матриці:
// p = p - ik * jk; // - це прибрати для "або"
for (i = 0; i < ik; i++)
{ for ( j = 0; j < jk; j++)
printf ( "%d ",*(p+j+i*jk)); // або: *(p+i*jk+j) або: p[i*jk+j]);
printf("\n");
}
free( p); // - звільнення ОП, починаючи з 0-елементу
// для "або": free (p);
printf("\nДля завершення програми натисніть будь-яку клавішу\n");
getch(); // - натиснути будь-яку клавішу
}
Результати виконання програми:
Введіть кількість рядків матриці : 2
Кількість рядків матриці = 2
Введіть кількість значень в рядку : 3
Кількість значень в рядку = 3
Вводиться 1-а - рядок
Введіть 1-е значення : 1
Введіть 2-е значення : 2
Введіть 3-е значення : 3
Вводиться 2-а - рядок
Введіть 1-е значення : 4
Введіть 2-е значення : 5
Введіть 3-е значення : 6
Введена матриця таких значень:
1 2 3
4 5 6
У програмі листинга 4 використовуються змінні:
- i, j – для перебору номерів рядків і стовпців елементів масиву;
- ik, jk – кількість рядків і стовпців в рядку масиву;
- р – покажчик на дані типу int.
У режимі діалогу з клавіатури вводяться значення ik і jk – кількості рядків і стовпців масиву. Виділяється ОП для (ik *jk) значень типу int . Потім в режимі діалогу з клавіатури вводяться значення елементів масиву. Після введення всього масиву його значення виводяться на екран.
Вільні арифметичні масиви
Роботу з вільним масивом арифметичних даних і з динамічним виділенням ОП масиву розглянемо на прикладах.
У прикладі лістингу 5 кількість і значення елементів масиву вводяться з клавіатури в режимі діалогу. Для формування вільного масиву використовується р – статичний масив з 10 покажчиків на дані типу int. У нульовий стовпець кожного рядка вільного масиву вводиться кількість її елементів, а потім – значення елементів цього рядка.
Лістинг 5. Робота із статичним масивом покажчиків для формування вільного масиву цілих значень.
#include <stdio.h>
#include <alloc.h>
#include <conio.h>
void main()
{ int *p[10], *p1, i, j, ik, jk; clrscr(); // - очистити екран
printf ("\nВведiть кiлькiсть рядкiв матрицi;\n"
"воно повинне бути не бiльшe 10: ");
scanf ( "%d", &ik);
printf ("Кiлькiсть рядкiв матрицi = %d", ik);
for (i = 0; i < ik; i++)
{ printf("\nВкажiть кiлькiсть значень в %d-u рядку : ", i+1);
scanf ("%d", &jk);
printf ("Кiлькiсть значень в %d-й рядку = %d", i+1, jk);
p[i]= p1 = (int*) malloc(( jk + 1) * sizeof (int));
*p1++ = jk; // Або: *p[i] = jk; або: *(p+i) = jk;
printf("\n Вводиться %d- й рядок \n", i + 1);
for (j = 1; j <= jk; j++)
{ printf ("Введiть %d-e значення : ", j );
scanf ( "%d", p1++ ); // Або: (p[i]+j), (*(p+i)+j)
} // - кiнець циклу по 'j' }
} // - кiнець циклу по 'i'
printf ("\nВведена матриця таких значень: \n");
for ( i = 0; i < ik; i++) { p1 = p[i];
jk = *p1; // або: jk = *p[i]; або: jk = *(p+i);
for ( j = 0; j <= jk; j++)
printf ( "%d ", *p1++);
// Або: printf ( "%d ", *(p[i]+j) );
// Або: printf ( "%d ", *(*(p+i)+j) );
printf("\n"); }
// Звiльнення ОП даних:
for ( i = 0; i < ik; i++)
free(p[i]); //- звiльнення ОП i-рядки
printf ("\nДля завершення програми натиснiть будь-яку клавiшу\n");
getch(); // - натиснути будь-яку клавішу
}
Результати виконання програми:
Введіть кількість рядків матриці;
воно повинне бути не більш 10: 2
Кількість рядків матриці = 2
Вкажіть кількість значень в 1-й рядку : 2
Кількість значень в 1-й рядку = 2
Вводиться 1-й рядок
Введіть 2-е значення : 3
Введіть 3-е значення : 4
Вкажіть кількість значень в 2-й рядку : 3
Кількість значень в 2-й рядку = 3
Вводиться 2-й рядок
Введіть 1-е значення : 5
Введіть 2-е значення : 6
Введіть 3-е значення : 7
Введена матриця таких значень:
2 3 4
3 5 6 7
У програмі лістингу 5 використовуються такі змінні:
- p – ім'я статичного масиву з 10 покажчиків на дані типу int;
- p[i] – елемент масиву р, зберігає значення покажчика на початок ОП для значень i-рядки даних;
- p1 – скалярний покажчик на дані типу int;
- i – змінна для перебору номерів рядків масиву;
- ik – кількість рядків динамічного масиву;
- j – змінна для перебору номерів стовпців масиву;
- jk – кількість елементів масиву в рядку.
Для створення вільного масиву в режимі діалогу з клавіатури вводиться значення ik – кількості рядків вільного масиву. Воно повинне бути не більш 10 – кількості елементів р масиву покажчиків. Потім воно виводиться на екран. Для формування ik рядків організовується перебір номерів рядків по i від 0 до ik -1.
Для кожного рядка:
1) вводиться значення jk – кількість значень в рядку;
2) виділяється ОП для розміщення (jk + 1) - значень в i-рядку вільного масиву:
а) одне – для значення jk і
б) jk – для розміщення значень елементів i-рядка;
в) адреса розміщення елементів i-рядка поміщається в i-елемент масиву р і в змінну p1:
p[i]=p1 = (int*) malloc(( jk + 1) * sizeof (int));
3) у нульовий стовпець i – го рядка поміщається значення jk:
*p1++ = jk;
4) перебираються значення j номерів стовпців елементів i-рядка від 1 до jk;
5) для кожного j з клавіатури вводиться чергове значення і поміщається в ОП:
scanf(“%d”, p1++);
при цьому за допомогою р1++ спочатку за адресою – значенню покажчика р1 вводиться значення чергового елементу масиву, а потім значення покажчика збільшується на 1.
Після закінчення створення вільного масиву виконується виведення його значень на екран. Для цього перебираються значення і-номерів рядків масиву від 0 до (іk-l). Формується значення покажчика на початок і-рядка (на її нульовий елемент): р1=р[i]; формується кількість елементів і-рядка: jk= *p1, потім перебираються номери стовпців і-рядка масиву по j від 1 до jk. Кожне значення виводиться на екран з допомогою: printf (“%d “, *p1++); при цьому за допомогою виразу *p1++ спочатку виводиться значення *p1, а потім значення покажчика збільшується на 1. Таким чином за допомогою змінної pl виконується перебір адрес значень елементів масиву арифметичних даних при їх створенні і виведенні.
Після закінчення роботи програми ОП, виділена за допомогою функції malloc, звільняється за допомогою функції free. Для цього перебираються номери рядків по і від 0 до ik-1, і для кожного значення i звільняється ОП для даних рядка оператором free(p[i]);.
Аналогічні результати можна одержати, якщо використовувати динамічне виділення ОП не тільки елементам вільного масиву, але і масиву покажчиків, тобто з виділенням ОП масиву покажчиків, і вільному арифметичному масиву, приведений в лістингу 6. У програмі лістингу 6 в режимі діалогу вводиться значення ik – кількість рядків вільного масиву. Потім для р– динамічного масиву покажчиків виділяється ОП для ik його елементів за допомогою функції malloc. Звернення до елементів масиву покажчиків виконується звичайним способом, у вигляді p[i]. У іншому робота програми лістингу 6 аналогічна роботі програми лістингу 5. Для звернення до елементів масиву можна використовувати покажчик р1 або елемент масиву покажчиків p[i].
Лістинг 6. Робота з динамічним масивом покажчиків для вільного масиву цілих значень
#include <conio.h>
#include <stdio.h>
#include <alloc.h>
void main()
{ int **p, // p - iм'я покажчика на динамiчний масив покажчикiв
*p1, i, j, ik, jk; clrscr(); // очистити екран
printf ("\nВвeдiть кiлькiсть рядкiв матрицi: \n");
scanf ( "%d", &ik);
printf ("Кiлькiсть рядкiв матрицi = %d", ik);
// Запит ОП динамiчному масиву покажчикiв:
p=(int**) malloc (ik * sizeof(int*));
for (i=0; i < ik; i++)
{ printf("\nВкажiть кiлькiсть значень в %d рядку : ", i+1 );
scanf ("%d", &jk);
printf("Кiлькiсть значень в %d рядку = %d ", i+1, jk );
//Запит ОП i-рядку вiльного масиву:
p[i]= p1 = (int*) malloc ((jk+1) * sizeof (int));
*p1++ =jk; //или *p[i] =jk; або: *(p+i)= jk;
printf("\n Вводиться %d-й рядок \n", i+1);
for (j=1; j<=jk; j++)
{printf ("\n Введiть %d-е значення : ", j);
scanf ("%d", p1++); // Або: (p[i]+j), (*(p+i)+j)
} // - кiнець циклу по 'j'
} // - кiнець циклу по 'i'
for (i=0; i<jk; i++)
{p1 = p[i]; jk = *p1;
for (j=0; j<jk; j++)
printf ("%d ", *p1++);
//або printf ("%d ", *(p[i]+j) );
//або printf ("%d ", *(*(p+i)+j) );
printf ("%d ", *p1);
printf ("\n"); }
// Звiльнення ОП i-рядкa вiльного масиву:
free (p); // Звiльнення ОП покажчика для масиву покажчик?в
printf ("\nДля завершення роботи натиснiть будь-яку клавiшу\n");
getch (); // - натиснути будь-яку клавiшу
}