Forum: D Programlama Dili RSS
Dizileri kırpmak
acehreli (Moderatör) #1
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: Dizileri kırpmak
Dilimler çok kullanışlı olabiliyor. Komut satırından gelen parametrelerin ilki, yani parametreler[0], her zaman için program başlatılırken kullanılan isimdir.

Aşağıdaki program bütün parametrelerinin toplamını döndürüyor. Dilimlerin sevdiğim tarafı, topla işlevini çağırırken o ilk parametreden kurtulmak için [1 .. $] yazmak yetiyor.

import std.stdio;
import std.conv;
 
int main(string[] parametreler)
{
    if (parametreler.length < 2) {
        writeln("Hiç sayı belirtmediniz");
        return 1;
    }
 
    writeln("Toplam: ", topla(parametreler[1 .. $]));
 
    return 0;
}
 
real topla(string[] veriler)
{
    real toplam = 0L;
 
    foreach (veri; veriler) {
        toplam += to!real(veri);
    }
 
    return toplam;
}

Daha da güzeli, o işlem sırasında hiç eleman kopyalanmıyor. topla'ya, asıl dizinin bir dilimi gönderiliyor.

Ali
canalpay (Moderatör) #2
Kullanıcı başlığı: Can Alpay Çiftçi
Üye Tem 2009 tarihinden beri · 1133 mesaj · Konum: İzmir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Evet D'de diziler çok güzel. Bunun yanında eşleme tablolarıda çok güzel. Ama diziler hakkında bazı karışıklıklar vardı, bunlar çözüldü mü ?
acehreli (Moderatör) #3
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Dizilerin gelişimleri durdu ve karışıklıkları çözüldü. (Bunları 2.045 ile aşağıda deniyorum.)

Aklıma gelen iki tanesi:

1) sabit uzunluklu dizilerin değer türü kabul edilmelerini biz de yaşadık (bu konuyu D.ershane'de değiştirmiştim bile)

Bu, C'den ve C++'dan çok büyük bir fark olarak kabul edilmeli. O dillerde, diziler yarım referans gibi türlerdir. İşlevlere gönderilirken özel kuralları filan vardır.

D'de olay iyice çözülmüş durumda: sabit uzunluklu diziler kopyalanır, dinamik diziler (aslında dilim ile aynı şey) ise referans türüdür; kopyalanmaz:

// Sabit uzunluklu dizi olduğu için, parametre kopyalanır
void sabitAlan(int[3] dizi)
{
    // yalnızca yerel 'dizi' değişir
    dizi[2] = 22222;
}
 
// Dilim olduğu için, parametre kopyalanmaz
void dilimAlan(int[] dizi)
{
    // gönderilen asıl dizi değişir
    dizi[2] = 22222;
}
 
void main()
{
    int[3] sabitUzunluklu = [ 0, 1, 2 ];
    sabitAlan(sabitUzunluklu);
    // değişmemiş; çünkü kopyalanarak gönderilir
    assert(sabitUzunluklu == [ 0, 1, 2 ]);
 
    int[] dilim = [ 0, 1, 2 ];
    dilimAlan(dilim);
    // değişmiş; çünkü referans olarak gönderilir
    assert(dilim == [ 0, 1, 22222 ]);
 
    // Sabit uzunluklu olan da dilim olarak gönderilebilir
    dilimAlan(sabitUzunluklu);
    assert(sabitUzunluklu == [ 0, 1, 22222] );
}

2) Dilimlere eklemek, şaşırtıcı sonuçlar doğurabilir:

void main()
{
    // İki tane elemanı olan bir dilim oluşturuyoruz
    int[] dilim;
    dilim ~= 3;
    dilim ~= 33;
 
    // İçinde 3 ve 33 bulunmasını bekleriz
    assert(      dilim == [ 3, 33 ]);
 
    // Başka bir dilimi, bu dilim ile ilkliyoruz
    int[] başka_dilim = dilim;
 
    // Bu noktadan sonra iki dilimin elemanları da aynıdır
    // (aslında "aynı elemanlara erişim sağlarlar" demek daha
    // doğru)
    assert(      dilim == [ 3, 33 ]);
    assert(başka_dilim == [ 3, 33 ]);
 
    // Buradaki 'is' işleci, "aynı elemanlara erişim sağlar"
    // anlamına geliyor
    assert(dilim is başka_dilim);
 
    // Göstergeler dersinde gördüğümüz .ptr değerleri de aynı
    assert(dilim.ptr == başka_dilim.ptr);
 
    // Birinci dilimde bir değer değiştiriyoruz
    dilim[0] = 7;
 
    // Evet, ikisinin de ilk elemanları değişmiştir
    assert(      dilim == [ 7, 33 ]);
    assert(başka_dilim == [ 7, 33 ]);
 
    // Diğer ilişkilerinde bir değişme beklemeyiz; aynılar
    assert(dilim is başka_dilim);
    assert(dilim.ptr == başka_dilim.ptr);
 
    // Dilimlerden birisine bir eleman ekliyoruz
    dilim ~= 333;
 
    // O dilimin yeni bir elemanı oluyor
    assert(      dilim == [ 7, 33, 333 ]);
 
    // Diğer dilimin bu konuyla bir ilgisi yok
    assert(başka_dilim == [ 7, 33 ]);
 
    // Artık "aynı elemanlara erişim sağlar" diyemeyiz; o
    // yüzden, !is işleci doğru oluyor
    assert(dilim !is başka_dilim);
 
    // İşin garibi, erişim sağladıkları elemanlar yine de
    // "aynı", çünkü .ptr değerleri aynı
    assert(dilim.ptr == başka_dilim.ptr);
 
    // Yine değer değiştiriyoruz
    dilim[0] = 8;
 
    // O değişikliği ikisinde de görüyoruz
    assert(      dilim == [ 8, 33, 333 ]);
    assert(başka_dilim == [ 8, 33 ]);
 
    //  İşler bu noktadan sonra ilginçleşiyor
    //
    // Önce, bu aşamada belleğin nasıl olduğuna
    // bakalım. Ortalıkta yalnızca 3 tane eleman var. dilim,
    // bunların üçüne de erişim sağlıyor; başka_dilim ise ilk
    // ikisine:
    //
    //      ... |  8  |  33 | 333 | ...
    //             \      \    \
    //               -------------- dilim
    //               \      \
    //                 ---------- başka_dilim
 
    // Şimdi, "diğer" dilime eleman ekliyoruz
    başka_dilim ~= 3333;
 
    // O son işlem, bu iki dilimin arasındaki "paylaşma"
    // ilişkisini sona erdirir. Bunun nedeni, ikinci dilimin
    // sonunda serbestçe eleman ekleyeceği yer
    // bulunmamasıdır. Çünkü orada birinci elemanın eklemiş
    // olduğu 333 vardır.
    //
    // Önemli nokta: O son işlem, başka_dilim'in elemanlarının
    // yeni bir yere kopyalanmalarına ve başka_dilim'in artık
    // farklı elemanlara erişim sağlamasına neden olur:
    //
    //      ... |  8  |  33 | 333 | ...
    //             \      \    \
    //               -------------- dilim
    //
    //
    //      ... |  8  |  33 | 3333 | ...
    //               \      \   \
    //                 ------------- başka_dilim
 
    // Evet, içerikler beklediğimiz gibi:
    assert(      dilim == [ 8, 33, 333 ]);
    assert(başka_dilim == [ 8, 33, 3333]);
 
    // Artık farklı elemanlara erişim sağlıyorlar (yani !is)
    assert(dilim !is başka_dilim);
 
    // Kopyalandıklarını da .ptr değerlerinin farklı
    // olmasından anlıyoruz
    assert(dilim.ptr != başka_dilim.ptr);
}

Çok uzun bir hikaye oldu. :)

Aslında hiç de zor bir konu değil ama dilimlerin belirli bir noktadan sonra birbirlerinden bağımsız hale gelebileceklerini anlamamız gerekiyor.

Ali
Doğrulama Kodu: VeriCode Lütfen resimde gördüğünüz doğrulama kodunu girin:
İfadeler: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Özel Karakterler:
Bağlı değilsiniz. · Şifremi unuttum · ÜYELİK
This board is powered by the Unclassified NewsBoard software, 20100516-dev, © 2003-10 by Yves Goergen
Şu an: 2017-11-18, 03:55:59 (UTC -08:00)