Оголошення двовимірного масиву СІ має наступний синтаксис:
тип ім'я [розмір №1] [розмір №2];
Розміри двовимірного масиву в СІ вказуються в окремих парних квадратних дужках після імені та можуть бути будь-якими позитивними цілочисельними значеннями. Насправді прийнято значення першої розмірності називати рядками, а другий – стовпцями. Як і у випадку одномірного масиву, у стандарті С89 регламентується, що розміри двовимірного масивуповинні бути цілими константами.
Стандарт С99 допускає оголошення динамічних двовимірних масивів шляхом використання виразів при вказівці розмірів матриці, якщо цей вислів входять значення певних раніше змінних (вираз повинен мати позитивний цілочисельний результат). Наприклад:
int n,m;
printf("Введіть розміри матриці: ”);
scanf("%d%d", &n,&m);
double a[n][m];
При оголошенні двовимірного масиву в СІдопускається проводити ініціалізацію значень елементів матриці:
тип ім'я[розмір №1][розмір №2] = (
(значення № 11, ... значення № 1N),
   ...
(значення № M1, ... значення № MN)
  };
Приклади оголошень з ініціалізацією:
int a = (// Оголошено двовимірний масив
  {1,2,3,4}, // 1 2 3 4
  {5,6}}; // 5 6 0 0

Double b = (// Оголошено двовимірний масив
   {1.0, 2.0, 3.0, 4.0, 5.0}, // 1 2 3 4 5
   {6.0, 7.0} // 6 7 0 0 0
  }; // 0 0 0 0 0

Пропускати значення ініціалізації рядків не можна. Наприклад, наступний фрагмент коду програми неправильний:
int a = ((1,2,3,4,5),(6,7,8,9,0));Допускається не вказувати кількість рядків у двовимірному масиві (вказуються порожні квадратні дужки). У такому разі розмір масиву буде визначено за кількістю ініціалізуючих значень рядків. Кількість стовпців матриці завжди потрібно вказувати. Наприклад:
double b = ((1,2,3,4),(5,6,7,8));Оголошення константних матриць (значення їх елементів змінити не можна) починається з ключового слова const, за яким слідує оголошення матриці з ініціалізацією. Приклад:
const int matrix = (
   {1,2,3,4,5},
   {6,7,8,9}
  };
Звернення до елемента матриці здійснюється шляхом вказівки імені матриці, а після імені в окремих парних квадратних дужках індекси елемента (рядок та стовпець):
ім'я[рядок][стовпець]Індексація у мові СІ починається з нуля, тому для матриці розміром, наприклад, п'ять рядків та десять стовпців правильними будуть індекси рядків від нуля до чотирьох, а стовпців – від нуля до дев'яти включно.
Кожен окремий елемент матриці може розглядатися як проста змінна і, відповідно, виступати у виразах як RValue або LValue значень.
Введення та виведення матриць у мові СІ здійснюється поелементно. Так як матриця має подвійну розмірність, то введення та виведення здійснюється у вкладених циклах. Наприклад:
double a;
for(int i=0;ii++)
for(int j=0;jj++)
scanf("%lf",&a[i][j]);
  ...
for(int i=0;ii++)(
for(int j=0;jj++)
printf("%8.2lf\t",a[i][j]);
printf("\n");
  }
Присвоєння матриці також здійснюється поелементно. Наприклад, необхідно присвоїти цілочисленну матрицю x цілісної матриці y. Фрагмент програми:
int x, y;
  ...
for(int i=0;ii++)
for(int j=0;jj++)
y[i][j] = x[i][j];
  ...
У мові СІ допускається створення масивів розмірністю три і більше (тобто тривимірні, чотиривимірні і т.д.). Наприклад, оголошення тривимірного цілісного масиву з ініціалізацією матиме вигляд:
int a=( //це тривимірний масив
   {{1,2},{3,4}},
   {{5,6},{7,8}}
  };
Введення, виведення та інша обробка такого масиву здійснюється аналогічно обробці двовимірного масиву, тільки вже у трьох вкладених

До цього моменту ми розглядали лише одновимірні масиви, тобто до елемента масиву ми зверталися через один індекс. Однак, масиви можуть бути двовимірними і тривимірними і, навіть, n-мірними. Багатовимірні масиви — це масиви, які мають більше одного індексу. Замість одного рядка елементів багатовимірні масиви можна розглядати як сукупність елементів, які розподілені по двох або більше вимірах. Ось так, наприклад, можна візуалізувати двовимірний масив:

У цьому прикладі зображено двовимірний масив розміром 3*5, 3 - рядки та 5 стовпців. Оголошення двовимірного масиву майже нічим не відрізняється від оголошення одномірного, за винятком того, що при оголошенні двовимірного масиву потрібно вказувати розмір кожного вимірювання в квадратних дужках. Наприклад, давайте оголосимо двовимірний масив розміром 8*8, це розмір поля для стандартних шашок — 8 рядків та 8 стовпців:

Int checkers; // двовимірний масив

Тобто двомірний масив добре підходить для зберігання інформації на шашковому полі. Також двовимірний масив можна легко використовувати для зберігання інформації про будь-яку іншу гру - шахи, хрестики нуліки, сапер і т. д. Щоб отримати доступ до будь-якого елемента такого масиву, потрібно скористатися двома значеннями - індексами, перший індекс - це номер рядка, а другий - Номер стовпця. Все вище сказане стосується і n-мірних масивів. Хоча, вже 4-мірні масиви важко візуалізувати. Надавати значення елементам масиву дуже просто, ось приклад:

// присвоюємо першому елементу масиву значення – 5 myArray = 5;

Приклад надання значення елемента двовимірного масиву:

// присвоюємо першому елементу масиву значення – 5 myArray = 10;

У цьому прикладі ми надали значення 10 елементу двовимірного масиву myArray , який знаходиться в другому рядку і в 4-му стовпці. Візуально це виглядає так:

[__][__][__][__][__] [__][__][__][__] [__][__][__][__][__]

Як бачите, все просто, головне, пам'ятайте, що нумерація рядків і стовпців завжди починається з 0. Тобто, я ще раз хочу вам нагадати, що ви ніколи не повинні намагатися записати дані після останнього елемента масиву, наприклад, коли у вас є масив розміром - 10 елементів і ви намагаєтеся привласнити значення елемента з індексом. Пам'ять для масиву була виділена тільки для десяти елементів (індекси від 0 до 9), тому елемента з індексом 10 просто не існує. У такому разі запис в оперативній пам'яті може призвести до непередбачуваних наслідків — наприклад, ви можете зіпсувати роботу паралельно запущеної програми. Однак, як правило, операційна система не дозволить такої безрозсудної поведінки і призведе до краху програми, якщо та спробує отримати доступ до нерозподіленої пам'яті.

Давайте розглянемо практичний приклад використання масивів у програмах:

#include int main() ( int i, j; int myArray; // оголошуємо масив розміром 8*8 елементів for (i = 0; i< 8; i++) { for (j = 0; j < 8; j++) myArray[i][j] = i * j; // каждому элементу присваиваем значение произведения текущих индексов элемента массива } printf("Вот такой массив у нас получился:\n"); for (i = 0; i < 8; i++) { for (j = 0; j < 8; j++) { printf("[%d][%d]=%d ", i, j, myArray[i][j]); } printf("\n"); } getchar(); }

Відразу дивимося результат роботи програми:

Ось такий масив у нас вийшов: =0 =0 =0 =0 =0 =0 =0 =0 =0 =1 =2 =3 =4 =5 =6 =7 =0 =2 =4 =6 =8 = 10 = 12 = 14 = 0 = 3 = 6 = 9 = 12 = 15 = 18 = 21 = 0 = 4 = 8 = 12 = 16 = 20 = 24 = 28 = 0 = 5 = 10 = 15 = 20 = 25 = 30 = 35 = 0 = 6 = 12 = 18 = 24 = 30 = 36 = 42 = 0 = 7 = 14 = 21 = 28 = 35 = 42 = 49

У цьому прикладі ми спочатку заповнюємо двовимірний масив твором його індексів, рядки 8 - 11. А потім виводимо на екран його вміст, рядки 13 - 20.

Якщо ви хочете оголосити вказівник на масив, то ви не повинні використовувати операцію взяття адреси - & , ось приклад:

Char *ptrArray; char myString; ptrArray = myString; // покажчику присвоюємо адресу першого елемента масиву myString без використання &

Коли зі звичайними змінними, цього зробити не можна, приклад:

Int *ptrNumber; int number; ptrNumber = // обов'язково використовуємо оператор - &

На перший погляд, той факт, що масиви працюють як покажчики може заплутати вас, але це специфіка мови програмування, це потрібно просто запам'ятати.

PS: Після прочитання статті, рекомендую вам відволіктися від програмування. Хороший спосіб це зробити – цікава гра. Дістаньте смартфон та запустіть свою улюблену гру. А ось і корисне посилання для фанів андроїда - скачати ігри для андроїд. Ігор дуже багато і всі цікаві, а головне безкоштовні.

Анотація: Наводяться правильні та неправильні способи реалізації матриць та багатовимірних масивів мовою Сі. Робота з матрицями ілюструється з прикладу приведення матриці до ступінчастому виду методом Гаусса. Розглядаються методи роботи з файлами, які використовують функції вводу-виводу зі стандартної бібліотеки ANSI. Наводяться способи роботи із символами та текстовими рядками за допомогою функцій стандартної бібліотеки. Матеріал ілюструється прикладами, що включають програму "wc" підрахунку символів, слів та рядків у файлі та програму "Записна книжка", яка дозволяє знаходити телефон людини за його ім'ям, а також зберігати та модифікувати вміст книжки.

Подання матриць та багатовимірних масивів

Спеціального типу данихматриця або багатовимірний масивв Сі немає, однак, можна використовувати масив елементів типу масив . Наприклад, змінна a являє матрицю розміру 3x3 з речовими елементами:

Елементи матриці розташовуються в пам'яті послідовно по рядках: спочатку йдуть елементи рядка з індексом 0, потім рядки з індексом 1, наприкінці рядка з індексом 2 (у програмуванні відлік індексів завжди починається з нуля, а не одиниці!). При цьому вираз

де i - Ціла змінна, являє собою покажчик на початковий елемент i-го рядка і має тип double *.

Для звернення до елемента матриці треба записати його індекси у квадратних дужках, наприклад, вираз

являє собою елемент матриці a у рядку з індексом i і стовпчику з індексом j. Елемент матриці можна використовувати у будь-якому вираженні як звичайну змінну (наприклад, можна читати його значення чи присвоювати нове).

Така реалізація матриці зручна і максимально ефективна з точки зору доступу до елементів. Вона має лише один істотний недолік: так можна реалізувати тільки матрицю, розмір якої відомий заздалегідь. Мова Сі не дозволяє описувати масиви змінного розміру, розмір масиву повинен бути відомий до початку роботи програми ще на стадії компіляції.

Нехай потрібна матриця розмір якої визначається під час роботи програми. Тоді простір під неї треба захоплювати динамічної пам'яті за допомогою функції malloc мови Сі або оператора new мови C++. При цьому динамічної пам'яті захоплюється лінійний масив і повертається покажчик на нього. Розглянемо речову матрицю розміром m рядків на n стовпців. Захоплення пам'яті виконується за допомогою функції malloc мови Сі

double *a; . . . a = (double *) malloc (m * n * sizeof (double));

або за допомогою оператора new мови C++:

double *a; int m, n; . . . a = new double;

При цьому вважається, що елементи матриці будуть розташовуватися в масиві наступним чином: спочатку йдуть елементи рядка з індексом 0 потім елементи рядка з індексом 1 і т.д., останніми йдуть елементи рядка з індексом m - 1 . Кожен рядок складається з n елементів, отже, індекс елемента рядка i та стовпця j у лінійному масиві дорівнює

(дійсно, оскільки індекси починаються з нуля, то i дорівнює кількості рядків, які потрібно пропустити, i * n - сумарна кількість елементів у рядках, що пропускаються; число j дорівнює зміщенню всередині останнього рядка). Таким чином, елементу матриці у рядку i та стовпці j відповідає вираз

Цей спосіб представлення матриці зручний та ефективний. Його основна перевага полягає в тому, що елементи матриці зберігаються в безперервномувідрізку пам'яті. По-перше, це дозволяє компілятору, що оптимізує, перетворювати текст програми, домагаючись максимальної швидкодії; по-друге, при виконанні програми максимально використовується механізм кеш-пам'яті, що зводить до мінімуму звернення до пам'яті та значно прискорює роботу програми.

У деяких книгах Сі рекомендується реалізовувати матрицю як масив покажчиків на її рядки, при цьому пам'ять під кожен рядок захоплюється окремо в динамічній пам'яті:

double **a; // Адреса масиву покажчиків int m, n; // Розміри матриці: m рядків, n стовпців int i; . . . // Захоплюється пам'ять під масив покажчиків a = (double**) malloc(m*sizeof(double*)); for (i = 0; i< m; ++i) { // Захватывается память под строку с индексом i a[i] = (double *) malloc(n * sizeof(double)); }

Після цього до елемента a ij можна звертатися за допомогою виразу

Незважаючи на всю складність цього рішення, жодного виграшу немає, навпаки, програма програє у швидкості! Причина полягає в тому, що матриця не зберігається у безперервній ділянці пам'яті, це заважає як оптимізації програми, так і ефективному використанню кеш-пам'яті. Отже, краще не застосовувати такий метод представлення матриці.

Багатовимірні масиви реалізуються аналогічно матрицям. Наприклад, речовий тривимірний масив розміру 4 x 4 x 2 описується як

звернення до його елемента з індексами x, y, z здійснюється за допомогою виразу

Багатомірні масиви змінного розміру з числом індексів більшим за два зустрічаються в програмах досить рідко, але жодних проблем з їх реалізацією немає: вони реалізуються аналогічно матрицям. Наприклад, нехай треба реалізувати тривимірний речовий масив розміру m x n x k . Захоплюється лінійний масив дійсних чисел розміром m * n * k :

double *a; . . . a = (double *) malloc (m * n * k * sizeof (double));

Доступ до елемента з індексами x, y, z здійснюється за допомогою виразу

a[(x * n + y) * k + z]

Приклад: приведення матриці до ступінчастого виду методом Гаусса

Як приклад роботи з матрицями розглянемо алгоритм Гауса приведення матриці до ступінчастого вигляду. Метод Гаусса - один з основних результатів лінійної алгебри та аналітичної геометрії, до нього зводяться безліч інших теорем і методів лінійної алгебри (теорія та обчислення визначників, рішення систем лінійних рівнянь, обчислення рангу матриці та зворотної матриці, теорія базисів кінцевих векторів. .).

Нагадаємо, що матриця A з елементами a ij називається ступінчастою, якщо вона має наступні дві властивості:

  1. якщо в матриці є нульовий рядок, то всі рядки нижче за неї також нульові;
  2. нехай a ij не дорівнює 0 - перший ненульовий елемент у рядку з індексом i, тобто. елементи a il = 0 при l< j . Тогда все элементы в j -м столбце ниже элемента a ij равны нулю, и все элементы левее и ниже a ij также равны нулю: a kl = 0 при k >i та l =< j .

Ступінчаста матриця виглядає приблизно так:

тут темними квадратиками відзначені перші ненульові елементи рядків матриці. Білим кольором зображуються нульові елементи, сірим кольором – довільні елементи.

Алгоритм Гауса використовує елементарні перетворення матриці двох типів.

  • Перетворення першого роду:Два рядки матриці змінюються місцями, і при цьому знаки всіх елементів одного з рядків змінюються на протилежні.
  • Перетворення другого роду:до одного рядка матриці додається інший рядок, помножений на довільне число.

Елементарні перетворення зберігають визначник та ранг матриці, а також безліч рішень лінійної системи. Алгоритм Гауса наводить довільну матрицю елементарними перетвореннями до ступінчастого вигляду. Для ступінчастої квадратної матриці визначник дорівнює добутку діагональних елементів, а ранг - числу ненульових рядків (рангом за визначенням називається розмірність лінійної оболонки рядківматриці).

Метод Гауса в математичному варіанті полягає в наступному:

  1. шукаємо спочатку ненульовийелемент у першому стовпці. Якщо всі елементи першого стовпця нульові, переходимо до другого стовпця, і так далі. Якщо знайшли ненульовий елемент в k-му рядку, то за допомогою елементарного перетворення першого роду міняємо місцями перший і k-ий рядок, домагаючись того, щоб перший елемент першого рядка був відмінний від нуля;
  2. використовуючи елементарні перетворення другого роду, обнулюємо всі елементи першого стовпця, починаючи з другого елемента. Для цього від рядка з номером k віднімаємо перший рядок, помножений на коефіцієнт a k1 /a 11 .
  3. переходимо до другого стовпця (або j-му, якщо всі елементи першого стовпця були нульовими), і надалі розглядаємо тільки частину матриці, починаючи з другого рядка і нижче. Знову повторюємо пункти 1) та 2) доти, доки не наведемо матрицю до ступінчастого вигляду.

Програмістський варіант методу Гауса має три відмінності від математичного:

r = -a kj / a ij. a k = a k + r * a i

Така схема працює нормально лише тоді, коли коефіцієнт r по абсолютній величині не перевищує одиниці. В іншому випадку, помилки округлення множаться на великий коефіцієнт і таким чином експоненційно зростають. Математики називають це явище нестійкістюобчислювальної схеми. Якщо обчислювальна схема нестійка, отримані з її допомогою результати немає жодного стосунку до вихідної задачі. У разі схема стійка, коли коефіцієнт r = -a kj /a ij вбирається у модулю одиниці. Для цього має виконуватися нерівність

|a ij | >= |a kj | при k > i

Звідси випливає, що при пошуку роздільного елемента в j-му стовпці необхідно знайти не перший ненульовий елемент, що попався, а максимальний за абсолютною величиною. Якщо він по модулю вбирається у , то вважаємо, що це елементи стовпця нульові; інакше міняємо місцями рядки, ставлячи його на вершину стовпця, а потім обнуляємо стовпець елементарними перетвореннями другого роду.

Нижче дано повний текст програми на Сі, що приводить речову матрицю до ступінчастого вигляду. Функція, що реалізує метод Гауса, одночасно підраховує і ранг матриці. Програма вводить розміри матриці та її елементи з клавіатури та викликає функцію приведення до ступінчастого вигляду. Потім програма друкує ступінчастий вид матриці та її ранг. У разі квадратної матриці також обчислюється та друкується визначник матриці, рівний добутку діагональних елементів ступінчастої матриці

При реалізації методу Гауса використовується схема побудови циклу за допомогою інваріанту, див. 1.5.2. У циклі змінюються дві змінні - індекс рядка i, 0 =< i < m - 1 , и индекс столбца j , 0 =< j < n - 1 . Инвариантом цикла является утверждение о том, что часть матрицы (математики говорят мінор) у стовпцях 0,1,...j - 1 приведена до ступінчастого вигляду і що перший ненульовий елемент у рядку i - 1 стоїть у стовпці з індексом меншим j. У тілі циклу розглядається тільки мінор матриці в рядках i,...,m-1 і стовпцях j,...,n-1. Спочатку шукається максимальний за модулем елемент у j-му стовпці. Якщо він по абсолютній величині не перевищує, то j збільшується на одиницю (вважається, що стовпець нульовий). Інакше перестановкою рядків роздільна здатність ставиться на вершину j -го стовпця мінора, і потім стовпець обнулюється елементарними перетвореннями другого роду. Після цього обидва індекси i та j збільшуються на одиницю. Алгоритм завершується, коли або i = m, або j = n. Після закінчення алгоритму значення змінної i дорівнює числу ненульових рядків ступінчастої матриці, тобто. рангу вихідної матриці

Для обчислення абсолютної величини речовинного числа x типу double ми користуємося стандартною математичною функцією fabs (x), описаної в стандартному заголовному файлі "math.h."

#include // Опис функцій введення-виведення #include // Опис математичних функцій #include // Опис функцій malloc та free // Прототип функції приведення матриці // до ступінчастого вигляду. // Функція повертає ранг матриці int gaussMethod(int m, // Число рядків матриці int n, // Число стовпців матриці double *a, // Адреса масиву елементів матриці double eps // Точність обчислень); int main() ( int m, n, i, j, rank; double *a; double eps, det; printf("Введіть розміри матриці m, n: "); scanf("%d%d", &m, &n );// Захоплюємо пам'ять під елементи матриці a = (double *) malloc(m * n * sizeof(double));printf("Введіть елементи матриці:\n");for (i = 0; i< m; ++i) { for (j = 0; j < n; ++j) { // Вводим элемент с индексами i, j scanf("%lf", &(a)); } } printf("Введите точность вычислений eps: "); scanf("%lf", &eps); // Вызываем метод Гаусса rank = gaussMethod(m, n, a, eps); // Печатаем ступенчатую матрицу printf("Ступенчатый вид матрицы:\n"); for (i = 0; i < m; ++i) { // Печатаем i-ю строку матрицы for (j = 0; j < n; ++j) { printf(// Формат %10.3lf означает 10 "%10.3lf ", // позиций на печать числа, a // 3 знака после точки); } printf("\n"); // Перевести строку } // Печатаем ранг матрицы printf("Ранг матрицы = %d\n", rank); if (m == n) { // Для квадратной матрицы вычисляем и печатаем // ее определитель det = 1.0; for (i = 0; i < m; ++i) { det *= a; } printf("Определитель матрицы = %.3lf\n", det); } free(a); // Освобождаем память return 0; // Успешное завершение программы } // Приведение вещественной матрицы // к ступенчатому виду методом Гаусса с выбором // максимального разрешающего элемента в столбце. // Функция возвращает ранг матрицы int gaussMethod(int m, // Число строк матрицы int n, // Число столбцов матрицы double *a, // Адрес массива элементов матрицы double eps // Точность вычислений) { int i, j, k, l; double r; i = 0; j = 0; while (i < m && j < n) { // Инвариант: минор матрицы в столбцах 0..j-1 // уже приведен к ступенчатому виду, и строка // с индексом i-1 содержит ненулевой эл-т // в столбце с номером, меньшим чем j // Ищем максимальный элемент в j-м столбце, // начиная с i-й строки r = 0.0; for (k = i; k < m; ++k) { if (fabs(a) >r) (l = k; // Запам'ятаємо номер рядка r = fabs(a); // і макс. ел-т)) if (r<= eps) { // Все элементы j-го столбца по абсолютной // величине не превосходят eps. // Обнулим столбец, начиная с i-й строки for (k = i; k < m; ++k) { a = 0.0; } ++j; // Увеличим индекс столбца continue; // Переходим к следующей итерации } if (l != i) { // Меняем местами i-ю и l-ю строки for (k = j; k < n; ++k) { r = a; a = a; a = (-r); // Меняем знак строки } } // Утверждение: fabs(a) >eps // Обнуляємо j-й стовпець, починаючи з рядка i+1, // застосовуючи елем. перетворення другого роду for(k = i+1; k< m; ++k) { r = (-a / a); // К k-й строке прибавляем i-ю, умноженную на r a = 0.0; for (l = j+1; l < n; ++l) { a += r * a; } } ++i; ++j; // Переходим к следующему минору } return i; // Возвращаем число ненулевых строк }

Формулювання завдання:

Всім добрий день) Мені хотілося б по можливості отримати Вашу допомогу з даним завданням, провів за ним достатньо часу, хочу розібратися, де маю помилки. Власне саме завдання: "Напишіть програму, яка створює матрицю 5*5 і заповнює її повністю +. Користувачеві має бути запропоноване меню: Матриця виглядає так: + + + + + + + + + + + + + + + + + + + + + + + + + Опції: (1) Заповнити всі поля знаком 0 (2) Заповнити обидві діагоналі 0 (3) Заповнити задане поле 0 (стовпець, рядок) (4) Оновити: Заповнити всі поля знову + (5) Кінець програми " Приклад виведення для 2 опції: Матриця виглядає зараз так: 0 + + + 0 + 0 + 0 + + + 0 + + + 0 + 0 + 0 + + + 0 Які у мене проблеми: 1. Чомусь матриця у разі виведення через arr [i][j] заповнюється не +, а лівими символами 2. У випадку з вибором 2 опції, начебто діагоналі задані правильно, але з'являються "зайві" нулі і виводиться не один раз (чому не один раз я знаю, але не зовсім розумію, як це коректно виправити) 3. Як правильно задати саме потрібну адресу з клавіатури та "прикрутити" її до матриці, щоб саме це поле змінювалося на нуль. 4. Як покращити реалізацію циклу do while, щоб програма продовжувала виконуватися, поки не буде натиснута кнопка 5. 5. Як реалізувати висновок "красивше"? Ось мій код: #include int main() ( char arr; int i, j; int choice; int col, row; for (i = 0; i<5; i++) // цикл по строкам { for (j = 0; j<5; j++) // цикл по столбцам { arr[i][j]= 43; } } printf("Матрица выглядит так:"); printf(", arr [i][j]); printf("\Опции: \n (1) Заповнити всі поля знаком 0 \n (2) Заповнити обидві діагоналі 0 \n (3) Заповнити задане поле 0 (стовпець, рядок)\n (4) Оновити: Заповнити всі поля знову + \n (5) Кінець програми \n"); scanf("%i",&choice); do (switch (choice) (case 1: (for (i = 1; i)<6; i++) // цикл по строкам { for (j = 1; j<6; j++) // цикл по столбцам { arr[i][j]= "O"; } } } printf("Опция: %i \n Матриця виглядає тепер так:", choice); printf(" %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c\n %c %c %c %c %c\n", arr [i] [j]); ) Break; case 2:( if (i==j || i==4-j) arr[i][j]= "O"; printf("Опція: %i \n Матриця виглядає тепер так", choice); printf(" %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c\n %c %c %c %c %c\n", arr [i] [j]); printf("\n"); ) break; case 3: ( for (i = 0; i<6; i++) // цикл по строкам { for (j = 0; j<6; j++) // цикл по столбцам { { printf(" Введите столбец и стрку = "); scanf("%i", &arr); arr= "0"; } // Вывод элементов массива for (i = 0; i<5; i++) { // цикл по строкам for (j = 0; j<5; j++) { // цикл по столбцам printf("Опция: %i Матриця виглядає тепер так: ", choice); printf(" %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c\n %c %c %c %c %c\n", arr [i] [j]); printf("\n"); ) ) // переклад на новий рядок ) ) ) break; case 4:( for (i = 0; i<6; i++) // цикл по строкам { for (j = 0; j<6; j++) // цикл по столбцам { arr[i][j]= "+"; } } printf("Опция: %i \n Матриця виглядає тепер так ", choice); printf(" %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c\n %c %c %c %c %c\n", arr [i] [j]); ) break; ) while (choice! = 5); break; return 0; )

Код завдання: «Заповнення матриці символами»

Textual #include #include int main() ( char arr; int i, j; int choice; int col, row; printf("Матриця виглядає так:\n\n"); for (i = 0; i< 5; i++) { for (j = 0; j < 5; j++) { printf("+ ", arr[i][j]); } printf("\n"); } printf("\nОпции: \n (1) Заполнить все поля знаком 0 \n (2) Заполнить обе диагонали 0 \n " "(3) Заполнить заданное поле 0 (столбец, строка)\n (4) Обновить: Заполнить все поля снова знаком" " + \n (5) Конец программы \n\n"); do{ printf("Сделайте выбор: \n"); scanf("%i", &choice); }while(choice < 1 || choice >5); switch (choice) ( case 1: ( printf("Опція: %i \n", choice); printf("Матриця виглядає тепер так:\n\n"); for (i = 0; i< 5; i++) // цикл по строкам { for (j = 0; j < 5; j++) // цикл по столбцам { printf("0 ", arr[i][j]); } printf("\n"); } } break; case 2: { printf("Опция: %i \n", choice); printf("Матрица выглядит теперь так:\n\n"); for(i = 0; i < 5; i++) { for(j = 0; j < 5; j++) { if(i == j || i == 4 - j) { arr[i][j] = 0; printf("%i ", arr[i][j]); } else { printf("+ "); } } printf("\n"); } } break; case 3: { printf("Введите столбец и стрку: \n"); scanf(" %i %i", &col, &row); printf("Опция: %i \n", choice); printf("Матрица выглядит теперь так:\n\n"); // Вывод элементов массива for (i = 0; i < 5; i++) { // цикл по строкам for (j = 0; j < 5; j++) { // цикл по столбцам if(i == col - 1 || j == row - 1) { arr[i][j] = 0; printf("%i ", arr[i][j]); } else { printf("+ ");} } printf("\n"); // перевод на новую строку } } break; case 4: { printf("Опция: %i \n", choice); printf("Матрица выглядит так:\n\n"); for (i = 0; i < 5; i++) { for (j = 0; j < 5; j++) { printf("+ ", arr[i][j]); } printf("\n"); } } break; case 5: { exit(0); } } return 0; }

При вирішенні завдань з великою кількістю даних однакового типу використання змінних з різними іменами, які не впорядковані за адресами пам'яті, ускладнює програмування. У таких випадках у мові Сі використовують об'єкти, які називаються масивами.

- Це безперервна ділянка пам'яті, що містить послідовність об'єктів однакового типу, що позначається одним ім'ям.

Масив характеризується такими основними поняттями:

Елемент масиву (значення елемента масиву)– значення, що зберігається у певній комірці пам'яті, розташованої в межах масиву, а також адресу цієї комірки пам'яті.
Кожен елемент масиву характеризується трьома величинами:

  • адресою елемента - адресою початкової комірки пам'яті, в якій розташований цей елемент;
  • індексом елемента (порядковим номером елемента у масиві);
  • значенням елемента.

Адреса масиву – адреса початкового елемента масиву.

Ім'я масиву – ідентифікатор, який використовується для звернення до елементів масиву.

Розмір масиву – кількість елементів масиву

Розмір елемента – кількість байт, які займає один елемент масиву.

Графічно розташування масиву в пам'яті комп'ютера можна у вигляді безперервної стрічки адрес.

Представлений малюнку масив містить q елементів з індексами від 0 до q-1 . Кожен елемент займає пам'яті комп'ютера k байт, причому розташування елементів у пам'яті послідовне.

Адреси i-го елемента масиву має значення

Адреса масиву є адресою початкового (нульового) елемента масиву. Для звернення елементів масиву використовується порядковий номер (індекс) елемента, початкове значення якого дорівнює 0 . Так, якщо масив містить елементів q, то індекси елементів масиву змінюються в межах від 0 до q-1 .

Довжина масиву – кількість байт, що відводиться пам'яті для зберігання всіх елементів масиву.

Довжина Масиву = Розмір Елементу * Кількість Елементів

Для визначення розміру елемента масиву може використовуватись функція

int sizeof (тип);

Наприклад,

sizeof (char) = 1;
sizeof(int) = 4;
sizeof (float) = 4;
sizeof (double) = 8;

Оголошення та ініціалізація масивів

Для оголошення масиву в мові Сі використовується наступний синтаксис:

тип ім'я [розмірність] = (ініціалізація);

Ініціалізація є набір початкових значень елементів масиву, зазначених у фігурних дужках, і розділених комами.

int a = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9); // масив a з 10 цілих чисел

Якщо кількість ініціалізуючих значень, зазначених у фігурних дужках, менша, ніж кількість елементів масиву, вказана в квадратних дужках, то всі елементи, що залишилися в масиві (для яких не вистачило ініціалізуючих значень) дорівнюватимуть нулю. Цю властивість зручно використовувати для завдання нульових значень усім елементам масиву.

int b = (0); // масив b з 10 елементів, ініціалізованих 0


Якщо масив проініціалізований при оголошенні, то константні початкові значення його елементів вказуються через ком у фігурних дужках. У цьому випадку кількість елементів у квадратних дужках може бути опущена.

int a = (1, 2, 3, 4, 5, 6, 7, 8, 9);

При зверненні до елементів масиву індекс необхідного елемента вказується у квадратних дужках.

Приклад на Сі

1
2
3
4
5
6
7
8

#include
int main()
{
int a = (5, 4, 3, 2, 1); // масив a містить 5 елементів
printf("%d%d%d%d\n", a, a, a, a, a);
getchar();
return 0;
}

Результат виконання програми:

Однак часто потрібно задавати значення елементів масиву у процесі виконання програми. У цьому використовується оголошення масиву без ініціалізації. У такому разі вказівка ​​кількості елементів у квадратних дужках є обов'язковою.

int a;

Для завдання початкових значень елементів масиву часто-густо використовується параметричний цикл:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18


#include
int main()
{
int a;
int i;
// Введення елементів масиву
for (i = 0; i<5; i++)
{
printf("a[%d] = ", i);
scanf("%d", &a[i]);
}
// Виведення елементів масиву
for (i = 0; i<5; i++)
printf("%d", a[i]); // Пробіл у форматі друку обов'язковий
getchar(); getchar();
return 0;
}

Результат виконання програми

Багатовимірні масиви

У мові Сі можуть бути оголошені багатовимірні масиви. Відмінність багатовимірного масиву від одномірного у тому, що у одномірному масиві становище елемента визначається одним індексом, а багатомірному - декількома. Прикладом багатовимірного масиву є матриця.

Загальна форма оголошення багатовимірного масиву

тип ім'я[розмірність1][розмірність2]...[розмірністьm];

Елементи багатовимірного масиву розташовуються в послідовних осередках оперативної пам'яті зростання адрес. У пам'яті комп'ютера елементи багатовимірного масиву розташовуються поспіль, наприклад масив, що має 2 рядки і 3 стовпці,

int a;


буде розташований у пам'яті наступним чином

Загальна кількість елементів у наведеному двовимірному масиві визначиться як

Кількість Рядок * Кількість Стовпців = 2 * 3 = 6.

Кількість байт пам'яті, необхідних розміщення масиву, визначиться як

Кількість елементів * Розмір елемента = 6 * 4 = 24 байти.

Ініціалізація багатовимірних масивів

Значення елементів багатовимірного масиву, як і в одновимірному випадку, можуть бути задані константними значеннями при оголошенні, укладеними у фігурні дужки (). Однак у цьому випадку зазначення кількості елементів у рядках та стовпцях має бути обов'язково вказано у квадратних дужках.

Приклад на Сі

1
2
3
4
5
6
7
8
9

#include
int main()
{
int a = (1, 2, 3, 4, 5, 6);
printf("%d%d%d\n", a, a, a);
getchar();
return 0;
}



Однак частіше потрібно вводити значення елементів багатовимірного масиву у процесі виконання програми. З цією метою зручно використовувати вкладений параметричний цикл.

Приклад на Сі

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

#define _CRT_SECURE_NO_WARNINGS
#include
int main()
{
int a; // масив з 2 рядків та 3 стовпців
int i, j;
// Введення елементів масиву
for (i = 0; i<2; i++) // цикл по рядках
{
for (j = 0; j<3; j++) // цикл по стовпцях
{
printf("a[%d][%d] = ", i, j);
scanf("%d", &a[i][j]);
}
}
// Виведення елементів масиву
for (i = 0; i<2; i++) // цикл по рядках
{
for (j = 0; j<3; j++) // цикл по стовпцях
{
printf("%d", a[i][j]);
}
printf("\n"); // Переведення на новий рядок
}
getchar(); getchar();
return 0;
}



Передача масиву у функцію

Обробку масивів зручно організовувати за допомогою спеціальних функцій. Для обробки масиву як аргументи функції необхідно передати

  • адреса масиву,
  • розмір масиву.

Виняток становлять функції обробки рядків, які достатньо передати лише адресу.

При передачі змінні як аргументи функції дані передаються як копії. Це означає, що якщо всередині функції відбудеться зміна значення параметра, це ніяк не вплине на його значення всередині функції, що викликає.

Якщо в функцію передається адреса змінної (або адреса масиву), то всі операції, що виконуються в функції з даними, що знаходяться в межах видимості зазначеної адреси, проводяться над оригіналом даних, тому вихідний масив (або значення змінної) може бути змінено функцією, що викликається.

Приклад на Сі Дан масив із 10 елементів. Поміняти місцями максимальний і вихідний елементи масиву. Для пошуку максимального елемента та обміну використовувати функцію.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

#define _CRT_SECURE_NO_WARNINGS
#include
// Функція обміну
void change(int * x, int n)
{
// x - покажчик на масив (адреса масиву)
// n - розмір масиву
int i;
int max, index;
max = x;
index = 0;
// Пошук максимального елемента
for (i = 1; i {
if (x[i]>max)
{
max = x [i];
index = i;
}
}
// Обмін
x = x;
x = max;
}
// Головна функція
int main()
{
int a;
int i;
for (i = 0; i<10; i++)
{
printf("a[%d] = ", i);
scanf("%d", &a[i]);
}
change(a, 10); // виклик функції обміну
// Виведення елементів масиву
for (i = 0; i<10; i++)
printf("%d", a[i]);
getchar();
getchar();
return
p = p * x [i];
}
return p;
}
// Головна функція
int main()
{
int a; // оголошено масив a з 5 елементів
int i;
int pr;
// Введення елементів масиву
for (i = 0; i<5; i++)
{
printf("a[%d] = ", i);
scanf("%d", &a[i]); // &a[i] - адреса i-го елемента масиву
}
pr = func(a, 5); // Обчислення твору
printf("\n pr = %d", pr); // Висновок твору парних елементів
getchar(); getchar();
return 0;
}