
- •Базові типи даних. Уведення-виведення та форматування даних
- •Циклічні обчислювальні процеси
- •Одновимірні масиви. Статичні й динамічні масиви
- •Двовимірні масиви. Динамічне виділення пам'яті під двовимірні масиви
- •Функції користувача
- •Рядки. Робота з рядком як із масивом символів
- •Контрольні запитання й завдання
- •Контрольні запитання й завдання
- •Контрольні запитання й завдання
Контрольні запитання й завдання
Дайте визначення масиву й типу масиву.
Як здійснюється доступ до елементів одновимірного масиву?
Чи може список ініціалізації масиву містити більше (менше) значень, ніж вказано в оголошенні масиву?
У якому фрагменті програми iнiцiалiзацiя масиву виконана неправильно?
int s[3] = {1; 1; 1};
int d[] = {10, 10, 10};
double ext[3] = {4, 5.5};
int a[3] = {1, 4}.
Нехай оголошений масив int w[3] = {1, 2, 3};. Чому дорівнює вираз *(w + 1)?
Що буде виведено на екран унаслідок виконання такого фрагмента:
define SQ(a) a+5
void main () { int x = 5; printf(“%d \n“, SQ(x)*SQ(x) ); } ?
Як організовуються введення та виведення масиву, його ініціалізація?
Як організовується пошук мінімального або максимального елемента?
Пам'ять для даних матриці виділяється так (один із варіантів):
для кожного рядка матриці пам'ять виділяється окремо (S областей пам'яті по S елементів у кожній), і в масив покажчиків заносяться покажчики на відповідні області. Таким чином, матриця необов'язково займає суміжні області пам'яті. Можна звертатися до даних матриці, указуючи два індекси. Виділення пам'яті (і відповідно звільнення) слід виконувати в циклі.
double** Ar; // покажчик на масив покажчиків
int S; // розмірність матриці
printf ( "Уведіть розмірність матриці ->" ); scanf ( "%d",&S );
// виділення пам'яті для масиву покажчиків на рядки масиву
Ar = (double**) malloc ( sizeof ( double* ) * S );
// виділення пам'яті для кожного рядка і заповнення масиву покажчиків
// кожному елементу масиву покажчиків на рядки присвоюється адреса
// початку ділянки пам'яті, виділеного під рядок двовимірного масиву
for ( int i = 0; i < S; ++i )
Ar [i] = ( double* ) malloc ( sizeof (double) * S );
// заповнення масиву дійсними числами
srand( (unsigned)time( NULL ) );
for ( int i = 0; i < S; ++i)
for ( int j = 0; j < S; ++j)
*(*(Ar + i) + j) = (double) rand() / 100 - 50;
Спосіб виділення пам'яті під масив n×m, коли обидві його розмірності задаються на етапі виконання програми, із використанням операції new:
int n, m;
printf ("Уведіть кількість рядків і стовпців: ");
scanf (“%d %d”, n, m);
int **a = new int *[n];
for (int i = 0; i < n; ++i)
а[i]= new int [m];
Контрольні запитання й завдання
Яким є принцип зображення двовимірного масиву в оперативній пам’яті?
Як здійснюється доступ до елементів двовимірного масиву?
Виберіть правильно виконану ініціалізацію двовимірного масиву:
int g[3][2] = {2, 2}, {2, 2}, {2, 2};
int p[2][3] = {{1, 1, 1}, {5, 5, 5}};
int dig[2][4] = [[0, 0], [0, 0], [0, 0], [0, 0]];
int p[2][3] = {1, 1, 1, 5, 5, 5};
Чи можна задати список ініціалізації для динамічного масиву?
Чому буде дорівнювати значення змінної z після виконання такого фрагмента коду?
int a[] = { 3, 5, 3.4, 67.6, 55, -40.64, -1 };
int *b = &a[6];
int z = *(b - 3);
Як організовується введення та виведення двовимірного масиву, ініціалізація двовимірного масиву, пошук мінімального або максимального елемента?
Скільки рядків i стовпців матиме масив int a[3][5]?
Яку кількість пам’яті займатиме масив double monitor[3][4]?
//-----------------------------------------------------------------------------------
void inArray ( double**, int ); // заповнення масиву дійсними числами
void outArray ( double**, int ); // виведення матриці
double determinant ( double**, int ); // обчислення визначника
//-----------------------------------------------------------------------------------
int main() {
double** Ar; // покажчик на масив покажчиків
int S; // розмірність матриці
printf ( "Enter the dimension of matrix ->" );
scanf ( "%d", &S );
Ar = (double**) malloc ( sizeof ( double* ) * S );
for ( int i = 0; i < S; ++i )
Ar [i] = ( double* ) malloc ( sizeof (double) * S );
inArray ( Ar, S );
outArray ( Ar, S );
printf("\n");
printf("\tDeterminant = %10.4lf", determinant( Ar, S ));
printf("\n\n");
outArray ( Ar, S );
for ( int i = 0; i < S; free ( *(Ar + i++) ) );
free (Ar);
printf ("\nThe end\n"); getch();
return 0;
}
void inArray ( double** Ar, int S ) {
srand( (unsigned)time( NULL ) );
for ( int i = 0; i < S; ++i)
for ( int j = 0; j < S; ++j)
*(*(Ar + i) + j) = (double) rand() / 100 - 50;
}
void outArray ( double** Ar, int S ){
for ( int i = 0; i < S; ++i ) {
for ( int j = 0; j < S; printf("%8.2lf", *(*(Ar + i) + j++)) );
putchar('\n');
}
}
void triangular (double** a, int k, int S ){ // k - номер рядка, що обчислюється
double koef; // коефіцієнт "виключення" елемента
for (int i = k+1; i < S; ++i) { // обирання наступного рядка
koef = a[i][k] / a[k][k]; // обчислення коефіцієнта "виключення"
for (int j = 0; j < S; ++j) // обчислення елементів у вибраному рядку
a[i][j] = a[i][j] - a[k][j] * koef;
}
return;
}
int change ( double** a, int i, int S ){
//i - номер рядка, що міняється місцем із будь-яким іншим рядком
int sign = 1; // ознака зміни знака визначника
for (int j = 0; j < S-i; ++j) // пошук рядка з ненульовим опорним елементом
if ( a[i+j][i] != 0 ) { // якщо шуканий елемент ненульовий
for (int k = 0; k < S; ++k)// виконується переставлення рядків
{ double tmp; tmp = a[i][k]; a[i][k] = a[i+j][k]; a[i+j][k] = tmp; }
sign = -sign; // ознака зміни знака визначника
}
return sign;
}
double determinant ( double** a, int S ){ // обчислення визначника
void triangular ( double**, int, int ); // обчислення трикутноі матриці
int change ( double**, int, int ); // перестановка рядків
int sign = 1; // ознака зміни знака визначника
double det; // значення визначника матриці
for ( int i = 0; i < S-1; ++i ) {
if ( a[i][i] == 0 ) // якщо опорний елемент дорівнює нулю,
sign = change(a, i, S); // переставлення рядків місцями
triangular(a, i, S); // обчислення стовпців трикутноі матриці
}
det = 1;
for ( int i = 0; i < S; ++i ) // перемноження діагональних елементів
det = det * a[i][i];
if ( sign < 0 ) det = -det; // зміна знака визначника
return det;
}
Вот ваша практика. Все это более подробно можно взять в моей методичке + разные книги.
Еще примеры для вашей практики.
Задача 1. Заполнить одномерный массив элементами, отвечающими следующему соотношению:
a1=1; a2=1; ai=ai-2+ai-1 (i = 3, 4, ..., n).
cin >> N; /*Ввод количества элементов*/
A[0] = 1;
A[1] = 1;
for(int i=2; i<n; i++)
A[I] = A[I - 1] + A[I - 2];
Другой вариант присваивания значений элементам массива — заполнение значениями, полученными с помощью датчика случайных чисел.
Задача 2. Заполнить одномерный массив с помощью датчика случайных чисел таким образом, чтобы все его элементы были различны.
// программа заполнение массива #include <iostream.h> #include <time.h> #include <stdlib.h>
void main() { int A[99]; /*Массив из 100 элементов*/ cout << "Введите количество элементов массива"; int N; cin >> N; randomize(); A[0] = -32768 + random(65535); for(int i=1; i<N; i++) { int log=1; do { A[i] = -32768 + random(65535); int j = 1; while((log==1) && (j <= i - 1)) { if(A[i] != A[j]) log = 0; j++; } }while(log==1); } for(i=0;i<N;i++) cout << A[i] << " "; } |
Ввод значений элементов массива с клавиатуры используется обычно тогда, когда между элементами не наблюдается никакой зависимости. Например, последовательность чисел 1, 2, -5, 6, -111, 0 может быть введена в память следующим образом:
int A[99], n;
cout << "Введите количество элементов массива ";
cin >> n;
for(int i=0; i<n; i++)
{
cout << "Введите A[" << i << "]";
cin >> A[i];
}
Над элементами массива чаще всего выполняются такие действия, как
а) поиск значений;
б) сортировка элементов в порядке возрастания или убывания;
в) подсчет элементов в массиве, удовлетворяющих заданному условию.
Сумму элементов массива можно подсчитать по формуле S=S+A[I] первоначально задав S=0. Количество элементов массива можно подсчитать по формуле К=К+1, первоначально задав К=0. Произведение элементов массива можно подсчитать по формуле P = P * A[I], первоначально задав P = 1.
Задача 3. Дан линейный массив целых чисел. Подсчитать, сколько в нем различных чисел.
{Подсчет количества различных чисел в линейном массиве.
ИДЕЯ РЕШЕНИЯ: заводим вспомогательный массив, элементами которого являются псевдологические величины (0 - если элемент уже встречался ранее, 1 - иначе)}
// программа различные числа
#include <iostream.h>
void main()
{
int A[50], Lo[50], n;
cout << "Введите количество элементов массива: ";
cin >> n;
for(int i=0; i<n; i++)
{
cout << "A[" << i << "]=";
cin >> A[i];
Lo[i] = 1;
}
int kol = 0; /*переменная, в которой будет храниться количество различных чисел*/
for (i=0;i<n;i++)
{
if (Lo[i]==1)
{
kol++;
for(int k=i; k<n; k++)
{
Lo[k] = (A[k] != A[i]) && Lo[k];
}
}
}
cout << "Количество различных чисел: " << kol;
}
Тест: N = 10; элементы массива - 1, 2, 2, 2, -1, 1, 0, 34, 3, 3. Ответ: 6.
Задача 4. Дан линейный массив. Упорядочить его элементы в порядке возрастания.
{Сортировка массива выбором (в порядке возрастания). ИДЕЯ РЕШЕНИЯ: пусть часть массива (по K-й элемент включительно) отсортирована. Нужно найти в неотсортированной части массива минимальный элемент и поменять местами с (K+1)-м}
// программа сортировка выбором #include <iostream.h>
void main() { int A[30], n; cout << "Введите количество элементов: "; cin >> n; for(int i=0; i<< i A[? ?Введите cout { i++)>> A[i]; } for(i=0; i<n-1; i++) { int k = i; for(int j=i+1; j<n; j++) if(A[j]<=A[k]) k = j; int buf = A[i]; A[i] = A[k]; A[k] = buf; } for(i=0; i<n; i++) { cout << A[i] << " "; } } Тест: N = 10; элементы массива - 1, 2, 2, 2, -1, 1, 0, 34, 3, 3. Ответ: -1, -1, 0, 1, 2, 2, 2, 3, 3, 34. |
При решении практических задач часто приходится иметь дело с различными таблицами данных, математическим эквивалентом которых служат матрицы. Такой способ организации данных, при котором каждый элемент определяется номером строки и номером столбца, на пересечении которых он расположен, называется двумерным массивом.
Например, данные о планетах Солнечной системы представлены следующей таблицей:
Планета |
Расст. до Солнца |
Относ. объём |
Относ. масса |
Меркурий |
57.9 |
0.06 |
0.05 |
Венера |
108.2 |
0.92 |
0.81 |
Земля |
149.6 |
1.00 |
1.00 |
Марс |
227.9 |
0.15 |
0.11 |
Юпитер |
978.3 |
1345.00 |
318.40 |
Сатурн |
1429.3 |
767.00 |
95.20 |
Их можно занести в память компьютера, используя понятие двумерного массива. Положение элемента в массиве определяется двумя индексами. Они показывают номер строки и номер столбца. Индексы пишутся в отдельных квадратных скобках. Например: A[7][6], D[56][47].
Заполняется двумерный массив аналогично одномерному: с клавиатуры, с помощью оператора присваивания. Например, в результате выполнения программы:
void main()
{
int A[20][20];
for(int i=0; i<3; i++)
for(int j=0; j<2; j++)
A[i][j] = 456 + i;
}
элементы массива примут значения A[1][1] = 457; A[1][2] = 457; A[2][1] = 458; A[2][2] = 458; A[3][1] = 459; A[3][2] = 459.
При описании массива задается требуемый объем памяти под двумерный массив, указываются имя массива и в квадратных скобках максимальное значение индекса.
При выполнении инженерных и математических расчетов часто используются переменные более чем с двумя индексами. При решении задач на ЭВМ такие переменные представляются как компоненты соответственно трех-, четырехмерных массивов и т.д.
Однако описание массива в виде многомерной структуры делается лишь из соображений удобства программирования как результат стремления наиболее точно воспроизвести в программе объективно существующие связи между элементами данных решаемой задачи. Что же касается образа массива в памяти ЭВМ, то как одномерные, так и многомерные массивы хранятся в виде линейной последовательности своих компонент, и принципиальной разницы между одномерными и многомерными массивами в памяти ЭВМ нет. Однако порядок, в котором запоминаются элементы многомерных массивов, важно себе представлять. В большинстве алгоритмических языков реализуется общее правило, устанавливающее порядок хранения в памяти элементов массивов: элементы многомерных массивов хранятся в памяти в последовательности, соответствующей более частому изменению младших индексов.
Задача 5. Заполнить матрицу порядка n по следующему образцу:
1 |
2 |
3 |
... |
n-2 |
n-1 |
n |
2 |
1 |
2 |
... |
n-3 |
n-2 |
n-1 |
3 |
2 |
1 |
... |
n-4 |
n-3 |
n-2 |
... |
... |
... |
... |
... |
... |
... |
n-1 |
n-2 |
n-3 |
... |
2 |
1 |
2 |
n |
n-1 |
n-2 |
... |
3 |
2 |
1 |
// программа заполнение массива
#include <iostream.h>
void main()
{
int A[10][10], n;
cout << "Введите порядок матрицы: ";
cin >> n;
for( int i=0; i<n; i++ )
for( int j=i; j<n; j++ )
{
A[i][j] = j + i + 1;
A[j][i] = A[i][j];
}
for( i=0; i<n; i++ )
{
cout << "\n";
for( int j=0; j<n; j++ )
cout << A[i][j] << " ";
}
}
Задача 6. Дана целочисленная квадратная матрица. Найти в каждой строке наибольший элемент и поменять его местами с элементом главной диагонали.
// программа обмен в массиве #include <iostream.h>
void main() { int A[15][15], n; cout << "Введите количество элементов в массиве: "; cin >> n; for(int i=0; i<n; i++) for(int j=0; j<n; j++) { cout << "A[" << I << "][" << J << "] "; cin >> A[i][j]; } for(i=0; i<n; i++) { int max = A[i][1]; int ind = 1; for(int j=2; j<n; j++) if(A[i][j]>max) { max = A[i][j]; ind = j; } int vsp = A[i][i]; A[i][i] = A[i][ind]; A[i][ind] = vsp; } for(i=0; i<n; i++) { cout << "\n"; for(int j=0; j<n; j++) { cout << A[i][j] << " "; } } } |
Для допуска к зачету надо эти программы продемонстрировать в среде программирования
и
выполнить контрольное задание в аудитории на зачет.