Паролингизни унутдингизми?
Login
Left, Right, Center Left, Center, Right Center, Left, Right



C++ 4-darslik

 Massivlar Bu qismda dasturdagi ma'lumot strukturalari bilan tanishishni boshlaymiz.Dasturda ikki asosiy tur ma'lumot strukturalari mavjuddir. Birinchisi statik, ikkinchisi dinamikdir.

 

 Statik deganimizda hotirada egallagan joyi o'zgarmas, dastur boshida beriladigan strukturalarni nazarda tutamiz. Dinamik ma'lumot tiplari dastur davomida o'z hajmini, egallagan hotirasini o'zgartirishi mumkin.

 Agar struktura bir hil kattalikdagi tiplardan tuzilgan bo'lsa, uning nomi massiv (array)  deyiladi. Massivlar dasturlashda eng ko'p qo'laniladigan ma'lumot tiplaridir. Bundan tashqari strukturalar bir necha farqli tipdagi o'zgaruvchilardan tashkil topgan bo'lishi mumkin. Buni biz klas (Pascalda record) deymiz. Masalan bunday strukturamiz ichida odam ismi va yoshi bo'lishi mumkin.  

Bu bo'limda biz massivlar bilan yaqindan tanishib o'tamiz. Bu bo'limdagi massivlarimiz C uslubidagi, pointerlarga (ko'rsatkichlarga) asoslan strukturalardir. Massivlarning boshqa ko'rinishlarini keyingi qismlarda o'tamiz.

 Massivlar hotirada ketma-ket joylashgan, bir tipdagi o'zgaruvchilar guruhidir. Alohida bir o'zgaruvchini ko'rsatish uchun massiv nomi va kerakli o'zgaruvchi indeksini yozamiz. C/C++ dagi massivlardagi elementlar indeksi har doim noldan boshlanadi. Bizda char tipidagi m nomli massiv bor bo'lsin. Va uning 4 dona elementi mavjud bo'lsin. Shemada bunday ko'rsataylik:

  m[0] ->   4

 m[1] -> -44

 m[2] -> 109

 m[3] ->  23

 

Ko'rib turganimizdek, elementga murojaat qilish uchun massiv nomi va [] qavslar ichida element indeksi yoziladi. Bu yerda birinchi element qiymati 4, ikkinchi element - 1 nomerli indeksda -44 qiymatlari bor ekan. Ohirgi element indeksi n-1 bo'ladi (n - massiv elementlari soni).

[] qavslar ichidagi indeks butun son yoki butun songa olib keluvchi ifoda bo'lmog'i lozim. Masalan:

 ...

int k = 4, l = 2;

m[ k-l ] = 77; // m[2] = 77 

m[3] *= 2; // m[3] = 46

double d = m[0] * 6; // d = 24

cout << m[1]; // Ekranda: -44 

...

 Massivlarni ishlatish uchun ularni e'lon qilish va kerak bo'lsa massiv elementlarini initsalizatsiya qilish kerak. Massiv e'lon qilinganda kompilyator elementlar soniga teng hajmda hotira ajratadi. Masalan yuqorida qo'llanilgan char tipidagi m massivini e'lon qilaylik.

 char m[4];

 Bu yerdagi 4 soni massivdagi elementlar miqdorini bildiradi. Bir necha massivni e'londa bersak ham bo'ladi:

 int m1[4], m2[99], k, l = 0;

 Massiv elementlari dastur davomida initsalizatsiya qilishimiz mumkin, yoki boshlang'ich qiymatlarni e'lon vaqtida, {} qavslar ichida ham bersak bo'ladi. {} qavslardagagi qiymatlar massiv initsalizaytsiya ro'yhati deyiladi.

 int n[5] = {3, 5, -33, 5, 90};

 Yuqorida birinchi elementning qiymati 3, ikkinchiniki 5 ... ohirgi beshinchi element qiymati esa 90 bo'ldi. Boshqa misol:

 double array[10] = {0.0, 0.4, 3.55};

 Bu yerdagi massiv tipi double bo'ldi. Ushbu massiv 10 ta elementdan iboratdir. {} qavslar ichida esa faqat boshlangich uchta element qiymatlari berildi. Bunday holda, qolgan elementlar avtomatik tarzda nolga tenglashtiriladi. Bu yerda aytib o'tishimiz kerakki, {} qavslar ichida berilgan boshlangish qiymatlar soni massivdagi elementlar sonidan katta bo'lsa, sintaksis hatosi vujudga keladi. Masalan:

 char k[3] = {3, 4, 6, -66, 34, 90}; // Hato! 

 Uch elementdan iborat massivga 6 dona boshlangich qiymat berilyapti, bu hatodir. Boshqa misolni ko'rib chiqaylik: 

 int w[] = {3, 7, 90, 78};

 w nomli massiv e'lon qilindi, lekin [] qavslar ichida massivdagi elementlar soni berilmadi. Bunday holda necha elementga joy ajratishni kompilyator {} qavslar ichidagi boshlangich qiymatlar miqdoriga qarab biladi. Demak, yuqoridagi misolda w massivimiz 4 dona elementdan iborat bo'ladi.  

E'lon davridagi massiv initsalizatsiya ro'yhati dastur ijrosi vaqtidagi initsalizatsiyadan ko'ra tezroq ishlaydigan mashina kodini vujudga keltiradi. 

Bir misol keltiraylik.

 // Massivlar bilan ishlash.

 # include <iostream.h>

# include <iomanip.h>

const int massiv = 8; // massiv kattaligi uchun konstanta

 int k[massiv];

char c[massiv] = {5,7,8,9,3,44,-33,0}; // massiv initsalizatsiya ro'yhati

 int main()

{

   for (int i = 0; i < massiv; i++) {

      k[i] = i + 1;                // dastur ichida inisalizatsiya

   }

     for (int j = 0; j < massiv; j++) {

      cout << k[j]

           << setw(4)

           << c[j]

           << endl; 

   }  

     return (0);

}

 Ekranda:

 1   5

2   7

3   8

4   9

5   3

6  44

7 -33

8   0

 Yuqorida <iomanip.h> faylini dasturimizga kiritdik. Bu e'lon faylida standart kirish/chiqish oqimlari bilan ishlaydigan buyruqlar berilgan. Dasturimizda qo'llanilgan setw() manipulyatori chiqish oqimiga berilayatgan ma'lumotlarning eng kichik kengligini belgilaydi, biz setw() parametrini 4 deb berdik, demak c[] massivi elementlari 4 harf kenglikda ekranga bosiladilar. Agar kenglik kamlik qilsa, u kattalashtiriladi, agar bo'sh joy qolsa, elementlar chapga yondashilib yoziladi. Biz <iomanip.h> va manipulyatorlarni keyinroq to'la ko'rib chiqamiz.

 Misolimizda massiv nomli konstantani qo'lladik. Uning yordamida massiv chegaralarini va for strukturasidagi chegaraviy qiymatlarni berdik. Bunday o'zgarmasni qo'llash dasturda hatoga yo'l qo'yishni kamaytiradi. Massiv chegarasi o'zgarganda, dasturning faqat bir joyiga o'zgarish kiritiladi. Massiv hajmi e'lonida faqat const sifatli o'zgaruvchilar qo'llanilishi mumkin.

 Massivlar bilan ishlaganda eng ko'p yo'l qoyiladigan hato bu massivga 0 dan kichkina va (n-1) dan (n: massivdagi elementlar soni) katta indeks bilan murojaat qilishdir. Bunday hato dastur mantig'i hatosiga olib keladi. Kompilyator bu turdagi hatolarni tekshirmaydi. Keyinroq o'zimiza yozgan massiv klaslarida ushbu hatoni tekshiriladigan qilishimiz mumkin. 10 ta sonning tushish ehtimilini ko'rsaturvchi dastur yozaylik.

 

// Ehtimollar va massivlar

 # include <iomanip.h>

# include <iostream.h>

# include <time.h>

# include <stdlib.h>

 

int main ()

{

   const int massivHajmi = 10;

   int m[massivHajmi] = {0}; // hamma 10 ta element

                             // 0 ga tenglashtirildi 

      srand( time(NULL) );

   for(int i = 0; i < 1000; i++) {

      ++m[ rand() % 10 ]; 

   }

      for(int j = 0; j < massivHajmi; j++) {

      cout << j << setw(4) << m[j] << endl;

   }

      return (0);

}

 Ekranda:

 0  96   

1  89

2 111

3  97

4 107

5  91

6 100

7 118

8  99

9  92

 

Ko'rib turganimizdek, sonlarning tushish ehtimoli nisbatan tengdir. Albatta, bu qiymatlar dasturning har yangi ishlashida o'zgaradi.

 ++m[ rand() % 10 ];

 Yozuvi bilan biz massivning rand() % 10 indeksli elementini birga oshirmoqdamiz. Bunda rand () % 10 ifodasidan chiqadigan qiymatlar [0;9] ichida yotadi. Satrlar, yani harflar ketma-ketligi ("Toshkent", "Yangi yilingiz bilan!"...) C/C++ da char tipidagi massivlar yordamida beriladi. Bunday satrlar bilan islovlar juda tez bajariladi. Chunki ortiqcha tekshirishlar bajarilmaydi.

Bundan tashqari C++ da ancha rivojlangan String klasi mavjuddir, u oddiy char bilan berilgan satrlardan ko'ra qulayroqdir. Lekin ushbu klas ko'proq joy egallaydi va massivli satrlardan ko'ra sekinroq ishlaydi. String klasini keyingi qismlarda o'tamiz. Qolaversa, satrlar bilan ishlash uchun biz o'zimiz klas yoki struktura yozishimiz mumkin. C dan meros bo'lib qolgan satrlar ustida amallar bajarish uchun biz dasturimizga <string.h> (yangi ismi <cstring>) e'lon faylini kiritishimiz kerak. Ushbu e'lon faylida berilgan funksiyalar bilan keyingi bo'limda ishlaymiz.

 Harflar, yani literalar, aytib o'tganimizdek, C++ da char tipi orqali beriladi. Literalar apostroflarga ('S', '*' ...) olinadi. Satrlar esa qo'shtirnoqlarga olinadi. Satrlar e'loniga misol beraylik. 

 char string[] = "Malibu";

char *p = "Ikkinchi!?!";

 Satrlarni yuqoridagi ikkita yo'l bilan initsalizatsiya qilsa bo'ladi. Satrlar ikkinchi uslubda e'lon qilinganda, yani pointer mehanizmi qo'llanilganda, ba'zi bir kompilyatorlar satrlarni hotiraning konstantalar saqlanadigan qismiga qo'yadi. Yani ushbu satrlarga o'zgartirish kiritilishi ta'qiqlanadi. Shu sababli satrlarni hardoim o'zgartirish imkoni bo'lishi uchun ularni char tipidagi massivlar ko'rinishida e'lon qilish afzaldir.   

Satrlar massiv yordamida berilganda, ularning uzunligi noma'lumdir. Shu sababli satrning tugaganligini bildirish uchun satr ohiriga mahsus belgi nol literasi qo'yiladi. Uning dastursa belgilanishi '\0' ko'rinishga ega. Demak, yuqorida berilgan "Malibu" satriga ohiriga '\0' belgisi qo'shiladi, yani massivning umumiy uzunligi "Malibu":6 + '\0':1 = 7 ta char tipidagi elementga teng bo'ladi. Satrlarni massiv initsalizatsiya ro'yhati ko'rinishida ham bersak bo'ladi:

 char c[6] = {'A', 'B', 'C', 'D', 'E' , '\0'};

...

cout << c;

...

Ekranda:

 ABCDE

 

Biz cout bilan c ning qiymati ekranga bosib chiqardik. Aynan shunday klaviaturadan ham o'qib olishimiz mumkin:

 char string[80];

cin >> string;

 Eng muhimi satr bilan '\0' belgisi uchun yetarli joy bo'lishi kerak. Satrlar massiv yordamida berilganligi uchun, alohida elementlarga indeks orqali yetishish mumkin, masalan:

 char k[] = "Bahor keldi, gullar ochildi."; 

for (int i = 0; k[i] != '\0'; i++)

   if ( (i mod 2) == 0 )     // juft sonlar uchun haqiqat bo'ladi 

      cout << k[i] << " ";

 Ekranda:

 B h r k l i   u l r o h l i

 Yuqoridagi misolda, sikl tugashi uchun k[i] element '\0' belgiga teng bo'lishi kerak.  

               FUNKSIYALARNING MASSIV KIRISH PARAMETRLARI

 Funksiyalarga massivlarni kirish argument sifatida berish uchun parametr e'lonida [] qavslar qo'yiladi. Masalan: 

...

void sortArray(int [], int );  // funksiya e'loni

void sortArray(int n[], int hajm) { // funksiya aniqlanishi

 ...

}

...

 Dasturda esa, funksiya chaqirilganda, massivning faqat ishmi beriladi halos, [] qavslarning keragi yo'q. 

 int size = 10;

int array[size] = {0};

...

void sortArray(array, size); // funksiya chaqirig'i,

                        // faqat massiv ismi - array berildi

...

 

Funksiyaga massivlarni berganimizda, eng katta muammo bu qanday qilib massivdagi elementlari sonini berishdir. Eng yaxshi usul bu massiv kattaligini qo'shimcha kirish parametri orqali funksiyaga bildirishdir. Bundan tashqari, massiv hajmini global konstanta orqali e'lon qilishimiz mumkin. Lekin bu ma'lumotni ochib tashlaydi, global sohani ortiqcha narsalar bilan to'ldirib tashlaydi. Undan tashqari massiv hajmini funksiyaning o'ziga yozib qoyishimiz mumkin. Biroq bunda bizning funksiyamiz faqat bitta kattalikdagi massivlar bilan ishlaydigan bo'lib qoladi. Yani dasturimiz dimamizmni yo'qotadi. Klaslar yordamida tuzilgan massivlar o'z hajmini biladi. Agar bunday ob'ektlarni qo'llasak, boshqa qo'shimcha parametrlarni qo'llashimizning keragi yo'q.

 Funksiyalarga massivlar ko'rsatkich ko'rinishida beriladi. Buni C++, biz ko'rsatmagan bo'lsak ham, avtomatik ravishda bajaradi. Agar massivlar qiymat bo'yicha chaqirilganda edi, har bir massiv elementining nushasi olinishi kerak bo'lardi, bu esa dastur ishlash tezligiga salbiy ta'sir ko'rsatar edi. Lekin massivning alohida elementi argument o'rnida funksiyaga berilganda, ushbu element, aksi ko'rsatilmagan bo'lsa, qiymat bo'yicha beriladi. Masalan:

 ...

double m[3] = {3.0, 6.88, 4.7};

void foo(double d){

   ...

}

...

int main()

{

...

void foo(m[2]); // m massivining uchinchi elementining qiymati - 4.7 berildi

...

return (0);

}

 Agar kiritilayatgan massiv funksiya ichida o'zgarishi ta'qiqlansa, biz funksiya massiv parametri oldiga const sifatini qo'ysak bo'ladi: 

 foo(const char []);

 Bunda funksiyaga kiradigan massiv funksiya tomonidan o'zgartirilmaydi. Agar o'zgartirishga urinishlar bo'lsa, kompilyator hato beradi. Massivlar va funksiyalarning birga ko'llanilishiga misol beraylik.

 

// Massiv argumentli funksiyalar

# include <istream.h>

 const int arraySize = 10;

double ortalama(int m[], int size) {

   double temp = 0;

      for (int i = 0; i < size; i++) {

      temp += m[i];

   }

   return ( temp / size );

}

 void  printArray(const int n[], int size, int ortalama) {

   for (int i = 0; i < size; i++) {

      cout << n[i]; << endl;

   }   

   cout << "O'rtalama: " << ortalama << endl;  

}

 int main()

{ 

   int m[10] = {89,55,99,356,89,335,78743,44,767,346};

   printArray(m, arraySize, ortalama(m, arraySize)) ;

   return (0);

}

 Ekranda:

 89

55

99

356

89

335

78743

44

767

346

O'rtalama: 8092.3

 BIR NECHA INDEKSLI MASSIVLAR

 Massivlar bir necha indeksga ega bo'lishlari mumkin. C++ kompilyatorlari eng kamida 12 ta indeks bilan ishlashlari mumkin. Masalan, matematikadagi m x n kattalikdagi matritsani ikkita indeksli massiv yordamida berisak bo'ladi. 

 int matritsa [4][10];

 Yuqorida to'rt satrlik, 10 ustunlik matritsani e'lon qildik. Bir indeksli massivlar kabi ko'p indeksli massivlarni initsalizatsiya ro'yhati bilan birga e'lon qilish mumkin. Masalan:

 char c[3][4] = { 

                  {  2,  3,9, 5}, // birinchi satr qiymatlari

                  {-10, 77,5, 1}, // ikkinchi  "       "

                  { 90,233,3,-3}  // uchinchi  "       "

               };

 int m[2][2] = {56,77,8,-3}; // oldin birinchi satrga qiymatlar beriladi,

                            // keyin esa ikkinchi satrga

 

double d[4][3][6] = {2.55, -46,0988}; // birinchi satrning dastlabki ikkita

                                      // elementi qiymat oladi,

                                      // massivning qolgan elementlari esa

                                      // nolga tenglashtiriladi

 Massivning har bir indeksi alohida [] qavslar ichiga olinishi kerak. Yuqoridagi c[][] massivining ikkinchi satr, birinchi ustunidagi elementi qiymatini birga oshirish uchun 

 ++c[1][0]; // yoki c[1][0]++; 

           //      c[1][0] += 1;

           //      c[1][0] = c[1][0] + 1;

 deb yozishimiz mumkin. Massiv indekslari 0 dan boshlanishini unutmaslik zarur. Agar 

 ++c[1,0];

 deb yozganimizda hato bo'lar edi. C++ bu yozuvni

 ++c[0];

 deb tushunar edi, chunki kompilyator vergul bilan ajratilgan ro'yhatning eng ohirgi elementini qabul qilardi. Hullas, C++ dagi ko'p indeksli massivlar dasturchiga behisob imkoniyatlar beradi. Undan tashqari, ular hotirada static joylashganligi uchun ularning ishlash tezligi kattadir. 

 C++ dagi ko'p indeksli massivlar hotirada ketma-ket joylashgandir. Shu sababli agar massiv funksiyaga kirish parametri sifatida berilsa, faqat birinchi indeks tushurilib qoldiriladi, qolgan indekslar esa yozilishi shartdir. Aks taqdirda funksiya massiv kattaligini to'g'ri keltirib chiqarolmaydi. Massiv parametrli bir funksiya e'lonini beraylik.

 //Ko'p indeksli massivlar

# include <iostream.h>

int indeks = 3;

int intArray[indeks][4] = {}; // hamma elementlar 0 ga tenglashtirildi

void printArray(int mass[][4], int idx){   // funksiya e'loni

  

   for (int i = 0; i < idx; i++) { // massivning birinchi indeksini

                                   // o'zgartirsa bo'ladi

 

      for (int k = 0; k < 4; k++){ // massivning ikkinchi indeksi o'zgarmaydi

         cout << mass[i][k];

      }

      cout << endl;

   }

   return;

}

...

 

int main()

{

...

printArray(intArray); // funksiya chaqirig'i

...

return (0);

}

 Massivning indekslarini funksiyaga bildirish yana muammoligicha qoladi. Albatta, birinchi indeksdan tashqari qolgan boshqa indekslar kattaligini funksiya ichida berish ma'noga egadir. Lekin birinchi indeks kattaligini tashqaridan, qo'shimcha parametr sifatida bersak, funksiyamiz chiroyliroq chiqadi, turli kattalikdagi massivlarni o'lish imkoniga ega bo'ladi.

Share