Forum: Ders Arası RSS
Postfix hesap makinesi
acehreli (Moderatör) #1
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4643 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: Postfix hesap makinesi
Postfix, işlemin değerlerden sonra gelmesi anlamına geliyor. Örneğin, 1 + 2 değeri için önce 1, sonra 2, sonra + girin.
import std.stdio;
import std.conv;
import std.exception;
import std.string;
 
alias Tür = double;
 
void kısalt(ref Tür[] yığıt, size_t adet) {
    yığıt.length -= adet;
    yığıt.assumeSafeAppend();
}
 
void kullanım() {
    writeln("Kullanım:
    sayı      : Yığıta ekler
    +, -, *, /: Yığıttaki son iki değerle işlem yapar; sonucu yığıta ekler
    sil       : Son değeri yığıttan çıkartır
");
}
 
void main() {
    kullanım();
 
    Tür[] yığıt;
 
    foreach (satır; stdin.byLineCopy) {
        satır = strip(satır);
switchBaşı:
        switch (satır) {
            static foreach (işlem; [ "+", "-", "*", "/" ]) {
            case işlem:
                if (yığıt.length < 2) {
                    writefln("HATA: Yığıtta %s işlemi için yeterli değer yok", satır);
                } else {
                    auto değer = mixin(format("yığıt[$-2] %s yığıt[$-1]", işlem));
                    yığıt.kısalt(2);
                    yığıt ~= değer;
                }
                break switchBaşı;
            } // static foreach
 
        case "sil":
            if (!yığıt.empty) {
                yığıt.kısalt(1);
            }
            break;
 
        default:
            if (!satır.empty) {
                try {
                    yığıt ~= satır.to!Tür;
                }
                catch (ConvException hata) {
                    writefln(`HATA: "%s sayı değil`, satır);
                }
                break;
            }
        } // switch
        writefln("Yığıt: %s", yığıt);
    }
}
Ali
erdem (Moderatör) #2
Üye Tem 2009 tarihinden beri · 1076 mesaj · Konum: Eskişehir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
$ dmd test3.d -oftest3
test3.d(30): Error: basic type expected, not foreach
test3.d(30): Error: no identifier for declarator _error_

Dmd v2.075.1 ile derlenirken böyle hatalar verdi.

Allah'a şükür D derleyicisinin son sürümüyle derlendi.
cos00kun #3
Üye Kas 2014 tarihinden beri · 262 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Bu bilgilerde güzel oldu benim için..Buradaki "stdin.byLineCopy" ve "assumeSafeAppend()"  nin tam olarak ne işe yaradığını soracaktımki forumda arattığımda bunları açıklayan topicler buldum.. Yinede stdin (standart giriş) elemenaları ve kullanımları ile ilgili boş bir zamanda bir konu başlığı açılıp bilgilendirme yapılırsa çok iyi olur kanaatindeyim naçizane  :blush: zira Kitapta haklı olarak bu konu çok yer bulamamış olabilir.
E=mc^2
acehreli (Moderatör) #4
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4643 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Biraz olgunlaştırdım:
import std.stdio;
import std.conv;
import std.string;
import std.algorithm;
 
immutable işlemler = [ "+", "-", "*", "/" ];
 
// Diziye kendi türünden eleman ekler
void ekle(T)(ref T[] dizi, T değer) {
    dizi ~= değer;
}
 
// Diziye string'den dönüştürdüğü eleman ekler.
// `değer` T'ye dönüştürülemiyorsa ConvException atar
void ekle(T)(ref T[] dizi, string değer) {
    dizi ~= değer.to!T;
}
 
// Diziden eleman çıkartır. Dizinin başka dilimi
// olmadığını varsayarak çıkartılan elemanların
// yerlerini daha sonradan eklenen elemanlar için kullanır.
void kısalt(T)(ref T[] dizi, size_t adet) {
    dizi.length -= adet;
    dizi.assumeSafeAppend();
}
 
// Yığıtın içeriğini yazdırır. Gittikçe azalan ve en sonunda
// yok olan etiketler kullanır.
void bildir(T)(const T[] yığıt)  {
    static size_t adet = 0;
    enum etiketler = [ "Yığıt", "y", "" ];
    const etiket = etiketler[min(etiketler.length - 1, adet)];
    writefln("%s:%( %s%)", etiket, yığıt);
    ++adet;
}
 
void kullanım() {
    writefln(
"Kullanım:
    sayı     : Yığıta ekler
    %-(%s %)  : Yığıttaki son iki değerle işlem yapar; sonucu yığıta ekler
    sil      : Son değeri yığıttan çıkartır
", işlemler);
}
 
void main() {
    kullanım();
 
    double[] yığıt;
 
    void işle(string satır) {
switchBaşı:
        switch (satır) {
            static foreach (işlem; işlemler) {
            case işlem:
                if (yığıt.length < 2) {
                    writefln(`HATA: Yığıtta "%s" işlemi için yeterli değer yok`, işlem);
                } else {
                    auto değer = mixin(format("yığıt[$-2] %s yığıt[$-1]", işlem));
                    yığıt.kısalt(2);
                    yığıt.ekle(değer);
                }
                break switchBaşı;
            } // static foreach
 
        case "sil":
            if (!yığıt.empty) {
                yığıt.kısalt(1);
            }
            break;
 
        default:
            try {
                yığıt.ekle(satır);
            }
            catch (ConvException hata) {
                writefln(`HATA: Sayı, işlem, veya "sil" değil: "%s"`, satır);
            }
            break;
        } // switch
 
        yığıt.bildir();
    }
 
    stdin
        .byLine
        .map!strip
        .filter!(satır => !satır.empty)
        .map!(satır => satır.text)
        .each!işle;
}
Ali
acehreli (Moderatör) #5
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4643 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #3
cos00kun:
"stdin.byLineCopy"

Okunan ifadeleri dizgi olarak saklayacağımı düşündüğüm için baştan byLineCopy kullanmıştım. Gerekmediğini görünce byLine ile değiştirdim. İkisi de girişi satır satır sunar ama byLine daha hızlı olsun diye her satır için yeni bellek ayırmaz; hepsini aynı yere okur. Bu da satırın parçalarını daha sonra kullanmak için string olarak saklamak istendiğinde sorun oluşturur. (Çünkü önceki satırın saklanan parçasının üzerine yeni satır okunmuştur.)

"assumeSafeAppend()"

Böyle bir programda kesinlikle gerekmiyor ama yığıt elemanlarına eriştiren başka dilim olmadığını bildiğimden yine de kullandım. Çöp toplayıcı (aslında D çalışma ortamı (runtime)), bir dilime eleman eklerken o elemanı gösteren başka dilim olup olmadığını bilemez. (Bilecek biçimde de tasarlanabilirdi ama onun hesabını tutmak fazla masraflı olurdu.) O yüzden, ~= işlemi sırasında bütün elemanlar yeni bir yere kopyalanırlar. Bu programda ise elemanlara eriştiren başka dilim bulunmadığını bildiğimden, sondan çıkartılan elemanların üzerine yazılmasında sakınca olmadığını biliyordum. O yüzden, ekleme (append) işleminin güvenle yapılabileceğini runtime'a assumeSafeAppend ile bildirdim.

Ali
cos00kun #6
Üye Kas 2014 tarihinden beri · 262 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Hay Allah razı olsun herşey çok netleşti şimdi.. Kelimelerle istediğini bu kadar güzel ifade eden birine programlama dünyasında ilk defa rastladım gerçekten. Yada tamda benim dertlere derman oluyorsunuz diyelim .. Siz Edebiyat mezunu falan değilsiniz değilmi?  :-p

Bu bilgilerle şöyle 2 hafta bir altyapıyı toparlayayım D ile birlikte.. Sağolun varolun..
E=mc^2
acehreli (Moderatör) #7
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4643 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
cos00kun:
Edebiyat mezunu falan değilsiniz değilmi?  :-p

Güzel sözler için teşekkürler. :) Hayır, edebiyat mezunu değilim ve okulda o konulardan hiç hoşlanmamıştım. Benim gibi olan ve hatta tarihi de sevmeyen çok kişi tanıdım. O gibi konulara ilgi okuldan çok sonra oluşabiliyor...

Kompozisyon yazmak benim için eziyetti. :) Hatta, paragrafın ne olduğunu tabii ki anlıyordum ama kendim ne zaman ve neden paragraf başlatacağımdan emin olamıyordum. İlginç biçimde, bu konunun da programcılık öğrenirken geliştiğini düşünüyorum. (Belki de salt deneyimdendir; bilmiyorum.)

Ali
erdem (Moderatör) #8
Üye Tem 2009 tarihinden beri · 1076 mesaj · Konum: Eskişehir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #6
cos00kun:
Bu bilgilerle şöyle 2 hafta bir altyapıyı toparlayayım D ile birlikte..

Aslında bu kısım o kadar karışık değil. Yaptığımız basitçe yığıt veri yapısı kullanarak sayıları ve işleçleri bir yığıta koymak. Sonra diyeceğim ki sayılar yığıtından iki tane, işleçler yığıtından bir tane işleç çıkar. Örneğin 10, 20 ve + olsun. Sonucu tekrar sayılar yığıtına ekle. Bu şekilde işleçlerimiz bitene kadar devam et.
import std.array;
 
class Yığıt(T)
{
    private T[] elemanlar;
 
    @property bool boşMu() { return elemanlar.empty(); }
 
    void ekle(T enüst) { elemanlar ~= enüst; }
 
    T çıkar()
    {
        if (this.boşMu)
            throw new Exception("Yığıt boş.");
        auto enüst = elemanlar.back;
        elemanlar.popBack();
        return enüst;
    }
}
 
alias TamsayıYığıt = Yığıt!int;
alias DizgeYığıt = Yığıt!string;
 
void main()
{
    import std.stdio: writeln;
    auto yığıt = new TamsayıYığıt();
    yığıt.ekle(10);
    yığıt.ekle(20);
    writeln("Eleman çıkarıyorum ", yığıt.çıkar);
    writeln("Eleman çıkarıyorum ", yığıt.çıkar);
}

Örneğin bu yığıt örneğini inceleyebilirsin.
cos00kun #9
Üye Kas 2014 tarihinden beri · 262 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
erdem:
Aslında bu kısım o kadar karışık değil. Yaptığımız basitçe yığıt veri yapısı kullanarak sayıları ve işleçleri bir yığıta koymak. Sonra diyeceğim ki sayılar yığıtından iki tane...........
Yok hocam karışıklığından değil herşeyi anladım sadece D de çok ileri seviyede olmadığımdan daha doğrusu henüz belli konuları öğrenmediğimden dolayı sadcece herşey üst üste bindi yoksa konuyu anlamada şu an problem yok  ;-) zaten geçmişimde assembly ve cpu register konularında bayağı cebelleşmiş biri olarak stack hafızanın nasıl çalıştığını iyi bilir ve anlarım çok kabaca yapılan işin özetide bu aslında .. 2 ay önce burda paylaşılanların büyük bir bölümünü anlamayacağımı düşünürdüm belki sizin için değil ama benim için bayağı bir yol gittim sayılır sizlerin katkılarıyla.. Daha gidecek çok yolum olduğununda farkındayım ama sorun yok  :-)
E=mc^2
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:
Forum: Ders Arası RSS
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: 2018-02-23, 12:27:53 (UTC -08:00)