• ArrayInt() { delete[] m_data; } void erase() { delete[] m_data;
  • int operator[](int index) { assert(index >= 0 index return m_data[index]; }
  • 10-ma’ruza. Konteynerli tiplar va ularning qo’llanilishi. Konteyner sinflar va iteratorlar




    Download 278.14 Kb.
    Pdf ko'rish
    bet3/3
    Sana03.05.2023
    Hajmi278.14 Kb.
    #56090
    1   2   3
    Bog'liq
    10-ma’ruza. Konteynerli tiplar va ularning qo’llanilishi. Kontey
    7-sinf o\'zbekiston tarixi test, дафтар усти, ахборот, PERLA TOMATO, Informacionnyj list 1657746222398, inson va jamiyat, Aloqa xati, ipoteka, Asadbek Azizqulov Fizika, Sherzod dasturlash, dasturlash 4-amaliy topshiriq
     
     
    #ifndef ARRAYINT_H 
    #define ARRAYINT_H 

    #include  

    class ArrayInt 

    private: 
    int m_length; 
    int *m_data; 

    public: 
    ArrayInt(): 
    m_length(0), m_data(nullptr) 



    m_length=0; 
    m_data=nullptr; 


    ArrayInt(int length): 
    m_length(length) 

    assert(length >= 0); 

    if (length > 0) 
    m_data = new int[length]; 
    else 
    m_data = nullptr; 


    ~ArrayInt() 

    delete[] m_data; 


    void erase() 

    delete[] m_data; 
    // Chiqishda osilgan ko'rsatgich bo'lmasligi uchun m_data ni nullptr ga o'rnating
    m_data = nullptr; 
    m_length = 0; 


    int& operator[](int index) 

    assert(index >= 0 && index < m_length); 
    return m_data[index]; 


    int getLength() { return m_length; } 
    }; 

    #endif 
     
     
    Endi biz foydalanishimiz mumkin bo'lgan ArrayInt sinfiga egamiz. Biz ma'lum o'lchamdagi 
    massivni ajratishimiz va elementlarning qiymatlarini olish yoki o'zgartirish uchun [] operatoridan 
    foydalanishimiz mumkin. 
    Biroq, ArrayInt bilan biz qila olmaydigan yana bir nechta narsa bor. Bular massivning 
    avtomatik oʻlchamini oʻzgartirish, elementlarni qoʻshish/oʻchirish va elementlarni saralash. 
    Birinchidan, massivni o'lchamini o'zgartirish mumkin bo'lsin. Buning uchun ikki xil 
    funksiya yozamiz. Birinchi funktsiya qayta reallocate(), massiv hajmi o'zgartirilganda, u barcha 
    mavjud elementlarni yo'q qiladi (bu tez). Ikkinchi funktsiya resize(), massiv o'lchamini 
    o'zgartirganda, u barcha mavjud elementlarni saqlab qoladi (bu sekin). 
    // reallocate () funksiyasi massiv hajmini o'zgartiradi.


    //Massiv ichidagi barcha mavjud elementlar yo'q qilinadi.
    //Jarayon tez
    void reallocate(int newLength) 

    // Massiv ichidagi barcha mavjud elementlarni olib tashlash 
    erase(); 
    // Agar massivimiz bo'sh bo'lishi kerak bo'lsa, biz bu yerga qaytamiz 
    if (newLength <= 0) 
    return; 
    // Keyin biz yangi elementlarni tanlashimiz kerak 
    m_data = new int[newLength]; 
    m_length = newLength; 

    // resize() funksiyasi massiv hajmini o'zgartiradi. Barcha mavjud elementlar saqlanib 
    qoladi. Jarayon sekin 
    void resize(int newLength) 

    // Agar massiv kerakli uzunlikka ega bo'lsa, return bajaring 
    if (newLength == m_length) 
    return; 
    // Agar massivni bo'sh qilish kerak bo'lsa, buni bajaring va keyin return ni bajaring 
    if (newLength <= 0) 

    erase(); 
    return; 

    // Endi, deylik newLength kamida bitta elementga ega. Quyidagi harakatlar ketma-ketligi 
    amalga oshiriladi: 
    // 1. Yangi massivni ajrating. 
    // 2. Mavjud massivdagi elementlarni yangi tanlangan massivimizga nusxalash. 
    // 3. Eski massivni yo'q qiling va yangi massivga ishora qilish uchun m_data buyrug'ini 
    bering. 
    int *data = new int[newLength]; 
    // Keyin yangi massivga nusxalanadigan elementlar sonini aniqlashimiz kerak. 
    // Massivlarning kichikroq qismidagi qancha elementlar bo'lsa, shuncha ko'p elementni 
    nusxalashimiz kerak 
    if (m_length > 0) 

    int elementsToCopy = (newLength > m_length) ? m_length : newLength; 
    // Elementlarni birma-bir nusxalash 
    for (int index=0; index < elementsToCopy ; ++index) 
    data[index] = m_data[index]; 

    // Eski massivni o'chirib tashlang, chunki bizga endi kerak emas 
    delete[] m_data; 


    // Va eskisini o'rniga yangisini ishlating! E'tibor bering, m_data bizning yangi dinamik 
    ravishda ajratilgan massivimiz ko'rsatgan manzilga ishora qiladi. 
    // Ma'lumotlar dinamik ravishda ajratilganligi sababli, ular ko'lamdan chiqib ketganda 
    yo'q qilinmaydi 
    m_data = data; 
    m_length = newLength; 

    Ko’rib turganingizdek bu oson jarayon emas. Ko'pgina konteyner massivi sinflarining 
    funksionalligi shu erda tugaydi. Ammo, agar siz elementlarni qo'shish / o'chirish qobiliyatini 
    qanday amalga oshirishni ko'rishni istasangiz, endi biz buni ko'rib chiqamiz. Quyidagi ikkita 
    algoritm resize() funksiyasiga juda o'xshash: 
    void insertBefore(int value, int index) 

    // O'tkazilgan indeksning to'g'riligini tekshirish 
    assert(index >= 0 && index <= m_length); 
    // Eski massivdan bir element kattaroq yangi massiv yarating 
    int *data = new int[m_length+1]; 
    // Barcha elementlarni indeksgacha nusxalash 
    for (int before=0; before < index; ++before) 
    data[before] = m_data[before]; 
    // Bizning yangi elementimizni yangi massivimizga joylashtiring 
    data [index] = value; 
    // Kiritilgan elementdan keyin barcha qiymatlarni nusxalash 
    for (int after=index; after < m_length; ++after) 
    data[after+1] = m_data[after]; 
    // Eski massivni o'chiring va uning o'rniga yangi massivdan foydalaning 
    delete[] m_data; 
    m_data = data; 
    ++m_length; 

    void remove(int index) 

    // O'tkazilgan indeksning to'g'riligini tekshiring 
    assert(index >= 0 && index < m_length); 
    // Agar bu massivning oxirgi elementi bo'lsa, u holda massivni bo'sh qilamiz va return 
    if (m_length == 1) 

    erase(); 
    return; 

    // Eski massivimizdan bir element kichikroq yangi massiv yarating 
    int *data = new int[m_length-1]; 


    // Barcha elementlarni indeksgacha nusxalash 
    for (int before=0; before < index; ++before) 
    data[before] = m_data[before]; 
    // O'chirilgan elementdan keyin barcha qiymatlarni nusxalash 
    for (int after=index+1; after < m_length; ++after ) 
    data[after-1] = m_data[after]; 
    // Eski massivni o'chiring va uning o'rniga yangi massivdan foydalaning 
    delete[] m_data; 
    m_data = data; 
    --m_length; 

    // Qulaylik uchun bir nechta qo'shimcha funktsiyalar 
    void insertAtBeginning(int value) { insertBefore(value, 0); } 
    void insertAtEnd(int value) { insertBefore(value, m_length); } 
    Mana bizning ArrayInt konteyner sinfimiz. 
    ArrayInt.h: 
    #ifndef ARRAYINT_H 
    #define ARRAYINT_H 
    #include  // для assert() 
    class ArrayInt 

    private: 
    int m_length; 
    int *m_data; 
    public: 
    ArrayInt(): 
    m_length(0), m_data(nullptr) 


    ArrayInt(int length): 
    m_length(length) 

    assert(length >= 0); 
    if (length > 0) 
    m_data = new int[length]; 
    else 
    m_data = nullptr; 

    ~ArrayInt() 



    delete[] m_data; 

    void erase() 

    delete[] m_data; 
    // Здесь нужно указать m_data значение nullptr, чтобы на выходе не было висячего 
    указателя 
    m_data = nullptr; 
    m_length = 0; 

    int& operator[](int index) 

    assert(index >= 0 && index < m_length); 
    return m_data[index]; 

    // Функция reallocate() изменяет размер массива. Все существующие элементы 
    внутри массива будут уничтожены. Процесс быстрый 
    void reallocate(int newLength) 

    // Удаляем все существующие элементы внутри массива 
    erase(); 
    // Если наш массив должен быть пустым, то выполняем возврат здесь 
    if (newLength <= 0) 
    return; 
    // Затем выделяем новые элементы 
    m_data = new int[newLength]; 
    m_length = newLength; 

    // Функция resize() изменяет размер массива. Все существующие элементы 
    сохраняются. Процесс медленный 
    void resize(int newLength) 

    // Если массив нужной длины, то выполняем return 
    if (newLength == m_length) 
    return; 
    // Если нужно сделать массив пустым, то делаем это и затем выполняем return 
    if (newLength <= 0) 

    erase(); 
    return; 

    // Теперь предположим, что newLength состоит, по крайней мере, из одного 
    элемента. Выполняется следующий алгоритм действий: 
    // 1. Выделяем новый массив. 


    // 2. Копируем элементы из существующего массива в наш только что 
    выделенный массив. 
    // 3. Уничтожаем старый массив и даем команду m_data указывать на новый 
    массив. 
    // Выделяем новый массив 
    int *data = new int[newLength]; 
    // Затем нам нужно разобраться с количеством копируемых элементов в новый 
    массив. 
    // Нам нужно скопировать столько элементов, сколько их есть в меньшем из 
    массивов 
    if (m_length > 0) 

    int elementsToCopy = (newLength > m_length) ? m_length : newLength; 
    // Поочередно копируем элементы 
    for (int index=0; index < elementsToCopy ; ++index) 
    data[index] = m_data[index]; 

    // Удаляем старый массив, так как он нам уже не нужен 
    delete[] m_data; 
    // И используем вместо старого массива новый! Обратите внимание, m_data 
    указывает на тот же адрес, на который указывает наш новый динамически выделенный 
    массив. 
    // Поскольку данные были динамически выделены, то они не будут уничтожены, 
    когда выйдут из области видимости 
    m_data = data; 
    m_length = newLength; 

    void insertBefore(int value, int index) 

    // Проверка корректности передаваемого индекса 
    assert(index >= 0 && index <= m_length); 
    // Создаем новый массив на один элемент больше старого массива 
    int *data = new int[m_length+1]; 
    // Копируем все элементы аж до index 
    for (int before=0; before < index; ++before) 
    data [before] = m_data[before]; 
    // Вставляем наш новый элемент в наш новый массив 
    data [index] = value; 
    // Копируем все значения после вставляемого элемента 
    for (int after=index; after < m_length; ++after) 
    data[after+1] = m_data[after]; 


    // Удаляем старый массив и используем вместо него новый массив 
    delete[] m_data; 
    m_data = data; 
    ++m_length; 

    void remove(int index) 

    // Проверка на корректность передаваемого индекса 
    assert(index >= 0 && index < m_length); 
    // Если это последний элемент массива, то делаем массив пустым и выполняем 
    return 
    if (m_length == 1) 

    erase(); 
    return; 

    // Cоздаем новый массив на один элемент меньше нашего старого массива 
    int *data = new int[m_length-1]; 
    // Копируем все элементы аж до index 
    for (int before=0; before < index; ++before) 
    data[before] = m_data[before]; 
    // Копируем все значения после удаляемого элемента 
    for (int after=index+1; after < m_length; ++after ) 
    data[after-1] = m_data[after]; 
    // Удаляем старый массив и используем вместо него новый массив 
    delete[] m_data; 
    m_data = data; 
    --m_length; 

    // Несколько дополнительных функций просто для удобства 
    void insertAtBeginning(int value) { insertBefore(value, 0); } 
    void insertAtEnd(int value) { insertBefore(value, m_length); } 
    int getLength() { return m_length; } 
    }; 
    #endif 
    Edi dasturni testdan o’tkazamiz 
    #include  
    #include "ArrayInt.h" 
    int main() 



    // Объявляем массив с 10 элементами 
    ArrayInt array(10); 
    // Заполняем массив числами от 1 до 10 
    for (int i=0; i<10; i++) 
    array[i] = i+1; 
    // Изменяем размер массива до 7 элементов 
    array.resize(7); 
    // Вставляем число 15 перед элементом с индексом 4 
    array.insertBefore(15, 4); 
    // Удаляем элемент с индексом 5 
    array.remove(5); 
    // Добавляем числа 35 и 50 в конец и в начало 
    array.insertAtEnd(35); 
    array.insertAtBeginning(50); 
    // Выводим все элементы массива 
    for (int j=0; jstd::cout << array[j] << " "; 
    return 0; 

    Natija: 
    50 1 2 3 4 15 6 7 35 
    Konteyner sinflarini yozish biroz qiyin bo'lishi mumkin bo'lsa-da, yaxshi xabar shundaki, 
    ularni faqat bir marta yozishingiz kerak. Konteyner klassi ishga tushirilgandan so'ng, uni istalgan 
    joyda qo'shimcha kodlash/kodlash harakatlarisiz qayta ishlatishingiz mumkin. 
    Shuni ham ta'kidlash joizki, ArrayInt konteyner sinfimiz asosiy ma'lumotlar turini (int) o'z 
    ichiga olsa ham, biz maxsus ma'lumotlar turidan ham osonlikcha foydalanishimiz mumkin. 
    Eslatma: Agar C ++ standart kutubxonasi sinfi sizning ehtiyojlaringizga to'liq javob bersa, 
    o'z konteyner sinfingizni yozish o'rniga undan foydalaning. Masalan, ArrayInt o'rniga std :: vektor 
     dan foydalanish yaxshidir, chunki std :: vektor  ilovasi ko'p yillar davomida sinovdan 
    o'tgan/tasdiqlangan, samarali va C sinfidagi boshqa sinflar bilan yaxshi ishlaydi. ++ Standart 
    kutubxona. Ammo C ++ standart kutubxonasidan sinflardan foydalanish har doim ham imkoni 
    bo'lmasligi mumkinligi sababli, siz o'zingizning konteyner sinflaringizni qanday yaratishni 
    allaqachon bilasiz. 
     
     

    Download 278.14 Kb.
    1   2   3




    Download 278.14 Kb.
    Pdf ko'rish

    Bosh sahifa
    Aloqalar

        Bosh sahifa



    10-ma’ruza. Konteynerli tiplar va ularning qo’llanilishi. Konteyner sinflar va iteratorlar

    Download 278.14 Kb.
    Pdf ko'rish