Част 15
Масиви (Arrays)
Масивите са най-лесният начин да комбинираме данни от един и същ тип в един обект. Повечето програмни езици поддържат масивите и C++ не прави изключение. Отделните групирани данни се наричат елементи на масива и те са от един и същ тип: поради това те имат една и съща големина в паметта. Това позволява лесен достъп до даден елемент на масива посредством целочислена променлива, която показва неговото място. Тази променлива се нарича индекс или индексен номер на елемента.
1. Дефиниране на масив. За да дефинирате масив трябва да кажете на компютъра името на масива, типът неговите елементи и техният брой. По този начин програмата ще знае колко памет да запази за масива. Например ако искаме да дефинираме масив, който съхранява възрастта на група от 30 служители ще напишем
int age[30];
където int определя типа на елементите, age е името на масива, а 30 е броят елементи в масива. Този брой е заграден в средни скоби [ и ], а не обикновени (кръгли) скоби или големи скоби. Нека да си представим, че горната дефиниция е в тялото на някаква функция. Тогава при извикване на тази функция, програмата запазва в стека памет от 30 x 2 = 60 байта на 16 битовите компютри и 30 x 4 = 120 байта на 32 битовите компютри.
Елементите на масива могат да бъдат от произволен тип, например char, float, long double и включително потребителски дефиниран - например типът compl_num от лекция 10 или airtime от лекция 12. Следващата дефиниция запазва памет в компютъра за масата на 100 обекта.
long double mass[100];
2. Елементите на масива (Array Elements). Както казахме, всяка една променлива в масива се нарича елемент. Тези елементи са подредени и номерирани и достъпът до тях се осигурява с така наречения индекс или индексен номер или индексна променлива. Индексът на първият елемент е нула! Това е причина за множоство грешки сред начинаещите програмисти и затова е добре да се запомни от самото начало. Вторият елемен в масива има индекс 1, третият - 2 и т.н. В масива age последният елемент има индекс 29 , а в масива mass - 99. Достъпът до елементите на масива се осъществява с техния индекс като се изписва името на масива и индексът на елемента, заграден в средни скоби. Например следните пет реда променят възрастта на пет служителя.
age[0]
= 22;
age[1]
= 31;
age[4]
= 19;
age[5]
= 21;
age[29]
= 40;
Не бъркайте стойността на индекса със стойността на елемента. В първия ред елемент номер 1 от масива, който е с индекс 0, придобива стойност 22. Вторият елемент, с индекс 1, придобива стойност 31 и т.н. 30тият елемен придобива стойност 40.
По същият начин, ако са въведени 30те възрасти те могат да бъдат показани на екрана със следните редове.
for(int
j = 0; j < 30; ++j) // cycle through all 30 elements
cout << age[j] << endl; // display
each element
3. Инициализиране на елементите на масива (Initializing Array Elements). В C++ елементи на един масив могат да се инициализират с определени стойности още при дефинирането на масива. Ето един пример на масив, който съдържа броя на дните в месеците на една невисокосна годината.
int
days_per_month[12] = { 31, 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31 };
Формата на инициализирането е следната: след дефиницията на масива следва знака равно (който е и знак на операцията присвояване на стойност) и стойностите, с които се инициализарат елементите, заградени в големи скоби и разделени със запетаи. Вместо всички елементи, могат да се инициализират само първите няколко с определени стойности - тогава в списъка със стойности в големите скоби броят на стойности е по-малък от броя елементи на масива. Останалите елементи се инициализират с нули.
long double mass[100] = { 10.2543445, 9.234987 };
В този случай останалите елементи, от третия до стотния, ще имат стойност нула.
Ако искаме да инициализираме всички елементи със стойност нула то можем да напишем следното
int sum[10] = { 0 };
Имайте предвид, че локалните променливи, като тези дефинирани в телата на функциите или в дефиницията на класовете, нямат определена начална стойност. Те могат да заемат произволна стойност и ако програмистът разчита, че те имат стойност нула, то това ще доведе до неверно изпълнение на програмата. Затова програмистът трябва да се грижи всички локални променлива да бъдат инициализирани с подходяща начална стойност.
4. Масиви с няколко размерности (Multidimensional Arrays). Масивите могат да имат повече от една индексна променлива, т.е. да бъдат с повече от една размерност. Ето дефиницията на една матрица
float matrix[3][4]; // define two-dimensional array which represent a matrix
Обърнете внимание, че всяка една размерност е заградена в средни скоби - това е различно от, например, програмния език Pascal, където размерностите са разделени със запетайки. Компютърът запазва памет от 3 x 4 x 4 байта, понеже има 3 x 4 елемента в масива, а всеки един от тях е от тип float, който е от 4 байта. В паметта елементите се разполагат по следния начин (началото на паметта приемаме да е най-отгоре)
matrix[0][0]
matrix[0][1]
matrix[0][2]
matrix[0][3]
matrix[1][0]
matrix[1][1]
matrix[1][2]
matrix[1][3]
matrix[2][0]
matrix[2][1]
matrix[2][2]
matrix[2][3]
В матрицата matrix[0][0] стои най-горе и в най-ляво, а в паметта е първи. Последен в паметта е елементът matrix[2][3], който стои в матрицата най-долу и най-дясно.
Двуразмерен масив може да се инициализира по следния начин (обърнете внимание, че всеки ред на матричните елементи е заграден с големи скоби):
float
matrix[3][4] = { { 1.23, -12.654, 0.001, -21.000 }
{ -21.6723, -2.54, 0.0, 21.0200 }
{ 0.2433, 2.54, 121.734, 1221.000 } };
Това е равнозначно на следните редове:
float matrix[3][4];
matrix[0][0]
= 1.23;
matrix[0][1]
= -12.654;
matrix[0][2]
= 0.001;
matrix[0][3]
= -21.000
matrix[1][0]
= -21.6723;
matrix[1][1]
= -2.54;
matrix[1][2]
= 0.0;
matrix[1][3]
= 21.0200
matrix[2][0]
= 0.2433;
matrix[2][1]
= 2.54;
matrix[2][2]
= 121.734;
matrix[2][3]
= 1221.000;
Аналогично можем да дефинираме масиви с повече от две размерности. Например масив, който съхранява плътността на клетките в куб с размер 100 x 100 x 100 се дефинира по следния начин:
float density[100][100][100];
С това свършваме уводната лекция за масивите. В заключение ще споменем, че C++ не поддържа механизъм за проверка дали четете или пишете извън обсега на даден масив. Например ако за горния масив matrix искате да покажете на екрана елемента matrix[3][3], то компютърът ще прочете в стойността в паметта, която е голяма четири байта и се намира на 12 байта след последния елемент на масива matrix[2][3] - т.е. една безсмислена стойност. По-опасно е да се пише в паметта, т.е. на несъществуващ елемент на масива да се присвоява определена стойност, защото Вашата програма ще запише стойност в паметта, която се използва от друга програма и ще наруши нейната логика на изпълнение. Затова програмистът трябва сам да се грижи да не излиза извън паметта на масива.
Литература
[1] Robert Lafore; C++ Interactive Course. Waite Group Press, Macmillan Computer Publishing, 1996.
Автор: Проф. Процесор Аритметиков
Keywords: С++,
OOP programming , C++ , Classes , Inheritance , Reusability , Creating
New Data Types , Polymorphism and Overloading
Ключови думи: клас
, обект, обектно ориентирано програмиране , полиморфизъм switch if else
?