Реферат: Массивы
#include <stdio.h>
#incl ude <string . h > m а і n () { char s(80], printf( "Введіть рядок:");
gets(s);
printf( "Рядок\п%з\п має довжину %d символів \n", s, strlen(s)); }
ДВОВИМІРНІ МАСИВИ
Як ми вже зазначали, мова С допускає багатовимірні масиви, найпростішою формою яких е двовимірний масив (two-dimentional array). Можна сказати, що двовимірний масив - це масив одновимірних масивів .
Двовимірний масив int a[3][4] можна подати у вигляді таблички:
Другий індекс |
Перший індекс
а[0] [0] | а[0][1] | а[0][2] | а[0] [3] |
а[1] [0] | а[1][1] | а[1][2] | а[1][3] |
а[2][0] | а[2] [1] | а[2][2] | а[2] [3] |
Перший індекс - номер рядка, другий індекс - номер стовпця. Кількість байт пам'яті, яке необхідне для зберігання масиву, обчислюється по формулі
Кільк.байтів = <розмір типу даних>*<кільк.рядків>*<кільк.ствпців>.
У пам'яті комп'ютера масив розташовується безперервно по рядках, тобто а[0][0], а[0][1], а[0][2], а[0][3], а[1][0], а[1][1], а[1] [2], а[2] [1],. ... а[2] [3] .
Потрібно пам'ятати, що пам'ять для всіх масивів, які визначені як глобальні, відводиться в процесі компіляції і зберігається весь час, поки працює програма.
Часто двовимірні масиви використовуються для роботи з таблицями, що містять текстову інформацію. Також дуже часто використовуються масиви рядків.
ІНІЦІАЛІЗАЦІЯ МАСИВІВ
Дуже важливо уміти ініціалізувати масиви, тобто привласнювати елементам масиву деякі початкові значення. У мові С для цього є спеціальні можливості. Самий простий спосіб ініціалізації наступний: в процесі оголошення масиву можна указати в фігурних дужках список ініціалізаторів:
float а[6]={1.1, 2.2, 3.3, 4.0, 5, 6};
В іншому випадку така форма запису еквівалентна набору операторів:
а[0]=1.1; а[1]=2.2; ... а [5] =6.
Багатовимірні масиви, в тому числі і двовимірні масиви, можна ініціалізувати, розглядаючи іх як масив масивів.
Ініціалізації int а[3][5]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
і int а[3][5]={{1,2,3,4,5}, {6,7,8,9,10}, {11,12,13,14,15}};
еквівалентні.
Кількість ініціалізаторів не зобов'язана співпадати з кількістю
елементів масиву. Якщо ініціалізаторів менше, то значення решти
елементів масиву не визначені.
У той же час ініціалізації
int а[3][5]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
і
int а[3][5]={{1, 2, 3}, {4, 5, 6, 7, 8}, {9, 10, 11}};
різні.
//change strings: 1-6, 2-5, 3-4
#i nclude<std io. h >
void mai n()
{ int temp, i, j, a[6][4]={1,2,3,4,
5,6,7,8,
9,10,11,12,
1 3,14,1 5,16,
17,18,19,20,
21 ,22,23,24};
for (i=0;i<3;i++) for (j=0;j<4;j++)
{ temp=a[i][j]; a[i][j]=a[5-i][j]; a[5-i][j]=temp; } for (i=0; i<6; i++)
{
for (j=0;j<4;j++)
printf ("%4d", a[i][j]);
printf("\n");
}}
Символьні масиви можуть ініціалізувати як звичайний масив:
char str[15]={'В', ' о ' , ' г ' , ' 1 ' , ' а ' , ' n ' , ' d' , ' ',' С',^',^'};
а можуть - як рядок символів:
"char str[15]= Borland C++";
Відмінність цих двох способів полягає в тому, що у другому випадку буде доданий ще і нульовий байт. До того ж другий спосіб коротше. Допускається також оголошення і ініціалізація масиву без явної вказівки розміру масиву. Наприклад, для виділення місця під символьний масив звичайним способом
char str[80]= "Це оголошення і ініціалізація масиву символів";
ми повинні вважати кількість символів в рядку або указати явно більший розмір масиву.
При ініціалізації масиву без вказівки його розміру
char str[ ]= "Це оголошення і ініціалізація масиву символів";
компілятор сам визначить необхідну кількість елементів масиву, включаючи нульовий байт. Можна оголошувати таким же способом масиви будь-якого типу:
int mass []={!, 2, 3, 1, 2, 3, 4};
Від LG: При ініціалізації можна не вказувати розмірність масиву, вона обчислюється автоматично (проте для двовимірних масивів кількість стовпців треба указати), а при оголошенні - обов'язково. При оголошенні масивів з невідомою кількістю елементів можна не вказувати розмір тільки в самих лівих квадратних дужках.
ПОКАЖЧИКИ І АДРЕСИ (Керніган, Рітчі і Б.І.Березін,С.)(Б.Березін)
Пам'ять машини являє собою масив послідовно розташованих і пронумерованих комірок, з якими можна працювати окремо і зв'язаними ділянками. Покажчик - це група комірок в пам'яті комп'ютера, в яких може зберігатися адреса.
Унарний оператор & видає адресу об'єкта, так що інструкція
р=&а;
привласнює адресу комірки а змінній р (тепер р вказує на а або посилається) .
Оператор & застосовується тільки до об'єктів, розташованих в пам'яті: до змінних і елементам масивів. Його операндом не може бути ні вираз, ні константа, ні регістрова змінна.
Унарний оператор * є оператор розкриття посилання. Застосований до покажчика, він видає об'єкт, на який даний покажчик посилається.
ОГОЛОШЕННЯ ПОКАЖЧИКІВ
Якщо змінна буде покажчиком, то вона повинна бути оголошена таким чином:
тип *<ім'я змінної>;
У цьому оголошенні тип - деякий тип мови С, визначальний тип об'єкта, на який вказує покажчик (адреса якого містить); * - означає, що наступна за нею змінна є покажчиком.
ОПЕРАЦІЇ НАД ПОКАЖЧИКАМИ
З покажчиками пов'язані дві спеціальні операції.: & і *. Обидві ці операції є унарними, т. е. мають один операнд, перед якими вони ставляться. Операція & відповідає операції "взяти адресу". Операція * відповідає словам "значення, розташоване за вказаною адресою" .
Особливість мови С полягає в тому, що знак * відповідає двом операціям, що не мають один до одного ніякого відношення: арифметичній операції множення і операції взяти значення. У той же час сплутати їх в контексті програми не можливо, оскільки одна з операцій унарна (містить один операнд), інша - множення - бінарна (містить два операнди). Унарні операції & і * мають найвищий пріоритет нарівні з унарним мінусом.
В оголошенні змінної, що є покажчиком, дуже важливий базовий тип. Якщо покажчик має базовий тип int, то змінна займає 2 байти, char - 1 байт тощо. Приклад.
int а=3, Ь=5;
int *р;
р = &а; /* тепер р вказує на а*/ Ь = *р; /* b тепер дорівнює З*/ *р= 0; /*а тепер дорівнює О*/
&*а => а - розадресація.
Унарні оператори * і & мають більш високий пріоритет, ніж арифметичні оператори:
b = *р + 1 (взяти те, на що вказує р, додати до нього 1, а результат привласнити змінній b.
До покажчиків можна застосувати операцію привласнення. Покажчики одного і того ж типу можуть використовуватися в операції привласнення, як і будь-які інші змінні. Розглянемо приклад. #include <stdio. h> void mai n() { int x= 1 0;
int *p, *g;
p=&x;
g=p;
printf("%p", р); /* друк вмісту р */
printf("%p",g); /* друк вмісту g */
р г і n t f (" % d % d ", x, * g); / * друк величини хі величини за адресою g*/
} Результат: FFF4 FFF4 10 10
У цьому прикладі приведена ще одна специфікація формату функції printf() - %р. Цей формат використовується для друку адреси пам'яті в шістнадцятковій формі.
Не можна створити змінну типу void, але можна створити покажчик на тип void. Покажчику на void можна привласнити покажчик будь-якого іншого типу. Однак при зворотному привласненні необхідно використати явне перетворення покажчика на void/void *pv;
float f, *pf;
pf=&f;
pv=pf;
pp=(fioat*) pv;
У мові С допустимо привласнити покажчику будь-яку адресу пам'яті. Однак, якщо оголошений покажчик на ціле
int *р;
а за адресою, яка привласнена даному покажчику, знаходиться змінна х типу float, то при компіляції програми буде видане повідомлення про помилку в рядку
р=&х;
Цю помилку можна виправити, перетворювавши покажчик на int до типу покажчика на float явним перетворенням типу:
p=(int*)&x;
Але при цьому втрачається інформація про те, на який тип вказував початковий покажчик.
Як і над іншими типами змінних, над покажчиками можна виробляти арифметичні операції: складання і віднімання (операції ++ і є окремими випадками операцій складання і віднімання). Арифметичні
дії над покажчиками мають свої особливості. Виконаємо найпростішу програму
#include <stdio. h> void main() { і n t x= 1 0;