9-bo‘lim

Massivlar

Bir va ko'p o'lchamli massivlar, indekslash, xotirada joylashuvi, chegaradan chiqish xavfi va massivlar bilan ishlash usullari.

🕑 12 daqiqa o‘qish 📄 102 so‘z 👁 3 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Massiv yaratish
  2. Massivni aylanish
  3. Chegaradan chiqish
  4. Qidiruv va statistika
  5. Chiziqli qidiruv
  6. Massivni saralash
  7. Ikki o'lchamli massiv
  8. Jadval bilan ishlash
  9. Massivni nusxalash
  10. Massivni nol bilan to'ldirish
  11. Xulosa

Massiv - bir turdagi elementlarni ketma-ket saqlaydigan tuzilma. Bu C dagi eng asosiy ma'lumot tuzilmasi.

Massiv yaratish #

C
int baholar[5];                          /* bo'sh massiv */
int ballar[5] = {85, 92, 78, 95, 88};    /* qiymat bilan */
int nollar[5] = {0};                     /* hammasi nol */
int qisqa[] = {1, 2, 3};                 /* hajm avtomatik: 3 */
C
#include <stdio.h>

int main(void) {
    int ballar[5] = {85, 92, 78, 95, 88};

    printf("Birinchi element : %d\n", ballar[0]);
    printf("Uchinchi element : %d\n", ballar[2]);
    printf("Oxirgi element   : %d\n", ballar[4]);

    ballar[1] = 100;
    printf("O'zgartirilgan   : %d\n", ballar[1]);

    return 0;
}
Natija
Birinchi element : 85
Uchinchi element : 78
Oxirgi element   : 88
O'zgartirilgan   : 100
int ballar[5] xotirada 85 [0] 1000 92 [1] 1004 78 [2] 1008 95 [3] 1012 88 [4] 1016 ??? [5] Har bir int 4 bayt - manzillar 4 talab oshadi [5] massivga tegishli emas - u yerga tegmang!
Indeks noldan boshlanadi, oxirgisi esa hajm - 1
Indeks noldan boshlanadi

5 elementli massivda indekslar 0, 1, 2, 3, 4. ballar[5] yo'q!

Bu eng ko'p uchraydigan xato - «bittaga adashish» (off-by-one) deb ataladi.

C
int ballar[5];

for (int i = 1; i <= 5; i++) {     /* NOTO'G'RI */
    ballar[i] = 0;                 /* ballar[5] mavjud emas */
}

for (int i = 0; i < 5; i++) {      /* to'g'ri */
    ballar[i] = 0;
}

Qoida: for (int i = 0; i < hajm; i++) - <, <= emas.

Massivni aylanish #

C
#include <stdio.h>

int main(void) {
    int ballar[5] = {85, 92, 78, 95, 88};
    int soni = sizeof(ballar) / sizeof(ballar[0]);

    printf("Massivda %d ta element bor.\n", soni);

    for (int i = 0; i < soni; i++) {
        printf("  [%d] = %d\n", i, ballar[i]);
    }

    return 0;
}
Natija
Massivda 5 ta element bor.
  [0] = 85
  [1] = 92
  [2] = 78
  [3] = 95
  [4] = 88
Elementlar sonini hisoblash
C
int soni = sizeof(massiv) / sizeof(massiv[0]);

Bu «butun massivning bayt hajmini bitta elementning hajmiga bo'lish» degani. Massiv hajmi o'zgarsa, bu hisob avtomatik moslashadi.

Muhim ogohlantirish: bu hiyla faqat massiv e'lon qilingan funksiyada ishlaydi. Massivni funksiyaga uzatsangiz, u ko'rsatkichga aylanadi va sizeof ko'rsatkich hajmini beradi. Buni 13-bo'limda batafsil ko'ramiz.

Chegaradan chiqish #

C
int ballar[5] = {85, 92, 78, 95, 88};

printf("%d\n", ballar[10]);    /* XAVFLI: begona xotira */
ballar[100] = 42;              /* XAVFLI: begona xotirani buzadi */
C chegarani tekshirmaydi

Python'da ballar[10] xatolik beradi. C da esa dastur shunchaki o'sha manzildagi baytlarni o'qiydi - u yerda nima bo'lsa ham.

Natija uch xil bo'lishi mumkin:

  1. Axlat qiymat chiqadi (eng «yaxshi» holat - xatoni sezasiz);
  2. Boshqa o'zgaruvchi buziladi (xato butunlay boshqa joyda ko'rinadi);
  3. Dastur qulaydi (segmentation fault).

Eng yomoni - birinchi holat, chunki dastur ishlayotgandek ko'rinadi.

Himoya usullari:

  • Indeksni doim tekshiring;
  • Sikllarda < hajm yozing;
  • Kompilyatsiyada -fsanitize=address bayrog'ini ishlating (19-bo'lim).

Qidiruv va statistika #

C
#include <stdio.h>

int main(void) {
    int ballar[8] = {85, 92, 78, 95, 88, 61, 100, 73};
    int soni = sizeof(ballar) / sizeof(ballar[0]);

    int eng_katta = ballar[0];
    int eng_kichik = ballar[0];
    int yigindi = 0;

    for (int i = 0; i < soni; i++) {
        if (ballar[i] > eng_katta) {
            eng_katta = ballar[i];
        }
        if (ballar[i] < eng_kichik) {
            eng_kichik = ballar[i];
        }
        yigindi += ballar[i];
    }

    printf("Elementlar soni : %d\n", soni);
    printf("Eng katta       : %d\n", eng_katta);
    printf("Eng kichik      : %d\n", eng_kichik);
    printf("Yig'indi        : %d\n", yigindi);
    printf("O'rtacha        : %.2f\n", (double) yigindi / soni);

    return 0;
}
Natija
Elementlar soni : 8
Eng katta       : 100
Eng kichik      : 61
Yig'indi        : 672
O'rtacha        : 84.00
Boshlang'ich qiymatni noldan olmang
C
int eng_katta = 0;    /* xato bo'lishi mumkin */

Agar barcha elementlar manfiy bo'lsa, natija 0 bo'lib qoladi - bu massivda umuman yo'q qiymat.

To'g'ri yo'l - birinchi elementdan boshlash:

C
int eng_katta = massiv[0];

Chiziqli qidiruv #

C
#include <stdio.h>

int main(void) {
    int ballar[8] = {85, 92, 78, 95, 88, 61, 100, 73};
    int soni = 8;
    int qidirilayotgan = 95;
    int topilgan_indeks = -1;

    for (int i = 0; i < soni; i++) {
        if (ballar[i] == qidirilayotgan) {
            topilgan_indeks = i;
            break;
        }
    }

    if (topilgan_indeks != -1) {
        printf("%d qiymati %d-indeksda topildi.\n", qidirilayotgan, topilgan_indeks);
    } else {
        printf("%d topilmadi.\n", qidirilayotgan);
    }

    return 0;
}
Natija
95 qiymati 3-indeksda topildi.

Massivni saralash #

C
#include <stdio.h>

int main(void) {
    int ballar[6] = {85, 92, 78, 95, 88, 61};
    int soni = 6;

    /* Pufakcha saralash */
    for (int i = 0; i < soni - 1; i++) {
        for (int j = 0; j < soni - i - 1; j++) {
            if (ballar[j] > ballar[j + 1]) {
                int vaqtinchalik = ballar[j];
                ballar[j] = ballar[j + 1];
                ballar[j + 1] = vaqtinchalik;
            }
        }
    }

    printf("Saralangan: ");
    for (int i = 0; i < soni; i++) {
        printf("%d ", ballar[i]);
    }
    printf("\n");

    return 0;
}
Natija
Saralangan: 61 78 85 88 92 95 
Elementlarni almashtirish
C
int vaqtinchalik = a;
a = b;
b = vaqtinchalik;

C da Python'dagi a, b = b, a yo'q. Uchinchi o'zgaruvchi kerak - aks holda birinchi qiymat yo'qoladi.

Ikki o'lchamli massiv #

C
#include <stdio.h>

int main(void) {
    int jadval[3][4] = {
        {1,  2,  3,  4},
        {5,  6,  7,  8},
        {9, 10, 11, 12}
    };

    for (int qator = 0; qator < 3; qator++) {
        for (int ustun = 0; ustun < 4; ustun++) {
            printf("%4d", jadval[qator][ustun]);
        }
        printf("\n");
    }

    printf("\n[1][2] elementi: %d\n", jadval[1][2]);

    return 0;
}
Natija
   1   2   3   4
   5   6   7   8
   9  10  11  12

[1][2] elementi: 7
int jadval[3][4] - mantiqiy va haqiqiy ko'rinish Biz shunday tasavvur qilamiz 1 2 3 4 5 6 7 8 9 10 11 12 Xotirada esa ketma-ket yotadi 1 2 3 4 5 6 7 8 9 10 11 12 Qator bo'yicha joylashuv (row-major) Shuning uchun qator bo'yicha aylanish ustun bo'yichadan tezroq
Ikki o'lchamli massiv aslida bitta uzun chiziq

Jadval bilan ishlash #

C
#include <stdio.h>

int main(void) {
    int savdo[3][4] = {
        {120, 150, 130, 170},
        {200, 180, 210, 190},
        { 90, 110, 100, 120}
    };

    const char *mahsulotlar[3] = {"Klaviatura", "Sichqoncha", "Monitor"};

    printf("%-12s %6s %6s %6s %6s %8s\n",
           "Mahsulot", "1-chor", "2-chor", "3-chor", "4-chor", "Jami");

    int umumiy = 0;

    for (int i = 0; i < 3; i++) {
        int qator_jami = 0;

        printf("%-12s", mahsulotlar[i]);

        for (int j = 0; j < 4; j++) {
            printf("%6d", savdo[i][j]);
            qator_jami += savdo[i][j];
        }

        printf("%8d\n", qator_jami);
        umumiy += qator_jami;
    }

    printf("%-12s %6s %6s %6s %6s %8d\n", "JAMI", "", "", "", "", umumiy);

    return 0;
}
Natija
Mahsulot     1-chor 2-chor 3-chor 4-chor     Jami
Klaviatura     120   150   130   170     570
Sichqoncha     200   180   210   190     780
Monitor         90   110   100   120     420
JAMI                                         1770

Massivni nusxalash #

C
#include <stdio.h>

int main(void) {
    int asl[5] = {1, 2, 3, 4, 5};
    int nusxa[5];

    /* int nusxa = asl;   XATO: massivni shunchaki tenglashtirib bo'lmaydi */

    for (int i = 0; i < 5; i++) {
        nusxa[i] = asl[i];
    }

    nusxa[0] = 100;

    printf("Asl   : %d %d\n", asl[0], asl[1]);
    printf("Nusxa : %d %d\n", nusxa[0], nusxa[1]);

    return 0;
}
Natija
Asl   : 1 2
Nusxa : 100 2
memcpy bilan tezroq
C
#include <string.h>

memcpy(nusxa, asl, sizeof(asl));

memcpy xotira bloklarini bir yo'la ko'chiradi va sikldan tezroq ishlaydi. Faqat hajmni to'g'ri hisoblang - sizeof(asl) baytlarda beradi, elementlar sonida emas.

Massivni nol bilan to'ldirish #

C
#include <stdio.h>
#include <string.h>

int main(void) {
    int a[5] = {0};              /* barcha elementlar nol */

    int b[5];
    memset(b, 0, sizeof(b));     /* keyinroq nollash */

    printf("a: ");
    for (int i = 0; i < 5; i++) printf("%d ", a[i]);
    printf("\nb: ");
    for (int i = 0; i < 5; i++) printf("%d ", b[i]);
    printf("\n");

    return 0;
}
Natija
a: 0 0 0 0 0 
b: 0 0 0 0 0 
memset faqat baytlarni to'ldiradi
C
int a[5];
memset(a, 1, sizeof(a));    /* 1 EMAS! */

memset har bir baytga 1 yozadi, shuning uchun har bir int 0x01010101 = 16843009 bo'ladi.

memset faqat 0 va -1 uchun xavfsiz. Boshqa qiymatlar uchun oddiy sikl yozing.

Amaliy topshiriq
  1. 10 elementli massiv yaratib, uni 1 dan 10 gacha to'ldiring.
  2. Massivning yig'indisi, o'rtachasi va eng kattasini toping.
  3. Massivni teskari tartibda chiqaring.
  4. Chegaradan chiqib, nima bo'lishini ko'ring (massiv[100]).
  5. Massivda berilgan qiymatni qidiring.
  6. Pufakcha saralashni yozib, har qadamni chiqaring.
  7. Ikkita massivni birlashtirib, uchinchisiga yozing.
  8. 3x3 matritsa yaratib, uning diagonali yig'indisini toping.
  9. Matritsani transponirlang (qator va ustunni almashtiring).
  10. Massivdagi juft va toq sonlar sonini hisoblang.

Xulosa #

  • Massiv - bir turdagi elementlarning ketma-ket to'plami.
  • Indeks noldan boshlanadi; oxirgi indeks - hajm - 1.
  • C chegarani tekshirmaydi - chegaradan chiqish xotirani buzadi.
  • Sikllarda doim i < hajm yozing, i <= hajm emas.
  • Elementlar soni: sizeof(massiv) / sizeof(massiv[0]).
  • Bu hiyla massiv e'lon qilingan funksiyada ishlaydi.
  • Eng katta/kichikni qidirishda boshlang'ich qiymatni birinchi elementdan oling.
  • Massivni = bilan nusxalab bo'lmaydi - sikl yoki memcpy kerak.
  • Ikki o'lchamli massiv xotirada qator bo'yicha ketma-ket yotadi.
  • memset baytlar bilan ishlaydi - faqat 0 uchun xavfsiz.

Keyingi bo'limda satrlarni - C dagi eng o'ziga xos mavzuni ko'ramiz.

Xatolik topdingizmi?

Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.