D Programlama Dili - Çözümler

Göstergeler

  1. Parametre türleri yalnızca int olduğunda işleve main() içindeki değişkenlerin kopyalarının gönderildiklerini biliyorsunuz. main() içindeki değişkenlerin referanslarını edinmenin bir yolu, parametreleri ref int olarak tanımlamaktır.

    Diğer bir yol, o değişkenlere erişim sağlayan göstergeler göndermektir. Programın değişen yerlerini işaretlenmiş olarak gösteriyorum:

    void değişTokuş(int * birinci, int * ikinci) {
        int geçici = *birinci;
        *birinci = *ikinci;
        *ikinci = geçici;
    }
    
    void main() {
        int i = 1;
        int j = 2;
    
        değişTokuş(&i, &j);
    
        assert(i == 2);
        assert(j == 1);
    }
    
  2. Hem Düğüm hem de Liste int türüne bağlı olarak yazılmışlardı. Bu iki yapıyı şablona dönüştürmenin yolu, tanımlanırken isimlerinden sonra (T) eklemek ve tanımlarındaki int'leri T ile değiştirmektir. Değişen yerlerini işaretlenmiş olarak gösteriyorum:
    struct Düğüm(T) {
        T eleman;
        Düğüm * sonraki;
    
        string toString() const {
            string sonuç = to!string(eleman);
    
            if (sonraki) {
                sonuç ~= " -> " ~ to!string(*sonraki);
            }
    
            return sonuç;
        }
    }
    
    struct Liste(T) {
        Düğüm!T * baş;
    
        void başınaEkle(T eleman) {
            baş = new Düğüm!T(eleman, baş);
        }
    
        string toString() const {
            return format("(%s)", baş ? to!string(*baş) : "");
        }
    }
    

    Liste'yi artık int'ten başka türlerle de deneyebiliriz:

    import std.stdio;
    import std.conv;
    import std.string;
    
    // ...
    
    struct Nokta {
        double x;
        double y;
    
        string toString() const {
            return format("(%s,%s)", x, y);
        }
    }
    
    void main() {
        Liste!Nokta noktalar;
    
        noktalar.başınaEkle(Nokta(1.1, 2.2));
        noktalar.başınaEkle(Nokta(3.3, 4.4));
        noktalar.başınaEkle(Nokta(5.5, 6.6));
    
        writeln(noktalar);
    }
    

    Çıktısı:

    ((5.5,6.6) -> (3.3,4.4) -> (1.1,2.2))
    
  3. Bu durumda sondaki düğümü gösteren bir üyeye daha ihtiyacımız olacak. Açıklamaları programın içine yerleştirdim:
    struct Liste(T) {
        Düğüm!T * baş;
        Düğüm!T * son;
    
        void sonunaEkle(T eleman) {
            /* Sona eklenen elemandan sonra düğüm bulunmadığından
             * 'sonraki' düğüm olarak 'null' gönderiyoruz. */
            auto yeniDüğüm = new Düğüm!T(eleman, null);
    
            if (!baş) {
                /* Liste boşmuş. Şimdi 'baş' bu düğümdür. */
                baş = yeniDüğüm;
            }
    
            if (son) {
                /* Şu andaki 'son'dan sonraya bu düğümü
                 * yerleştiriyoruz. */
                son.sonraki = yeniDüğüm;
            }
    
            /* Bu düğüm yeni 'son' oluyor. */
            son = yeniDüğüm;
        }
    
        void başınaEkle(T eleman) {
            auto yeniDüğüm = new Düğüm!T(eleman, baş);
    
            /* Bu düğüm yeni 'baş' oluyor. */
            baş = yeniDüğüm;
    
            if (!son) {
                /* Liste boşmuş. Şimdi 'son' bu düğümdür. */
                son = yeniDüğüm;
            }
        }
    
        string toString() const {
            return format("(%s)", baş ? to!string(*baş) : "");
        }
    }
    

    başınaEkle() işlevi aslında daha kısa olarak da yazılabilir:

        void başınaEkle(T eleman) {
            baş = new Düğüm!T(eleman, baş);
    
            if (!son) {
                son = baş;
            }
        }
    

    Yukarıdaki Nokta nesnelerinin tek değerli olanlarını başa, çift değerli olanlarını sona ekleyen bir deneme:

    void main() {
        Liste!Nokta noktalar;
    
        foreach (i; 1 .. 7) {
            if (i % 2) {
                noktalar.başınaEkle(Nokta(i, i));
    
            } else {
                noktalar.sonunaEkle(Nokta(i, i));
            }
        }
    
        writeln(noktalar);
    }
    

    Çıktısı:

    ((5,5) -> (3,3) -> (1,1) -> (2,2) -> (4,4) -> (6,6))