• İki boyutlu dinamik dizi c. Tek Boyutlu Dinamik Diziler

    // 10 elemanlı iki boyutlu bir dinamik dizinin bildirimi:

    float **ptrarray = yeni float* ; // dizideki iki dizi

    için (int say = 0; say< 2; count++)

    ptrarray = yeni kayan nokta; // ve beş sütun

    // burada ptrarray, dizi için ayrılan bellek alanına işaretçi dizisidir gerçek sayılar kayan tip

    İlk olarak, bir float **ptrarray ikinci dereceden işaretçi bildirilir; bu, bir float* işaretçileri dizisine atıfta bulunur; burada dizi boyutu ikidir . Bundan sonra, for döngüsünde, dizinin her satırı, hat 2 bellek beş öğe için ayrılmıştır. Sonuç olarak, iki boyutlu bir dinamik dizi ptrarray elde edilir.İki boyutlu bir dinamik dizi için ayrılan belleği boşaltmaya bir örnek düşünelim.

    // iki boyutlu bir dinamik dizi için ayrılan belleğin serbest bırakılması:

    için (int say = 0; say< 2; count++)

    ptraray'i sil;

    // burada 2, dizideki satır sayısıdır

    #katmak
    #katmak
    #katmak
    geçersiz ana()
    {

    int*a; // diziye işaretçi

    sistem("chcp 1251");

    scanf("%d", &n);

    scanf("%d", &m);

    // Bellek tahsisi

    a = (int*) malloc(n*m*sizeof(int));

    // Dizi öğelerini girin

    için(i=0; ben

    için(j=0;j

    printf("a[%d][%d] = ", i, j);

    scanf("%d", (a+i*m+j));

    // Dizi öğelerini göster

    için(i=0; ben

    için(j=0;j

    printf("%5d ", *(a+i*m+j)); // bir dizi öğesi için 5 karakterlik boşluk

    getchar(); getchar();
    }

    Yürütme sonucu

    Satır sayısını girin: 3

    Sütun sayısını girin: 4

    Bir dizi işaretçi kullanarak, iki boyutlu bir dizi için belleği dinamik olarak ayırmanın başka bir yolu da vardır. Bunun için ihtiyacınız var:
    - bir işaretçi dizisi için bir RAM bloğu tahsis edin;
    - istenen matrisin satırları olan tek boyutlu diziler için RAM blokları tahsis edin;
    - dizelerin adreslerini bir işaretçi dizisine yazın.

    Malloc () işlevi, dinamik olarak ayrılmış bir bellek alanından ayrılan boyuttaki bir bellek alanının ilk baytına bir işaretçi döndürür. Dinamik bellek alanında yeterli bellek yoksa boş gösterici döndürülür.

    #katmak
    #katmak
    #katmak
    geçersiz ana()
    {

    int **a; // işaretçiden dizgeye işaretçi

    sistem("chcp 1251");

    printf("satir sayisini giriniz:");

    scanf("%d", &n);

    printf("Sütun sayisini giriniz: ");

    scanf("%d", &m);

    // Dizilere işaretçiler için bellek ayır

    a = (int**)malloc(n*sizeof(int*));

    // Dizi öğelerini girin

    için(i=0; ben

    // Dizeleri depolamak için bellek tahsis edin

    a[i] = (int*)malloc(m*sizeof(int));

    için(j=0;j

    printf("a[%d][%d] = ", i, j);

    scanf("%d", &a[i][j]);

    // Dizi öğelerini göster

    için(i=0; ben

    için(j=0;j

    printf("%5d", a[i][j]); // bir dizi öğesi için 5 karakterlik boşluk

    ücretsiz(a[i]); // dize için bellek boşaltma

    getchar(); getchar();
    }

    Programın yürütülmesinin sonucu önceki duruma benzer.

    Dize işaretçileri için dinamik bellek ayırmayı kullanarak boş diziler ayırabilirsiniz. özgür satırlarının boyutu farklı olabilen iki boyutlu bir dizi (matris) denir. Ücretsiz bir dizi kullanmanın avantajı, mümkün olan en uzun diziyi barındırmak için çok fazla bilgisayar belleği ayırmanız gerekmemesidir. Aslında, serbest bir dizi, tek boyutlu veri dizilerine işaret eden tek boyutlu bir dizidir.

    İşaretçiler.

    İşaretçi, değeri verilerin bulunduğu adres olan bir değişkendir. Adres, verilerin bulunduğu veya bulunduğu bellek konumunun numarasıdır.

    SI'daki veri türüne göre işaretçiler ayrılır:

    Yazılı bir işaretçi, belirli bir türdeki (sistem veya kullanıcı) verilerin adresini içeren bir işaretçidir.

    Türlenmemiş bir işaretçi, tanımlanmamış bir türdeki (yalnızca bir adres) verinin adresini içeren bir işaretçidir.

    İşaretçi bildirimi;

    İşaretçiyi ayarlamak;

    işaretçide bulunan değere erişme. C dilinde bir işaretçinin bildirimi (açıklaması) aşağıdaki gibidir:

    *isim [=değer] yazın;

    SI'daki bir işaretçi, atama işareti aracılığıyla karşılık gelen değeri belirterek bildirim üzerine başlatılabilir. Bu değer, aşağıdaki biçimlerden birinde yazılmış bir adres olmalıdır:

    Boş değer (NULL tanımlayıcısı);

    Başka bir işaretçi;

    Değişken adres (adres alma işlemi ile);

    İşaretçi aritmetiğini temsil eden bir ifade;

    Dinamik belleğin tahsisinden kaynaklanan adres.

    #katmak

    int var; // normal tamsayı değişkeni

    int *ptrVar; // tamsayı işaretçisi (ptrVar, int türünde bir değişkene başvuracağı için int türünde olmalıdır)

    ptrVar = // işaretçiye var değişkeninin değerinin bulunduğu bellekteki hücrenin adresi atanır

    scanf("%d", &var); // klavyeden girilen değeri var değişkenine koy

    printf("%d\n", *ptrVar); // işaretçi ile çıkış değeri

    Yürütme sonucu: 6 6

    Ders numarası 3.

    fonksiyonlar.

    Bir işlev, belirli bir eylemi veya eylemler grubunu gerçekleştiren sözdizimsel olarak ayırt edilen adlandırılmış bir program modülüdür. Her işlevin kendi arayüzü ve uygulaması vardır. İşlev arabirimi - işlevin adını, parametrelerinin listesini ve dönüş değerinin türünü gösteren işlev başlığı.

    C dilinde bir fonksiyonun tanımı, diğer fonksiyonların tanımı dışında programın herhangi bir yerinde gerçekleştirilir ve üç unsurdan oluşur:

    1. işlev prototipi;

    2. işlev başlığı;

    3. işlev gövdesi.

    Bir işlev prototipi, arabirimi belirli bir prototipe karşılık gelen bazı işlevleri bildirmeyi amaçlayan işlev açıklamasının isteğe bağlı bir parçasıdır.Bir prototip bildirimi aşağıdaki forma sahiptir:

    Tip adı (resmi parametre tiplerinin listesi);

    Fonksiyon parametreleri, çağrıldığında fonksiyona iletilen değerlerdir.

    İşlev başlığı - işlevin aşağıdakileri içeren arayüz bölümünün açıklaması: dönüş türü, işlev adı ve işlevin resmi parametrelerinin bir listesi. İşlev başlığı bildirimi sözdizimi:

    Tip adı (resmi parametrelerin listesi)

    İşlev başlığı örnekleri:

    int func(int i, çift x, çift y)

    geçersiz işlev(int ind, char *dize)

    Çift işlev (geçersiz)

    Bir fonksiyonun gövdesi, fonksiyon çağrıldığında yürütülen program kodunu içeren bir uygulama parçasıdır. İşlev gövdesi her zaman işlev başlığından hemen sonra gelir (ayrılamazlar) ve kaşlı ayraçlar içine alınır.

    Bir sayının faktöriyelini hesaplamak için SI'da bir fonksiyonun uygulanması.

    çift ​​faktöriyel(işaretsiz);

    Çift faktöriyel(işaretsiz sayı)

    çift ​​gerçek = 1.0;

    For(işaretsiz i=1;i<=num;i++)

    Gerçek *= (çift)i;

    dönüş gerçeği;

    yapılar.

    Yapı, bellekte sıralanmış çeşitli türlerdeki öğelerden oluşan karmaşık bir veri türüdür. Yapıdaki her öğenin kendi adı vardır ve alan olarak adlandırılır.

    Bir yapının SI bildirimi:

    Yapı [tür adı]

    Alan_1;

    Alan_2;

    Alan_N;

    ) [değişken listesi];

    Yapı alanı bildirimi yalnızca başlatma olmadan mümkündür. Bir yapının açıklamasında birbirini takip eden birkaç alan aynı tipe sahipse, aynı tipteki birkaç değişkeni bildirmek için sözdizimi bunları tanımlamak için kullanılabilir.

    Dosyalar.

    Dosya, bir depolama ortamındaki adlandırılmış bir veri alanıdır. Dosya türleri ("SI" diline göre):
    metin;
    ikili.
    Dosyalar üzerinde gerçekleştirilen temel işlemler:
    1. Dosyaları açma.
    2. Veri okuma ve yazma.
    3. Dosyaları kapatma.

    Ek işlemler:
    1. Dosyada gezinme.
    2. Dosyalarla çalışma hatalarını işleme.
    3. Dosyaları silin ve yeniden adlandırın.
    4. Değişkenin açıklaması

    Açılış modları SI içeren dosyalar

    Akış yönlendirme
    DOSYA * freopen(const char *dosyaadı, const char *mode, DOSYA *akış);

    İşlev şunu döndürür:
    Dosya işaretçisi - her şey yolunda,
    NULL bir yeniden tanımlama hatasıdır.

    bir dosyayı kapatma
    int fclose(DOSYA *akış);

    İşlev şunu döndürür:
    0 - dosya başarıyla kapatıldı.
    1 - Dosya kapatılırken bir hata oluştu.

    Dosya sonu kontrolü
    intfeof(DOSYA*akış);
    akış, açık bir dosyanın işaretçisidir.

    İşlev şunu döndürür:
    0 - dosyanın sonuna henüz ulaşılmamışsa.
    !0 – Dosyanın sonuna ulaşıldı.

    Metin dosyalarını açma
    İkinci parametre ayrıca t karakterini belirtir (isteğe bağlı):
    rt, ağırlık, en, rt+, ağırlık+, en+

    Bir metin dosyasından okuma

    Biçimlendirilmiş Okuma
    int fscanf(DOSYA *akış, const char *biçim, ...);

    İşlev şunu döndürür:
    >0 – başarıyla okunan değişken sayısı,
    0 - değişkenlerin hiçbiri başarıyla okunmadı,
    EOF - hata veya dosyanın sonuna ulaşıldı.
    satır okuma

    İşlev şunu döndürür:
    arabellek - her şey yolunda,
    satır okuma
    char * fgets(char * tampon, int maxlen, DOSYA *akış);

    İşlev şunu döndürür:
    arabellek - her şey yolunda,
    NULL - hata veya dosya sonuna ulaşıldı.
    karakter okuma
    int fgetc(DOSYA *akış);
    İşlev şunu döndürür:
    karakter kodu - her şey yolundaysa,
    EOF - bir hata oluşursa veya dosyanın sonuna ulaşılırsa.
    Akışa geri bir karakter koymak
    int ungetc(int c, DOSYA *akış);
    İşlev şunu döndürür:
    karakter kodu - her şey başarılıysa,
    EOF Bir hata oluştu.

    metne yaz SI'daki dosya

    Biçimlendirilmiş çıktı
    int fprintf(DOSYA *akış, const char *biçim, ...);
    İşlev şunu döndürür:
    yazılan karakter sayısı - her şey yolundaysa,
    negatif bir değer - bir hata ise.
    Dize girişi
    int fputs(const char *dize, DOSYA *akış);
    İşlev şunu döndürür:
    yazılı karakter sayısı - her şey yolunda,
    EOF Bir hata oluştu.
    Sembol girişi
    int fputc(int c, DOSYA *akış);
    İşlev şunu döndürür:
    yazılan karakterin kodu - her şey yolunda,
    EOF Bir hata oluştu.
    İkili dosyaları açma
    İkinci parametre ayrıca b karakterini (zorunlu) belirtir: rb, wb, ab, rb+, wb+, ab+
    İkili dosyalardan okuma
    size_t fread(void *arabellek, size_t boyut, size_t num,FILE *akış);
    İşlev, okunan blok sayısını döndürür. Num'dan küçükse, bir hata oluştu veya
    dosyanın sonu.

    Bir ikili dosyaya yazma
    size_t fwrite(const void *arabellek, size_t boyut, size_t sayı, DOSYA *akış);
    İşlev, yazılan blok sayısını döndürür. Num'dan küçükse, bir hata oluştu.

    dosya gezintisi

    Bir dosyadaki geçerli ofseti okumak:
    uzun int ftell(DOSYA *akış);
    Bir dosyadaki geçerli ofseti değiştirme:
    int fseek(DOSYA *akış, uzun int ofset, int kaynak);

    SEEK_SET (0) - dosyanın başından itibaren.
    SEEK_CUR (1) - geçerli konumdan.
    SEEK_END (2) - dosyanın sonundan.
    İşlev şunu döndürür:
    0 - her şey yolunda,
    !0 - bir hata oluştu.
    Bir dosyanın başına git:
    geçersiz geri sarma(DOSYA *akış);
    Bir dosyadaki geçerli konumu okumak:
    int fgetpos(DOSYA *akış, fpos_t *pos);
    Dosyadaki geçerli konumun ayarlanması:
    int fsetpos(DOSYA *akış, const fpos_t *pos);
    İşlevler döndürür:
    0 - her şey başarılı,
    !0 - bir hata oluştu.
    fpos_t yapısı:
    typedef yapı fpos_t (
    uzun süre kapalı;
    mbstate_t wstate;
    ) fpos_t;

    Hata bayrağını alma:
    int ferror(DOSYA *akış);
    Bir hata oluşursa işlev sıfır olmayan bir değer döndürür.
    Hata sıfırlama işlevi:
    void clearerr(DOSYA *akış);
    Hata mesajı çıkış fonksiyonu:
    geçersiz hata(const char *dize);

    ara belleğe alma

    Tampon temizleme işlevi:
    int floş(DOSYA *akış);
    İşlev şunu döndürür:
    0 - her şey yolunda.
    EOF Bir hata oluştu.
    Tampon yönetimi işlevi:
    geçersiz setbuf(FILE *stream, char *buffer);

    BUFSIZ boyutunda bir arabellek oluşturur. Bir akışa giriş veya çıkıştan önce kullanılır.

    Geçici dosyalar

    Geçici bir dosya oluşturma işlevi:
    DOSYA * tmp dosyası(geçersiz);
    wb+ modunda geçici bir dosya oluşturur. Dosya kapatıldıktan sonra, ikincisi otomatik olarak silinir.
    Geçici dosya adı oluşturma işlevi:
    char *tmpnam(char *arabellek);

    Sil ve yeniden adlandır

    Dosya silme işlevi:
    int remove(const char *dosyaadı);
    Dosya yeniden adlandırma işlevi:
    int rename(const char *fname, const char *nname);
    İşlevler döndürür:
    0 - başarı durumunda,
    !0 Aksi takdirde.

    Ders numarası 4.

    Yığın.

    Yığın, kuyruğun bir nevi tersidir çünkü son giren ilk çıkar (LIFO) esasına göre çalışır. Bir yığın görselleştirmek için bir tabak yığınını düşünün. Masanın üzerindeki ilk tabak en son kullanılacak ve en üste konulan son tabak ilk önce kullanılacaktır. Yığınlar, derleyiciler ve yorumlayıcılar da dahil olmak üzere sistem yazılımında sıklıkla kullanılır.

    Yığınlarla çalışırken, bir öğeyi ekleme ve çıkarma işlemleri temeldir. Bu işlemlere geleneksel olarak "yığının üzerine itme" (itme) ve "yığının dışına çıkma" (pop) adı verilir. Bu nedenle, bir yığın uygulamak için iki işlev yazmanız gerekir: yığına bir değer iten push() ve yığından bir değer iten pop(). Ayrıca stack olarak kullanılacak bir hafıza alanı ayırmak gerekiyor. Bu amaçla, dinamik bellek ayırma için sağlanan C dili işlevlerini kullanarak bir dizi ayırabilir veya dinamik olarak bir bellek parçası ayırabilirsiniz. Kuyrukta olduğu gibi, alma işlevi listeden bir öğe alır ve başka bir yerde depolanmamışsa kaldırır. Bir tamsayı dizisinde çalışan push() ve pop() işlevlerinin genel biçimi aşağıdadır. Dizinin altında yatan veri türü değiştirilerek farklı türdeki veri yığınları düzenlenebilir.

    intto=0; /* yığının başı */

    /* Elemanı yığının üzerine itin. */

    geçersiz itme(in i)

    if(tos >= MAKS) (

    printf("Yığın dolu\n");

    /* Yığının en üst elemanını al. */

    eğer (tos< 0) {

    printf("Yığın boş\n");

    dönüş yığını;

    tos ("yığının tepesi") değişkeni, yığının tepesinin indeksini içerir. Bu işlevleri uygularken, yığının dolu veya boş olduğu durumları hesaba katmak gerekir. Bizim durumumuzda, boş bir yığının işareti tos sıfıra eşittir ve yığın taşmasının işareti, tos'ta öyle bir artıştır ki, değeri dizinin son hücresinin ötesinde bir yere işaret eder.

    Yığın örneği.

    Yığın, sabit boyutlu bir diziye değil, dinamik olarak ayrılmış belleğe yerleştirilecektir. Bu kadar basit bir örnekte dinamik bellek tahsisinin kullanılması gerekli olmasa da, yığın verilerini depolamak için dinamik belleğin nasıl kullanılacağını göreceğiz.

    /* Dört adımlı basit bir hesap makinesi. */

    #katmak

    #katmak

    int*p; /* bellek alanını boşaltmak için işaretçi */

    int *to; /* yığının tepesine işaretçi */

    int*bos; /* yığının en altına işaretçi */

    geçersiz itme(int i);

    p = (int *) malloc(MAX*sizeof(int)); /* yığın belleği al */

    printf("Bellek yerlestirme hatasi\n");

    bos=p+MAKS-1;

    printf("Dört Adım Hesaplayıcı\n");

    printf("Çikmak için "q" tusuna basin\n");

    printf("%d\n", a+b);

    printf("%d\n", b-a);

    printf("%d\n", b*a);

    printf("0'a Böl.\n");

    printf("%d\n", b/a);

    case ".": /* yığının en üstündeki içeriği göster */

    printf("Yığının en üstündeki geçerli değer: %d\n", a);

    ) while(*s != "q");

    /* Elemanı yığına itiyoruz. */

    geçersiz itme(in i)

    eğer(p > bos) (

    printf("Yığın dolu\n");

    /* Yığından en üstteki elemanı al. */

    mümkünse< tos) {

    printf("Yığın boş\n");

    Sıra.

    Sıra, ilk giren ilk çıkar temelinde işlenen doğrusal bir bilgi listesidir; bu ilke (ve bir veri yapısı olarak sıra) bazen FIFO olarak da adlandırılır. Bu, kuyruğa yerleştirilen ilk öğenin kuyruktan çıkarılacak ilk öğe olacağı, kuyruğa yerleştirilen ikinci öğenin alınacak ikinci öğe olacağı vb. anlamına gelir. Kuyrukla çalışmanın tek yolu budur; bireysel öğelere rastgele erişime izin verilmez.

    Kuyruğun nasıl çalıştığını hayal etmek için iki işlevi tanıtalım: qstore() ve qretrieve() ("mağaza" - "kaydet", "al" - "al" dan). qstore() işlevi, sıranın sonuna bir öğe yerleştirir ve qretrieve() işlevi, bir öğeyi sıranın başından kaldırır ve değerini döndürür. Tablo, bu tür işlemlerin bir dizisinin etkisini göstermektedir.

    Aksiyon Kuyruk içeriği
    qstore(A) A
    qstore(B) AB
    qstore(C) A B C
    qretrieve() A'yı döndürür M.Ö
    qstore(D) B C D
    qretrive() B'yi döndürür CD
    qretrieve() C'yi döndürür D

    Getirme işleminin, başka bir yerde depolanmadığı sürece bir öğeyi sıradan kaldırdığını ve yok ettiğini unutmayın. Bu nedenle, tüm öğeleri çıkardıktan sonra sıra boş olacaktır.

    Programlamada, kuyruklar birçok sorunu çözmek için kullanılır. Bu tür problemlerin en popüler türlerinden biri simülasyondur. Kuyruklar, işletim sistemi görev planlayıcılarında ve G/Ç arabelleğinde de kullanılır.

    /* Mini olay planlayıcı */

    #katmak

    #katmak

    #katmak

    #katmak

    char *p, *qretrieve(geçersiz);

    void enter(void), qstore(char *q), gözden geçir(void), delete_ap(void);

    for(t=0; t< MAX; ++t) p[t] = NULL; /* иницилизировать массив

    boş işaretçiler */

    printf("Gir (E), Listele (L), Sil (R), Çik (Q): ");

    *s = üst(*s);

    /* Kuyruğa yeni bir toplantı ekle. */

    geçersiz giriş (geçersiz)

    printf("Randevu %d'yi giriniz: ", spos+1);

    if(*s==0) ​​​​break; /* yazma yapılmadı */

    p = (char *) malloc(strlen(s)+1);

    printf("Bellek yetersiz.\n");

    if(*s) qstore(p);

    /* Kuyruğun içeriğini görüntüle. */

    geçersiz inceleme (geçersiz)

    for(t=rpos; t< spos; ++t)

    printf("%d.%s\n", t+1, p[t]);

    /* Toplantıyı sıradan kaldır. */

    geçersiz sil_ap(geçersiz)

    if((p=qretrieve())==NULL) dönüş;

    printf("%s\n", p);

    /* Randevu ekle. */

    geçersiz qstore(char*q)

    printf("Liste Dolu\n");

    /* Randevuyu al. */

    char *qretrive(geçersiz)

    if(rpos==spos) (

    printf("Bir daha karsilasmak yok.\n");

    dönüş s;

    Liste.

    tek bağlantılı bir döngüsel liste, özyinelemeli bir yapı bildirimidir veya daha doğrusu, tip yapısının kendisinde ona bir işaretçidir:

    int veri;//veri alanı

    s *sonraki;//sonraki eleman

    ) *first,*curr;//ilk ve geçerli eleman

    başlatma:

    ilk->sonraki=curr;

    ilk elemanı almak için first->data kullanın

    yeni bir eleman eklemek için: curr->next=new s;

    curr=curr->sonraki;//sonuncuya git

    ve örneğin 50 öğeyi liste üzerinde yinelenen bir döngüden geçirmek için:

    curr=ilk;//birinciye atla

    for(int i=0;i<50;i++)

    if(curr->sonraki!=BOŞ)

    curr=curr->sonraki;


    Benzer bilgiler.


    Genellikle, belirli bir değişken için gereken bellek miktarı, bu değişken bildirilerek derleme işleminden önce ayarlanır. Boyutu önceden bilinmeyen bir değişken oluşturmak gerekirse, dinamik bellek kullanılır. Rezervasyon Ve serbest bırakmak C++ programlarında bellek kaybı herhangi bir zamanda meydana gelebilir. İşlemler devam ediyor dağıtım Hafıza iki şekilde:

    • işlevi kullanma alışveriş merkezi, kaltak, yeniden yerleştirme Ve özgür;
    • operatör aracılığıyla yeni Ve silmek.

    İşlev alışveriş merkezi rezervler belirtilen nesneyi tutmak için bitişik bir bellek hücresi bloğu ve bu bloktaki ilk hücreye bir işaretçi döndürür. İşlev çağrısı şöyle görünür:

    geçersiz *malloc(boyut);

    Burada boyut- ayrılan bellek alanının boyutunu bayt cinsinden belirten işaretsiz bir tamsayı değeri. Bellek rezervasyonu başarılıysa, işlev şu türde bir değişken döndürür: geçersiz*, istenen herhangi bir işaretçi türüne dönüştürülebilir.

    İşlev - kaltak bellek ayırmak için de kullanılır. Aşağıdaki giriş, vurgulanacağı anlamına gelir sayı tarafından elemanlar boyut bayt.

    void *calloc(nime, boyut);

    Bu işlev, seçime bir işaretçi döndürür veya HÜKÜMSÜZ bellek ayırmak mümkün olmadığında. Fonksiyonun bir özelliği, seçilen tüm elemanların sıfırlanmasıdır.

    İşlev yeniden yerleştirmeyeniden boyutlandırırÖnceden ayrılmış bellek. Ona şöyle hitap ederler:

    char *realloc (geçersiz *p, boyut);

    Burada P- yeniden boyutlandırılacak bellek alanına bir işaretçi boyut. İşlev sonucunda bellek alanının adresi değişirse, sonuç olarak yeni adres döndürülür. İlk parametrenin gerçek değeri ise HÜKÜMSÜZ, ardından işlev yeniden yerleştirme işlevle aynı şekilde çalışır alışveriş merkezi, yani, bir boyuta sahip bir bellek parçası ayırır boyut bayt.

    Ayrılan belleği boşaltmak için işlevi kullanın. özgür. Ona şöyle hitap ederler:

    boşluksuz (void *p boyutu);

    Burada P- daha önce işlevler tarafından ayrılmış bir hafıza alanına bir işaretçi alışveriş merkezi, kaltak veya yeniden yerleştirme.

    Operatörler yeni Ve silmek benzer işlevler alışveriş merkezi Ve özgür. Yeni bellek ayırır ve tek bağımsız değişkeni, ayrılacak bayt sayısını belirten bir ifadedir. Ayrılan bellek bloğunun başına bir operatör işaretçisi döndürür. Şebeke silmek belleği boşaltır, bağımsız değişkeni, serbest bırakılacak bloğun ilk hücresinin adresidir.

    dinamik dizi- programın yürütülmesi sırasında hafızanın tahsis edildiği değişken uzunlukta bir dizi. Bellek ayırma, işlevler tarafından gerçekleştirilir malç veya operatör yeni. Ayrılan belleğin ilk öğesinin adresi, işaretçi olarak bildirilen bir değişkende saklanır. Örneğin, aşağıdaki ifade, bir işaretçinin bildirildiği anlamına gelir. mas ve ifadeyle tahsis edilen bitişik dinamik bellek alanının başlangıç ​​adresi atanır yeni:

    int *mas=yeni int;

    10 int değeri depolamak için gerektiği kadar bellek ayrıldı.

    Aslında, değişkende mas dinamik dizinin sıfır elemanının adresi saklanır. Bu nedenle, tahsis edilen hafıza alanındaki bir sonraki, ilk elemanın adresi mas+1 ve mas+i, i'inci öğenin adresidir. Bir dinamik dizinin i'nci öğesine erişim, her zamanki gibi mas[i] veya başka bir şekilde yapılabilir. *(mas+i) . Ayrılan hafıza alanının sınırlarının dışına çıkmadığınızdan emin olmanız önemlidir.

    Dinamik diziye (program çalışmasının herhangi bir anında) ihtiyaç duyulmadığında, işlev kullanılarak bellek serbest bırakılabilir. özgür veya operatör silmek.

    Bu dersi pekiştiren birkaç görevi dikkate almayı öneriyorum:

    Görev 1

    Dinamik bir dizinin gerçek öğelerinin toplamını bulun.

    //malloc ve ücretsiz fonksiyonların kullanımına bir örnek #include "stdafx.h" #include ad alanı std kullanarak; int main() ( setlocale(LC_ALL,"Rus"); int i, n; float *a; //float için işaretçi float s; cout<<"\n"; cin>>n; //dizi boyutunun girişi //n adet gerçek elemanlık bir dizi için bellek tahsisi a=(float *)malloc(n*sizeof(float)); cout<<"Введите массив A \n"; //ввод элементов массива for (i=0; i>*(bir+i); ) //(s=0, i=0; i) için dizi elemanlarının toplamının toplanması

    //malloc ve free fonksiyonlarının kullanımına bir örnek

    #include "stdafx.h"

    #katmak

    ad alanı std kullanarak;

    int ana()

    int ben , n ;

    kayan *a; //yüzmek için işaretçi

    yüzer;

    cout<< "\n" ; cin >>n; // dizinin boyutunu girin

    // n adet gerçek öğe dizisi için bellek tahsisi

    a = (float * ) malloc (n * sizeof (float) ) ;

    cout<< "A \n dizisini girin";

    //giriş dizisi öğeleri

    için (i = 0 ; ben< n ; i ++ )

    cin >> * (a + ben ) ;

    //dizi elemanlarının toplamının toplanması

    için (s = 0 , ben = 0 ; ben< n ; i ++ )

    s += * (bir + ben ) ;

    // toplamın çıkış değeri

    cout<< "S=" << s << "\n" ;

    // Boş hafıza

    ücretsiz(a);

    sistem("duraklat");

    0 dönüşü;

    Görev 2

    Dinamik bir tamsayı dizisini, pozitif öğeleri negatif olacak ve tersi olacak şekilde değiştirin. Problemi çözmek için her elemanı -1 ile çarpacağız.

    //Yeni ve silme işleçlerini kullanma örneği #include "stdafx.h" #include ad alanı std kullanarak; int main() ( setlocale(LC_ALL,"Rus"); int i, n; //dizinin eleman sayısını girin cout<<"n="; cin>>n; //bellek tahsisi int *a=new int[n]; cout<<"Введите элементы массива:\n"; //ввод массива for (i=0; i>a[ı]; //(i=0; i) için verilen dizinin çıktısı

    //Yeni ve silme işleçlerini kullanma örneği

    #include "stdafx.h"

    #katmak

    ad alanı std kullanarak;

    int ana()

    setlocale(LC_ALL, "Rus" ) ;

    int ben , n ;

    //dizi elemanlarının sayısını girin

    cout<< "n=" ; cin >>n;

    //bellek tahsisi

    int * a = yeni int [ n ] ;

    cout<< "Dizi öğelerini girin:\n";

    //dizi girişi

    Bu makaleyi yazmak için bilgi toplarken, işaretçilerle ilk tanışmamı hatırladım - üzüntü vardı ... Bu nedenle, C ++ programlama üzerine çeşitli kitaplardan bu konuyla ilgili birkaç bölüm okuduktan sonra, farklı bir yoldan gitmeye ve C ++ işaretçileri konusunu gerekli gördüğüm sırayla belirtmeye karar verildi. Size hemen kısa bir tanım vereceğim ve çalışmadaki ipuçlarını örneklerle ele alacağız. Bir sonraki makale (), nüansları, C-stili dizelerle (karakter dizileri) işaretçilerin kullanımını ve hatırlanması gereken ana şeyleri kapsayacaktır.

    C++'da bir işaretçi, verilerin adresini (değerleri) bellekte depolayan ve verilerin kendisini depolayan bir değişkendir.

    Aşağıdaki örnekleri göz önünde bulundurarak, asıl şeyi anlayacaksınız - programlamada neden işaretçilere ihtiyacımız var, bunları nasıl bildireceğiz ve kullanacağız.

    Bir programda, program başlamadan önce boyutunu tam olarak bilmediğimiz bir tamsayı dizisi oluşturmamız gerektiğini varsayalım. Yani kullanıcının bu diziye kaç tane sayı eklemesi gerektiğini bilmiyoruz. Tabii ki, güvenli bir şekilde oynayabilir ve birkaç bin öğeden oluşan bir dizi (örneğin, 5.000) bildirebiliriz. Bu (bizim görüşümüze göre) kullanıcının çalışması için yeterli olmalıdır. Evet - gerçekten - bu yeterli olabilir. Ancak bu dizinin RAM'de çok yer kaplayacağını unutmayalım (5.000 * 4 (tip int) = 20.000 bayt). Ardından, kullanıcının dizimizin yalnızca 10 öğesini dolduracağından emin olduk. Görünüşe göre 40 bayt aslında çalışıyor ve 19.960 bayt boşuna hafıza kaplıyor.

    mantıksız RAM kullanımı

    #katmak ad alanı std kullanarak; int main() ( setlocale(LC_ALL, "rus"); const int SizeOfArray = 5000; int arrWithDigits = (); cout<< "Массив занял в памяти " << sizeof(arrWithDigits) << " байт" << endl; int amount = 0; cout << "Сколько чисел вы введёте в массив? "; cin >> miktar; cout<< "Реально необходимо " << amount * sizeof(int) << " байт" << endl; for (int i = 0; i < amount; i++) { cout << i + 1 << "-е число: "; cin >> diziWithDigits[i]; ) kesmek<< endl; for (int i = 0; i < amount; i++) { cout << arrWithDigits[i] << " "; } cout << endl; return 0; }

    #katmak

    ad alanı std kullanarak;

    int ana()

    const int SizeOfArray = 5000 ;

    int diziWithDigits [SizeOfArray] = ( ) ;

    cout<< "Dizi bellekte dolu"<< sizeof (arrWithDigits ) << " байт" << endl ;

    int miktar = 0 ;

    cout<< "Diziye kaç sayı koyacaksınız?";

    cin >> miktar ;

    cout<< "Gerçekten Gerekli"<< amount * sizeof (int ) << " байт" << endl ;

    için (int ben = 0 ; ben< amount ; i ++ )

    cout<< i + 1 << "-е число: " ;

    cin >> arrWithDigits[ i ] ;

    cout<< endl ;

    için (int ben = 0 ; ben< amount ; i ++ )

    cout<< arrWithDigits [ i ] << " " ;

    cout<< endl ;

    0 dönüşü;

    Standart bir kitaplık işlevine boyutu() bildirilen diziyi geçirme arrWithDigits satır 10. Çağrı sitesine, bu dizinin bellekte kapladığı boyutu bayt cinsinden döndürür. “Diziye kaç rakam gireceksiniz?” sorusuna cevap - 10. 15. satırda ifade miktar * sizeof(int) 10 * 4'e eşit olur, çünkü işlev sizeof(int) 4 döndürür (int tipi bayt cinsinden boyut). Ardından, klavyeden sayıları girin ve program bunları ekranda gösterecektir. Kalan 4990 elemanın sıfırları saklayacağı ortaya çıktı. O yüzden onları göstermenin bir anlamı yok.

    Ekrandaki ana bilgi: dizi 20.000 bayt aldı, ancak gerçekte 40 bayta ihtiyacı var. Bu durumdan nasıl çıkılır? Belki birisi programı yeniden yazmak isteyecektir, böylece kullanıcı dizinin boyutunu klavyeden girer ve değeri girdikten sonra gerekli sayıda öğeye sahip bir dizi bildirir. Ancak bu işaretçiler olmadan yapılamaz. Hatırlayacağınız gibi, bir dizinin boyutu sabit olmalıdır. Yani, dizi bildiriminden önce bir tamsayı sabiti başlatılmalıdır ve klavyeden girişini isteyemeyiz. Deney - kontrol edin.


    Burada operatör tarafından kırmızı renkle vurgulanıyoruz >> çünkü sabit bir değeri değiştiremezsiniz.

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


    Burada bir dizinin boyutunun sıradan bir değişkenin değeri OLMAYACAĞI konusunda uyarıldık. Sabit bir değer gerekli!

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Aşağıdaki kodda, sizin için yeni olan bir işaretçi ve operatörler kullanacağız. yeni(hafızayı ayır) ve silmek(belleği boşaltır).

    işaretçiler uygulayarak RAM'in makul kullanımı

    #katmak #katmak ad alanı std kullanarak; int main() ( setlocale(LC_ALL, "rus"); int sizeOfArray = 0; // dizi boyutu (kullanıcı girişi) cout<< "Чтобы создать массив чисел, введите его размер: "; cin >>sizeOfArray; // DİKKAT! int* arrWithDigits - new int* arrWithDigits = new int tarafından ayrılacak bir bellek parçasına bir işaretçi // bildirmek için (int ben = 0; ben< sizeOfArray; i++) { arrWithDigits[i] = i + 1; cout << arrWithDigits[i] << " "; } cout << endl; delete arrWithDigits; // освобождение памяти return 0; }

    #katmak

    #katmak

    ad alanı std kullanarak;

    int ana()

    setlocale(LC_ALL, "rus" ) ;

    int sizeOfArray = 0 ; // dizi boyutu (kullanıcı girişi)

    cout<< "Bir sayı dizisi oluşturmak için boyutunu girin: ";

    cin >> sizeOfArray ;

    // DİKKAT! int* arrWithDigits - işaretçi bildirimi

    // new'in ayıracağı hafıza alanına

    int *arrWithDigits = yeni int [sizeOfArray];

    için (int ben = 0 ; ben< sizeOfArray ; i ++ )

    diziWithDigits[ ben ] = ben + 1 ;

    cout<< arrWithDigits [ i ] << " " ;

    cout<< endl ;

    arrWithDigits'i sil; // belleği serbest bırak

    0 dönüşü;

    Kullanıcı klavyeden bir değer girer - satır 12. İşaretçi aşağıda tanımlanır: int * diziWithDigits Bu giriş şu anlama gelir: arrWithDigits bir işaretçidir. Tamsayının bulunacağı hücrenin adresini saklamak için oluşturulmuştur. bizim durumumuzda arrWithDigits dizini 0 olan dizi hücresini işaret edecektir. * - çarpma için kullanılanla aynı. Bağlamdan, derleyici bunun bir çarpma değil, bir işaretçi bildirimi olduğunu "anlayacaktır". sonra işaret gelir = ve operatör yeni, bir bellek bölgesi ayırır. Belleğimizin tek bir sayı için değil, bir dizi için ayrılması gerektiğini hatırlıyoruz. Kayıt yeni int[sizeOfArray]şu şekilde deşifre edilebilir: yeni(hafızayı ayır) int(tamsayıları saklamak için) (miktarında sizeOfArray ).

    Böylece, 16. satırda tanımlandı dinamik dizi. Bu, belleğin, sıradan dizilerde olduğu gibi derleme sırasında değil, program çalışması sırasında tahsis edileceği (veya tahsis edilmeyeceği) anlamına gelir. Yani, bellek tahsisi, programın gelişimine ve doğrudan çalışmasında alınan kararlara bağlıdır. Bizim durumumuzda, kullanıcının değişkene ne yazdığına bağlıdır. sizeOfArray

    Satır 25, ifadeyi kullanır silmek. Tahsis edilen operatörü serbest bırakır yeni hafıza. Çünkü yeni dizi tahsisi için ayrılmış bellek, daha sonra serbest bırakıldığında, derleyiciye dizi belleğini boşaltmanın gerekli olduğunu ve yalnızca sıfır hücresini değil, bu da arrWithDigits. Bu nedenle, arasında silmek ve işaretçi adı köşeli parantez içine alınır arrWithDigits'i sil; Unutulmamalıdır ki, hafıza kullanılarak her tahsis edilir. yeni kullanarak bu belleği boşaltmanız gerekir. silmek. Elbette programın sonunda kapladığı hafıza otomatik olarak boşalacaktır. Ancak operatörleri kullanmayı iyi bir alışkanlık haline getirin yeni Ve silmek ile eşleştirildi. Sonuçta, program örneğin 5-6 dizi içerebilir. Ve gelecekte çalışmakta olan programda artık ihtiyaç duyulmayan her seferinde belleği serbest bırakırsanız, bellek daha akıllıca harcanacaktır.

    Diyelim ki programımızda diziyi on değerle doldurduk. Sonra toplamlarını saydılar ve bir değişkene yazdılar. Hepsi bu kadar - artık bu diziyle çalışmayacağız. Program çalışmaya devam eder ve içinde bazı amaçlar için yeni dinamik diziler oluşturulur. Bu durumda, ilk dizinin kapladığı belleğin boşaltılması tavsiye edilir. Ardından, diğer diziler için bellek ayırırken, bu bellek programda yeniden kullanılabilir.

    İşaretçileri işlev parametreleri olarak kullanmayı düşünün. Başlamak için aşağıdaki kodu yazın ve derleyin. İçinde, işlev iki değişken alır ve değerlerinde değişiklik yapmayı önerir.

    bir işleve iletilen değişkenleri değiştirme girişimi

    #katmak #katmak ad alanı std kullanarak; void changeData(int varForCh1, int varForCh2); int main() ( setlocale(LC_ALL, "rus"); int değişkenForChange_1 = 0; int değişkenForChange_2 = 0; cout<< "variableForChange_1 = " << variableForChange_1 << endl; cout << "variableForChange_2 = " << variableForChange_2 << endl; cout << endl; changeData(variableForChange_1, variableForChange_2); cout << endl; cout << "variableForChange_1 = " << variableForChange_1 << endl; cout << "variableForChange_2 = " << variableForChange_2 << endl; return 0; } void changeData(int varForCh1, int varForCh2) { cout << "Введите новое значение первой переменной: "; cin >>varForCh1; cout<< "Введите новое значение второй переменной: "; cin >> varForCh2; )

    #katmak

    #katmak

    ad alanı std kullanarak;

    void changeData (int varForCh1 , int varForCh2 ) ;

    int ana()

    setlocale(LC_ALL, "rus" ) ;

    int değişkenForChange_1 = 0 ;

    int değişkenForChange_2 = 0 ;

    cout<< "variableForChange_1 = " << variableForChange_1 << endl ;

    cout<< "variableForChange_2 = " << variableForChange_2 << endl ;

    cout<< endl ;

    changeData (variableForChange_1 ,variableForChange_2 ) ;

    cout<< endl ;

    cout<< "variableForChange_1 = " << variableForChange_1 << endl ;

    cout<< "variableForChange_2 = " << variableForChange_2 << endl ;

    0 dönüşü;

    geçersiz changeData(int varForCh1 , int varForCh2 )

    cout<< "İlk değişken için yeni bir değer girin: ";

    cin >> varForCh1 ;

    cout<< "İkinci değişken için yeni bir değer girin: ";

    cin >> varForCh2 ;

    Programı çalıştırın ve yeni değişken değerleri girin. Fonksiyonun sonunda değişkenlerin değişmediğini ve 0'a eşit olduğunu göreceksiniz.

    Hatırlayacağınız gibi, işlev doğrudan değişkenlerle çalışmaz, onların tam kopyalarını oluşturur. Bu kopyalar, fonksiyondan çıkıldıktan sonra imha edilir. Yani, işlev bir değişkeni parametre olarak aldı, onun bir kopyasını oluşturdu, onunla çalıştı ve onu yok etti. Değişkenin kendisi değişmeden kalacaktır.

    İşaretçileri kullanarak değişken adresleri bir işleve iletebiliriz. Ardından işlev, adreste verilen değişkenlerle doğrudan çalışabilecektir. Bir önceki programda değişiklikler yapalım.

    işaretçileri kullanarak değişken değerleri değiştirme

    #katmak #katmak ad alanı std kullanarak; void changeData(int* varForCh1, int* varForCh2); int main() ( setlocale(LC_ALL, "rus"); int değişkenForChange_1 = 0; int değişkenForChange_2 = 0; cout<< "variableForChange_1 = " << variableForChange_1 << endl; cout << "variableForChange_2 = " << variableForChange_2 << endl; cout << endl; changeData(&variableForChange_1, &variableForChange_2); cout << endl; cout << "variableForChange_1 = " << variableForChange_1 << endl; cout << "variableForChange_2 = " << variableForChange_2 << endl; return 0; } void changeData(int* varForCh1, int* varForCh2) { cout << "Введите новое значение первой переменной: "; cin >> *varForCh1; cout<< "Введите новое значение второй переменной: "; cin >> *varForCh2; )

    Bu web sitesindeki ilk zamanlayıcı, işte başlıyor.

    C++'ta yeniyim ve şu anda "C++ Kullanan Veri Yapıları 2. baskı, D.S. Malik" kitabı üzerinde çalışıyorum.

    Kitapta Malik, dinamik bir iki boyutlu dizi oluşturmak için iki yol sunuyor. İlk yöntemde, değişkeni, her işaretçinin tamsayı türünde olduğu bir işaretçiler dizisi olarak bildirirsiniz. Örneğin.

    int *pano;

    Ve sonra bir dizi işaretçiyi "satırlar" olarak kullanırken "sütunlar" oluşturmak için bir for-loop kullanın.

    İkinci yöntem, bir işaretçiye bir işaretçi kullanırsınız.

    İç **pano; pano = yeni int* ;

    Sorum şu: Hangi yöntem daha iyi? ** yöntemini görselleştirmek benim için daha kolay, ancak ilk yöntem hemen hemen aynı şekilde kullanılabilir. Her iki yöntem de dinamik 2B diziler oluşturmak için kullanılabilir.

    Düzenleme: Yukarıda belirtildiği gibi yeterince açık değildi. İşte denediğim kod:

    Int satır, col; cout<< "Enter row size:"; cin >>sıra; cout<< "\ncol:"; cin >> sütun; int *p_board; için (int ben=0; ben< row; i++) p_board[i] = new int; for (int i=0; i < row; i++) { for (int j=0; j < col; j++) { p_board[i][j] = j; cout << p_board[i][j] << " "; } cout << endl; } cout << endl << endl; int **p_p_board; p_p_board = new int* ; for (int i=0; i < row; i++) p_p_board[i] = new int; for (int i=0; i < row; i++) { for (int j=0; j < col; j++) { p_p_board[i][j] = j; cout << p_p_board[i][j] << " "; } cout << endl; }

    4 yanıt

    İlk yöntem oluşturmak için kullanılamaz dinamik 2B diziler çünkü:

    int *pano;

    esasen bir int'ye 4 işaretçi dizisi tahsis ettiniz yığının üzerinde. Şimdi bu 4 işaretçinin her birini dinamik bir diziyle doldurursanız:

    için (int ben = 0; ben< 4; ++i) { board[i] = new int; }

    Sonunda elde ettiğiniz şey, 2 boyutlu bir dizidir. statik satır sayısı (bu durumda 4) ve dinamik sütun sayısı (bu durumda 10). Böylece, dinamikler tamamen, çünkü yığında bir dizi tahsis ettiğinizde, mutlak belirtmek sabit boyut, yani bilinen zaman. Dinamik dizi denir dinamik, çünkü boyutunun bilinmesi gerekmez derleme zamanı, ancak bunun yerine bazı değişkenler tarafından tanımlanabilir işlem esnasında.

    Bunu yaptığınızda bir kez daha:

    int *pano;

    Sabit int x = 4; //<--- `const` qualifier is absolutely needed in this case! int *board[x];

    bilinen bir sabit sağlıyorsunuz derleme zamanı(bu durumda 4 veya x) böylece derleyici artık ön seçim diziniz için bu bellek ve programınız belleğe yüklendiğinde, pano dizisi için zaten bu miktarda belleğe sahip olacaktır, bu yüzden buna denir statik, yani çünkü boyut kodlanmış Ve dinamik olarak değişemez(yürütme sırasında).

    Öte yandan, şunları yaptığınızda:

    İç **pano; tahta = yeni int*;

    int x = 10; //<--- Notice that it does not have to be `const` anymore! int **board; board = new int*[x];

    derleyici, bellek dizisi kartının ne kadarına ihtiyaç duyacağını bilmez ve bu nedenle önceden tahsis eder Tüm. Ancak programınızı çalıştırdığınızda, dizinin boyutu (çalışma zamanında) x değişkeninin değeri tarafından belirlenecek ve pano dizisi için karşılık gelen alan sözde alana tahsis edilecektir. demet- bilgisayarınızda çalışan tüm programların ayırabileceği bir bellek alanı önceden bilinmeyen(derleme zamanında) kişisel kullanım için belleği toplar.

    Sonuç olarak, gerçekten dinamik bir 2B dizi oluşturmak için ikinci yöntemi uygulamanız gerekir:

    İç **pano; tahta = yeni int*; // int için işaretçilerin dinamik dizisi (boyutu 10) (int i = 0; i< 10; ++i) { board[i] = new int; // each i-th pointer is now pointing to dynamic array (size 10) of actual int values }

    Az önce 10'a 10 kare 2B bir dizi oluşturduk.İçinden geçmek ve 1 gibi gerçek değerlerle doldurmak için iç içe döngüler kullanabiliriz:

    için (int ben = 0; ben< 10; ++i) { // for each row for (int j = 0; j < 10; ++j) { // for each column board[i][j] = 1; } }

    İkinci yöntem için tanımladığınız şey yalnızca bir 1B dizisi verir:

    int *pano = yeni int;

    Bu sadece 10 öğeli bir dizi ayırır. Belki de şöyle bir şey demek istedin:

    Int **pano = yeni int*; için (int ben = 0; ben< 4; i++) { board[i] = new int; }

    Bu durumda, 4 int* s ayırıyoruz ve ardından her birimiz dinamik olarak ayrılmış 10 int s dizisine işaret edeceğiz.

    Şimdi bunu int* board ile karşılaştırıyoruz; . Temel fark, böyle bir dizi kullanılırken derleme zamanında "satır" sayısının bilinmesi gerektiğidir. Bunun nedeni, dizilerin sabit derleme zamanı boyutlarına sahip olması gerektiğidir. Dizi, kapsamının sonunda yok edileceğinden, bu diziyi int* s'den döndürmek istiyorsanız da bir sorununuz olabilir.

    Hem satırları hem de sütunları dinamik olarak tahsis eden bir yöntem, bellek sızıntılarını önlemek için daha karmaşık önlemler gerektirir. Belleği şu şekilde boşaltmanız gerekir:

    için (int ben = 0; ben< 4; i++) { delete board[i]; } delete board;

    Bunun yerine standart kabı kullanmanızı tavsiye etmeliyim. std::array kullanabilirsiniz 4> veya belki std::vector > , uygun boyutla başlattığınız.

    Her iki durumda da, iç boyutunuz dinamik olarak ayarlanabilir (yani bir değişkenden alınabilir), ancak fark dış boyuttadır.

    Bu soru temel olarak aşağıdakine eşdeğerdir:

    int* x = yeni int; int x'ten "daha iyi" mi?

    Yanıt, "dizi boyutunu dinamik olarak seçmeniz gerekmediği sürece hayır"dır.

    Bu kod, çok az harici kitaplık gereksinimiyle iyi çalışır ve int **array öğesinin temel kullanımını gösterir.

    Bu cevap, dizinin her biri dinamik olarak boyutlandırılmıştır ve ayrıca dinamik olarak boyutlandırılmış bir doğrusal dizinin dinamik olarak boyutlandırılmış dallar dizisine nasıl atanacağı.

    Bu program, STDIN'den bağımsız değişkenleri aşağıdaki biçimde alır:

    2 2 3 1 5 4 5 1 2 8 9 3 0 1 1 3

    Programın kodu aşağıdadır...

    #katmak int main() ( int **array_of_arrays; int dizi_dizileri, sorgu_sayıları; sayı_arrays = sorgu_sayıları = 0; std::cin >> dizi_dizileri >> sorgular sayısı; //std::cout<< num_arrays << " " << num_queries; //Process the Arrays array_of_arrays = new int*; int size_current_array = 0; for (int i = 0; i < num_arrays; i++) { std::cin >> size_current_array; int *tmp_array = yeni int; için (int j = 0; j< size_current_array; j++) { int tmp = 0; std::cin >>tmp; tmp_array[j] = tmp; ) dizi_of_arrays[i] = tmp_array; ) // Sorguları işle int x, y; x=y=0; için (int q = 0; q< num_queries; q++) { std::cin >> x >> y; //std::çıkış<< "Current x & y: " << x << ", " << y << "\n"; std::cout << array_of_arrays[x][y] << "\n"; } return 0; }

    Bu, int main'in çok basit bir uygulamasıdır ve yalnızca std::cin ve std::cout'a bağlıdır. Barebone, ancak basit çok boyutlu dizilerle nasıl çalışılacağını gösterecek kadar iyi.

    dersin amacı: tek boyutlu dinamik diziler için belleğin bildirimlerini, tahsisini ve serbest bırakılmasını incelemek, öğelere erişmek, C ++ dilinde tek boyutlu dinamik dizileri kullanarak problemlerin nasıl çözüleceğini öğrenmek.

    Birçok veri yapısını kullanırken, bunların değişken boyutta olması genellikle yeterlidir. kurşun zamanı programlar. Bu durumlarda başvurmak gerekir. dinamik bellek ayırma. En yaygın bu tür veri yapılarından biri, başlangıçta boyutun tanımlanmadığı ve sabitlenmediği dizilerdir.

    Buna göre dil standardı dizi, her biri aynı niteliklere sahip olan bir öğeler koleksiyonudur. Tüm bu öğeler, dizinin başına karşılık gelen adresten başlayarak, arka arkaya bitişik bellek alanlarına yerleştirilir. Yani, dizi elemanlarının toplam sayısı ve ona ayrılan belleğin boyutu, dizi tanımı tarafından tamamen ve açık bir şekilde elde edilir. Ancak bu her zaman uygun değildir. Bazen bir dizi için ayrılan belleğin belirli bir sorunu çözmek için boyutlandırılması gerekir ve bunun miktarı önceden bilinmez ve sabitlenemez. Değişken boyutlarda dizilerin (dinamik diziler) oluşumu, işaretçiler ve araçlar kullanılarak organize edilebilir dinamik bellek ayırma.

    dinamik dizi boyutu önceden sabit olmayan ve programın yürütülmesi sırasında değişebilen bir dizidir. yeniden boyutlandırmak için dinamik dizi Programlama dili Bu tür dizileri destekleyen C++, özel yerleşik işlevler veya operasyonlar. Dinamik diziler saklanan veri hacimlerini tahmin etmeye değil, dizinin boyutunu gerçekten gerekli hacimlere göre ayarlamaya izin verdiği için verilerle daha esnek çalışmayı mümkün kılar.

    Tek boyutlu dinamik dizileri bildirme

    Tek boyutlu beyanı kapsamında dinamik dizi Belirli bir türdeki bir değişkene işaretçi bildirimini anlayın, böylece bu değişken şu şekilde kullanılabilir: dinamik dizi.

    sözdizimi:

    * DiziAdı yazın;

    Tür - beyan edilen öğelerin türü dinamik dizi. Elementler dinamik dizi void türünde işlevler ve öğeler olamaz.

    Örneğin:

    int*a; çift ​​*d;

    Bu örneklerde a ve d, tahsis edilen hafıza alanının başlangıcına işaretçilerdir. İşaretçiler, sırasıyla int tipi ve double tipi değerler için ayrılan bellek alanının adresinin değerini alır.

    Bu nedenle, dinamik diziler için dinamik olarak bellek ayırırken, tahsis edilen bellek alanının başlangıcının adresinin değeri atanacak olan karşılık gelen işaretçiyi tanımlamanız gerekir.

    Tek boyutlu bir dinamik dizi için bellek tahsisi

    Tek boyutlu bir bellek ayırmak için dinamik dizi C++ dilinde 2 yol vardır.

    1) bir operasyon yardımı ile diziyi barındırmak için uygun boyutta dinamik belleğin bir bölümünü ayıran ve dizinin öğelerini başlatmanıza izin vermeyen new .

    sözdizimi:

    DiziAdı = yeni Tür [SabitTürİfadesi];

    DiziAdı - dizi tanımlayıcısı, yani tahsis edilen bellek bloğu için işaretçinin adı.

    İfadeTürüSabitler– eleman sayısını ayarlar ( dizinin boyutu). Derleme zamanında bir sabit tür ifadesi değerlendirilir.

    Örneğin:

    int *mas; mas = yeni int ; /* 100*sizeof(int) baytlık dinamik bellek tahsisi*/ double *m = new double [n]; /*n*sizeof(double) baytlık dinamik belleği tahsis et*/ long (*lm); lm = yeni uzun; /*2*4*boyut(uzun) bayt dinamik bellek ayır*/

    Dinamik bellek tahsis edilirken dizinin boyutları tam olarak tanımlanmalıdır.

    2) kitaplık işlevi kullanma dinamik bellek ayırmak için kullanılan malloc (calloc).

    sözdizimi:

    DiziAdı = (Tür *) malloc(N*sizeof(Tür));

    DiziAdı = (Tür *) calloc(N, sizeof(Tür));

    DiziAdı - dizi tanımlayıcısı, yani tahsis edilen bellek bloğu için işaretçinin adı.

    Tür, bir dizi işaretçisinin türüdür.

    N, dizi öğelerinin sayısıdır.

    Örneğin:

    kayan *a; a=(float *)malloc(10*sizeof(float)); // veya a=(float *)calloc(10,sizeof(float)); /*10*sizeof(float) baytlık dinamik bellek boyutunun tahsisi*/

    malloc(calloc) işlevi geri döndüğünden beri yazılmamış işaretçi void * , ardından sonucu dönüştürmeniz gerekir