Forum: D Programlama Dili RSS
Giriş işlemleri için ddio.d
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ı: Giriş işlemleri için ddio.d
Standart girişten okumayla ilgili bazı sorunlar olduğunu biliyoruz. Emekliye ayrılacak olan din ve dout'u D.ershane'deki derslerden kaldırmadan önce stdin'in hatasız olarak kullanılabilmesini bekliyordum.

Öyle beklemek yerine, kendim oku isminde dört işlev yazdım. Kısa örnekler:

    oku!int();               // Bir int okur
 
    oku!dstring("İsminiz?"); // Belirtilen mesajı gösterdikten sonra bir
                             // dstring okur
 
    long l;
    oku(&l);                 // Var olan değişkenin türünde bir değer okur
                             // (burada long)
 
    dstring şehir;
    oku("Şehir?", &şehir);   // Belirtilen mesajı gösterdikten sonra, var olan
                             // değişkenin türünde bir değer okur (burada
                             // dstring) 

readf gibi becerikli değiller ama sanırım doğru işliyorlar. Ayrıca, hatalı girişlerde hangi değer aralığının doğru olduğunu da bildiriyorlar. Örnek:

ubyte türünde bir değer giriniz: -33
HATA: '-33', ubyte türüne dönüştürülemez; Geçerli değer aralığı: [0, 255]


Dosyanın ismini, "standard input output"un benzeri olan "ddili input output"a benzeterek ve fazla düşünmeden ddio.d yaptım:

/**
 * ddio.d - D.ershane'deki kod örneklerinde yararlanılan standart giriş/çıkış
 * dosyası
 *
 *   http://ddili.org/ders/d/index.html
 */
 
module ddio;
 
import std.stdio;
import std.string;
import std.conv;
import std.traits;
 
/**
 * Verilen mesajı standart çıkışa yazdırır, ve standart girişten belirtilen
 * türde bir değer okur
 */
T oku(T)(string mesaj)
{
    while (true) {
        if (mesaj.length) {
            stdout.write(mesaj ~ ' ');
        }
 
        string satır;
        while (satır.length == 0) {
            satır = strip(stdin.readln());
        }
 
        try {
            return dönüştürmeyiDene!T(satır);
 
        } catch (DönüşümHatası hata) {
            writef("HATA: %s", hata);
 
            /* Karakter ve dizgi türleri için "değer aralığı" kavramı kolay
             * tanımlanamadığı için bu mesajı yalnızca diğer türler için
             * gösteriyoruz. */
            static if (!isSomeChar!T && !isSomeString!T) {
                writef("; Geçerli değer aralığı: [%s, %s]", T.min, T.max);
            }
 
            writeln();
            stdin.clearerr();
        }
    }
}
 
/**
 * Yukarıdaki oku() işlevi gibi işler; farklı olarak, çıktıya bir mesaj
 * yazdırmaz
 */
T oku(T)()
{
    return oku!T("");
}
 
/**
 * Diğer oku() işlevleri gibi işler; farklı olarak, var olan bir değişkene
 * okuduğu için şablon parametresinin açıkça belirtilmesi gerekmez
 */
void oku(T)(string mesaj, T * değişken)
{
    *değişken = oku!T(mesaj);
}
 
/**
 * Diğer oku() işlevleri gibi işler; farklı olarak, var olan bir değişkene
 * okuduğu için şablon parametresinin açıkça belirtilmesi gerekmez, ve çıktıya
 * bir mesaj yazdırmaz
 */
void oku(T)(T * değişken)
{
    *değişken = oku!T();
}
 
private {
 
/**
 * Dönüşüm hatalarını bildirmede kullanılan tür
 *
 * Not: Bunun yerine, Phobos'un dönüşüm hatası durumlarında zaten atmakta
 * olduğu std.conv.ConvError türünü de kullanabilirdik; ancak o hatanın
 * çıktısı, bizim ihtiyacımız dışında bilgiler de taşıdığı için fazla
 * kalabalık oluyor.
 */
class DönüşümHatası : Exception
{
    string tür;
    string değer;
 
    this(string tür, string değer)
    {
        this.tür = tür;
        this.değer = değer;
 
        super(this.toString());
    }
 
    override string toString()
    {
        return format("'%s', %s türüne dönüştürülemez", değer, tür);
    }
}
 
/**
 * Gereken dönüşümü gerçekleştirmeyi dener; olası ConvError hatalarını
 * DönüşümHatası türüne dönüştürür
 */
T dönüştürmeyiDene(T)(string satır)
{
    try {
        return dönüştür!T(satır);
 
    } catch (ConvError) {
        throw new DönüşümHatası(T.stringof, satır);
    }
}
 
/**
 * Verilen dizgiden yararlanarak belirtilen türde bir değer üretir
 */
T dönüştür(T)(string satır)
{
    static if (is (T == bool)) {
        switch (satır) {
        case "false":
            return false;
 
        case "true":
            return true;
 
        default:
            /* Önemsiz bir ek davranış: Tamsayı değerlerin bool'a
             * dönüşebilmesinin tersi olarak, eğer bir sayıya
             * dönüştürülebiliyorsa ve sayı sıfırdan farklıysa değerinin
             * 'true' olmasını istiyoruz. */
            auto değer = parse!real(satır);
            return değer != 0;
        }
 
    } else static if (is (T == char)) {
        if (satır.length != 1) {
            throw new DönüşümHatası(T.stringof, satır);
        }
        return satır[0];
 
    } else static if (is (T == wchar)) {
        wstring değer = wtext(satır);
        if (değer.length != 1) {
            throw new DönüşümHatası(T.stringof, satır);
        }
        return değer[0];
 
    } else static if (is (T == dchar)) {
        dstring değer = dtext(satır);
        if (değer.length != 1) {
            throw new DönüşümHatası(T.stringof, satır);
        }
        return değer[0];
 
    } else static if (isSomeString!T) {
        return to!T(satır);
 
    } else {
        return parse!T(satır);
    }
}
 
unittest
{
    assert(!dönüştür!bool("false"));
    assert( dönüştür!bool("true"));
    assert(!dönüştür!bool("0"));
    assert( dönüştür!bool("42"));
 
    bool hataAtıldı = false;
 
    try {
        dönüştür!bool("geçersiz bir dizgi");
 
    } catch (Error) {
        hataAtıldı = true;
    }
 
    assert(hataAtıldı);
}
 
} /* private */

Görüldüğü gibi eksikleri var: Birim testleri henüz çok eksik, işlev açıklamaları çok boş; bunları geliştireceğim. Modülü denemek için küçük bir program da yazdım:

import ddio;
import std.stdio;
import std.string;
 
void main()
{
    /*
     * Var olan bir değişkene okuyunca, şablon parametresinin açıkça
     * belirtilmesi gerekmez
     */
    double d;
    oku("Bir double giriniz: ", &d);
    writeln("Karesi = ", d * d);
 
    /*
     * Okunan değerin döndürülmesinin yararlı olduğu durumlarda, şablon
     * parametresinin açıkça belirtilmesi gerekir (çünkü şablon parametresinin
     * çıkarsanacağı işlev parametresi yoktur)
     */
    writeln("İsminizi öğrendim: ", oku!string("İsminiz?"));
    writeln("Yaşınızı öğrendim: ", oku!uint("Yaşınız?"));
 
    /*
     * Değişkenin adresini gönderdiğimiz için immutable dizgilere bile
     * okuyabiliyoruz (immutable dizgilerin bütünüyle değişmesi yasaldır;
     * yasal olmayan, karakterlerinin değiştirilmesidir)
     */
    dstring şehir;
    oku("Yaşadığınız şehir?", &şehir);
    writefln("%s çok güzeldir", şehir);
 
    /* Bütün temel türler ve dizgiler için deneme */
    oku_dene!bool();
    oku_dene!byte();
    oku_dene!ubyte();
    oku_dene!short();
    oku_dene!ushort();
    oku_dene!int();
    oku_dene!uint();
    oku_dene!long();
    oku_dene!ulong();
    oku_dene!float();
    oku_dene!double();
    oku_dene!real();
    oku_dene!char();
    oku_dene!wchar();
    oku_dene!dchar();
    oku_dene!(char[])();
    oku_dene!(wchar[])();
    oku_dene!(dchar[])();
    oku_dene!string();
    oku_dene!wstring();
    oku_dene!dstring();
}
 
void oku_dene(T)()
{
    T okunan = oku!T(format("%s türünde bir değer giriniz:", T.stringof));
    stdout.writefln("Okudum: %s", okunan);
}

Ne dersiniz? ddio.d dosyasını D.ershane'nin girişten bilgi okumayla ilgili olan dersine koysam ve okuyanlardan onu ddio.d ismiyle kardetmelerini istesem? Ek olarak, programlarını oluştururken onu da eklemeleri gerektiğini söylesem:

dmd deneme.d ddio.d -w

Böylece din ve dout'u derslerden çıkartabilirim. Örnek programlar içinde de basitçe oku diyerek girişten bilgi okuyabiliriz.

Ali
Mengu (Moderatör) #2
Kullanıcı başlığı: NONSERVIAM
Üye Tem 2009 tarihinden beri · 347 mesaj · Konum: Dersaadet
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
abi bunu mail listesine gondersen, kullansa zavalli adamlar, negzel olur. :)
http://www.mengu.net - some kind of monster
canalpay (Moderatör) #3
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ı
Ne dersiniz? ddio.d dosyasını D.ershane'nin girişten bilgi okumayla ilgili olan dersine koysam ve okuyanlardan onu ddio.d ismiyle kardetmelerini istesem? Ek olarak, programlarını oluştururken onu da eklemeleri gerektiğini söylesem:

Bence bu projeyi ortalarda bir derste anlatın ve readf yerine bunuda kullanabilirsiniz deyin. İsteyen istediğini kullanır.

abi bunu mail listesine gondersen, kullansa zavalli adamlar, negzel olur. :)

Tamamen katılıyorum.

Kodlara daha bakmadım ama bence bunu bir projeye haline getirin. Biraz daha süsler hatalarından arındırırız ve projeyi duyururuz. Ancak sanırım en azından işlev adlarını ingilizce haline getrimek gerekir. alias ile takma ad takarak bunu halledebiliriz?
acehreli (Moderatör) #4
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ı
canalpay:
Bence bu projeyi ortalarda bir derste anlatın ve readf yerine bunuda kullanabilirsiniz deyin. İsteyen istediğini kullanır.

Aslında isteğe bağlı bir durum değil. Ben bir kaç ay önce derslerden din ve dout'u çıkartmaya başlamıştım ve yerlerine readf vs. yerleştiriyordum. İlk bir kaç derste başarılı oldum ama hemen bir derste "girişten bilgi okuma" işini kolayca halledemedim. :(

Bence tam da o derste "bu konuda bir eksiklik var; o yüzden, bilmediğiniz kodlar içeriyor olsa da, şu dosyayı kaydedin, import edin, ve derleme satırına ekleyin" demek gerek.

ingilizce haline getrimek gerekir. alias ile takma ad takarak bunu halledebiliriz?

Kullanış açısından, dört işlevin adını değiştirmek yeter ama bence bütün kodun İngilizce olması gerek. Herkes kodu görmek isteyecektir; yoksa açık kod sayılmaz. :) Hem okuyabilseler daha güzel öneriler de gelir.

Ali
canalpay (Moderatör) #5
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ı
Aslında isteğe bağlı bir durum değil. Ben bir kaç ay önce derslerden din ve dout'u çıkartmaya başlamıştım ve yerlerine readf vs. yerleştiriyordum.

Ben cstream'i olduğu gibi bırakalım ve bu projeyi tanıtalım demiştim. Her türlü olabilir bence. Ama dilin kütüphanesinde giriş işlevinin bu kadar zorlamasını sevmeyenlerde olacaktır.

Kullanış açısından, dört işlevin adını değiştirmek yeter ama bence bütün kodun İngilizce olması gerek. Herkes kodu görmek isteyecektir; yoksa açık kod sayılmaz. :) Hem okuyabilseler daha güzel öneriler de gelir.

Bencede tamamen doğru.


Bu arada
            stdout.write(mesaj ~ ' ');
Bence mesajdan sonra kendisinin otomatik boşluk koyması doğru değil.

T oku(T)(string mesaj)

Sanki string olarak belirtilmesede write gibi her türlü değeri gösterebilse. Hemde çokuzlu olarak.

Kodları çalıştırmadım ancak
T oku(T)()
{
    return oku!T("");
}

gerekli mi ?

Onun yerine asıl işlev
T oku(T)(string mesaj="")
olabilir mi? Hmm o zaman string yerine şablon kullanırsak sorun yaşayabiliriz.
acehreli (Moderatör) #6
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ı
canalpay:
Ben cstream'i olduğu gibi bırakalım ve bu projeyi tanıtalım demiştim.

Tamamdır. Zaten cstream'i teker teker çıkartmaya başlamıştım.

Ama dilin kütüphanesinde giriş işlevinin bu kadar zorlamasını sevmeyenlerde olacaktır.

Durumu yumuşak bir dille anlatırız. :)

Aslında bu olay bizim dışımızda büyük bir sorun da değil galiba; zaten öyle olsaydı başkaları da şikayet ederdi. Standart girişten kullanıcıyla etkileşmek çok yaygın değil aslında.

Hmmm. Acaba ben de daha çok komut satırı parametrelerine mi odaklansaymışım...

            stdout.write(mesaj ~ ' ');
Bence mesajdan sonra kendisinin otomatik boşluk koyması doğru değil.

Kabul; çıkartıyorum.

T oku(T)(string mesaj)

Sanki string olarak belirtilmesede write gibi her türlü değeri gösterebilse. Hemde çokuzlu olarak.

O konuyu ben de düşündüm. Aslında elimizde zaten format gibi bir araç bulunduğu araç için her işlevin çokuzlu (tuple) desteklemesi gerekmemiş olur. Ama eğer derslerin başında format kullanımını ortadan kaldıracaksa neden olmasın. Hatta sanırım bütün iş, çokuzluyu olduğu gibi format'a vermek oluyordu. (Unutmuşum! :) )

T oku(T)()
{
    return oku!T("");
}

gerekli mi ?

Kodu gönderdikten sonra orasını değiştirdim aslında. "Boş dizgi"ye özel bir anlam vermek yerine, elimizde zaten bulunan null kavramını kullandım:

    static string boşMesaj;
    return oku!T(boşMesaj);

ve sonra denetlerken:

        if (mesaj !is null) {
            stdout.write(mesaj);
        }

Onun yerine asıl işlev
T oku(T)(string mesaj="")
olabilir mi? Hmm o zaman string yerine şablon kullanırsak sorun yaşayabiliriz.

Haklısın! :) O işlevi bütünüyle kaldırmış oldum. Böylece işlevler üçe indi:

T oku(T)(string mesaj = null);
void oku(T)(string mesaj, T * değişken);
void oku(T)(T * değişken);

Aynı numarayı son ikisi için yapamıyoruz çünkü varsayılan değeri olan parametrelerin listenin sonunda olmaları gerekir, be bana mesajı sona koymak daha mantıksız geliyor:

    oku(&şehir, "Yaşadığınız şehir? ");

Olabilir de ama bence önceki sırası daha iyi.

Ali
acehreli (Moderatör) #7
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ı
Son hali:

/**
 * ddio.d - D.ershane'deki kod örneklerinde yararlanılan standart giriş/çıkış
 * dosyası
 *
 *   http://ddili.org/ders/d/index.html
 */
 
module ddio;
 
import std.stdio;
import std.string;
import std.conv;
import std.traits;
 
/**
 * Verilen mesajı standart çıkışa yazdırır, ve standart girişten belirtilen
 * türde bir değer okur
 */
T oku(T)(string mesaj = null)
{
    while (true) {
        if (mesaj !is null) {
            stdout.write(mesaj);
        }
 
        string satır;
        while (satır.length == 0) {
            satır = strip(stdin.readln());
        }
 
        try {
            return dönüştürmeyiDene!T(satır);
 
        } catch (DönüşümHatası hata) {
            writef("HATA: %s", hata);
 
            /* Karakter ve dizgi türleri için "değer aralığı" kavramı kolay
             * tanımlanamadığı için bu mesajı yalnızca diğer türler için
             * gösteriyoruz. */
            static if (!isSomeChar!T && !isSomeString!T) {
                writef("; Geçerli değer aralığı: [%s, %s]", T.min, T.max);
            }
 
            writeln();
            stdin.clearerr();
        }
    }
}
 
/**
 * Diğer oku() işlevlerine benzer şekilde işler; farklı olarak, var olan bir
 * değişkene okuduğu için şablon parametresinin açıkça belirtilmesi gerekmez
 */
void oku(T)(string mesaj, T * değişken)
{
    *değişken = oku!T(mesaj);
}
 
/**
 * Diğer oku() işlevlerine benzer şekilde işler; farklı olarak, var olan bir
 * değişkene okuduğu için şablon parametresinin açıkça belirtilmesi gerekmez,
 * ve çıktıya bir mesaj yazdırmaz
 */
void oku(T)(T * değişken)
{
    *değişken = oku!T();
}
 
private {
 
/**
 * Dönüşüm hatalarını bildirmede kullanılan tür
 *
 * Not: Bunun yerine, Phobos'un dönüşüm hatası durumlarında zaten atmakta
 * olduğu std.conv.ConvError türünü de kullanabilirdik; ancak o hatanın
 * çıktısı, bizim ihtiyacımız dışında bilgiler de taşıdığı için fazla
 * kalabalık oluyor.
 */
class DönüşümHatası : Exception
{
    string tür;
    string değer;
 
    this(string tür, string değer)
    {
        this.tür = tür;
        this.değer = değer;
 
        super(this.toString());
    }
 
    override string toString()
    {
        return format("'%s', %s türüne dönüştürülemez", değer, tür);
    }
}
 
/**
 * Gereken dönüşümü gerçekleştirmeyi dener; olası ConvError hatalarını
 * DönüşümHatası türüne dönüştürür
 */
T dönüştürmeyiDene(T)(string satır)
{
    try {
        return dönüştür!T(satır);
 
    } catch (ConvError) {
        throw new DönüşümHatası(T.stringof, satır);
    }
}
 
/**
 * Verilen dizgiden yararlanarak belirtilen türde bir değer üretir
 */
T dönüştür(T)(string satır)
{
    static if (is (T == bool)) {
        switch (satır) {
        case "false":
            return false;
 
        case "true":
            return true;
 
        default:
            /* Önemsiz bir ek davranış: Tamsayı değerlerin bool'a
             * dönüşebilmesinin tersi olarak, eğer bir sayıya
             * dönüştürülebiliyorsa ve sayı sıfırdan farklıysa değerinin
             * 'true' olmasını istiyoruz. */
            auto değer = parse!real(satır);
            return değer != 0;
        }
 
    } else static if (is (T == char)) {
        if (satır.length != 1) {
            throw new DönüşümHatası(T.stringof, satır);
        }
        return satır[0];
 
    } else static if (is (T == wchar)) {
        wstring değer = wtext(satır);
        if (değer.length != 1) {
            throw new DönüşümHatası(T.stringof, satır);
        }
        return değer[0];
 
    } else static if (is (T == dchar)) {
        dstring değer = dtext(satır);
        if (değer.length != 1) {
            throw new DönüşümHatası(T.stringof, satır);
        }
        return değer[0];
 
    } else static if (isSomeString!T) {
        return to!T(satır);
 
    } else {
        return parse!T(satır);
    }
}
 
unittest
{
    assert(!dönüştür!bool("false"));
    assert( dönüştür!bool("true"));
    assert(!dönüştür!bool("0"));
    assert( dönüştür!bool("42"));
 
    bool hataAtıldı = false;
 
    try {
        dönüştür!bool("geçersiz bir dizgi");
 
    } catch (Error) {
        hataAtıldı = true;
    }
 
    assert(hataAtıldı);
}
 
} /* private */
 
import ddio;
import std.stdio;
import std.string;
 
void main()
{
    /*
     * Var olan bir değişkene okuyunca, şablon parametresinin açıkça
     * belirtilmesi gerekmez
     */
    double d;
    oku("Var olan bir double'ın değerini giriniz: ", &d);
    writefln("%s x %s = %s", d, d, d * d);
 
    short s;
    write("Var olan bir short'un değerini mesajsız olarak giriniz -> ");
    oku(&s);
    writeln("Okuduk: ", s);
 
    /*
     * Okunan değerin döndürülmesinin yararlı olduğu durumlarda, şablon
     * parametresinin açıkça belirtilmesi gerekir (çünkü şablon parametresinin
     * çıkarsanacağı işlev parametresi yoktur)
     */
    writeln("İsminizi öğrendim: ", oku!string("İsminiz? "));
    writeln("Yaşınızı öğrendim: ", oku!uint("Yaşınız? "));
 
    /*
     * Değişkenin adresini gönderdiğimiz için immutable dizgilere bile
     * okuyabiliyoruz (immutable dizgilerin bütünüyle değişmesi yasaldır;
     * yasal olmayan, karakterlerinin değiştirilmesidir)
     */
    dstring şehir;
    oku("Yaşadığınız şehir? ", &şehir);
    writefln("%s çok güzeldir!", şehir);
 
    write("Bu int'i mesajsız okuyoruz -> ");
    writeln("Okuduk: ", oku!int());
 
    /* Bütün temel türler ve dizgiler için deneme */
    oku_dene!bool();
    oku_dene!byte();
    oku_dene!ubyte();
    oku_dene!short();
    oku_dene!ushort();
    oku_dene!int();
    oku_dene!uint();
    oku_dene!long();
    oku_dene!ulong();
    oku_dene!float();
    oku_dene!double();
    oku_dene!real();
    oku_dene!char();
    oku_dene!wchar();
    oku_dene!dchar();
    oku_dene!(char[])();
    oku_dene!(wchar[])();
    oku_dene!(dchar[])();
    oku_dene!string();
    oku_dene!wstring();
    oku_dene!dstring();
}
 
void oku_dene(T)()
{
    T okunan = oku!T(format("%s türünde bir değer giriniz: ", T.stringof));
    stdout.writefln("Okudum: %s", okunan);
}

Ali
acehreli (Moderatör) #8
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ı
Peki diziler ve eşleme tabloları ne olacak? :) Şu satır, bir derleme hatasına neden oluyor:

    oku_dene!(int[])();

Çünkü T dönüştür(T)(string satır) şablonu içinde dizilere özel bir static if bulunmuyor ve onlar için de else kapsamı seçiliyor. else'in içindeki parse!T(satır) ifadesi de dizilerle kullanılamadığı için derleme hatası oluşuyor.

(Not: Aslında dizgiler de dizidir tabii ama onları özel olarak hallediyoruz.)

Şimdi amaç kodu geliştirmek ve dizi ve eşleme tablosu okumayı da desteklemek. Önce dinamik dizilerden başlayalım; sabit uzunluklu dizileri ve eşleme tablolarını sonraya bırakalım.

Derleme hatasını giderebilmek için şöyle iki değişiklik yapabiliriz:

1) dönüştür işlevindeki static if zincirine bir koşul daha ekleyelim:

    /* ... */
 
    } else static if (isDynamicArray!T) {
        T dizi;
 
        foreach (i; 0 .. 3) {
            dizi ~= 42;
        }
 
        return dizi;
 
    } else {
        return parse!T(satır);
    }

(Not: Sabit uzunluklu diziler için isStaticArray, eşleme tabloları için de isAssociativeArray kullanılır.)

2) Dinamik dizilerin de .min ve .max nitelikleri bulunmadığı için, yardımcı mesajı onlar için de göstermeyelim (yoksa derleme hatası oluyor). :

            static if (!isSomeChar!T &&
                       !isSomeString!T &&
                       !isDynamicArray!T) {
                writef("; Geçerli değer aralığı: [%s, %s]", T.min, T.max);
            }

Şimdi, örneğin şöyle deneyebiliriz:

    int[] sayılar = oku!(int[])("Bir int dizisi giriniz: ");
    writeln("Okudum: ", sayılar);

Çıktısı:

$ ./deneme
Bir int dizisi giriniz: merhaba
Okudum: [42, 42, 42]


Gördüğünüz gibi, ne girilirse girilsin, üç 42'den oluşan bir dizi döndürüyor. Bu konuyla uğraşmak ister misiniz?

Sanırım yine conv.parse kullanılabilir. Belgesindeki örnekte, bir satırdan nasıl birden fazla veri çekilebildiği görülüyor:

  http://digitalmars.com/d/2.0/phobos/std_conv.html#parse

string test = "123 \t  76.14";
auto a = parse!(uint)(test);
assert(a == 123);
assert(test == " \t  76.14"); // parse bumps string (parse, dizgiyi ilerletir)
munch(test, " \t\n\r"); // skip ws (boşlukları atla)
assert(test == "76.14");
auto b = parse!(double)(test);
assert(b == 76.14);
assert(test == "");

İleriye bırakılacak işler:

- sayıların aralarında ayraçlar ve etraflarında köşeli parantezler girilebilmeli mi?

- dizi birden fazla satırda girilebilmeli mi? (Bu, herhalde tasarımda değişiklik gerektirir)

Ali
canalpay (Moderatör) #9
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ı
Bu arada bence ddio için bir çıkış işlevi yazmalıyız. http://d.puremagic.com/issues/buglist.…?query_format=spe… Örneğin bağlantıdaki önemli hataları çok profesyonelce olmadanda olsa yamalamalıyız. Daha sonra okuma işlevini yamalarız.

Bu oku'nun yanında yaz adında yeni bir işlev gerekiyor demek :-)

Bu arada çok güzel oldu. Acaba dosya yazma/okuma ile ilgili işlevlerde eklenmeli mi?
acehreli (Moderatör) #10
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ı
canalpay:
Bu arada bence ddio için bir çıkış işlevi yazmalıyız.

Ben bunu D.ershane kapsamında tutmaktan yanayım. Derslerdeki örnekleri sıkıntıya sokacak bir kısıtlamayla karşılaşırsak düzeltiriz.

Acaba dosya yazma/okuma ile ilgili işlevlerde eklenmeli mi?

Buradaki işlevleri standart girişe bağlayan tek şey, stdin.readln() çağrısı. (Aslında bir de, eğer hatalı bir duruma girmişse giriş akımını o durumdan çıkartmaya yarayan, ama olasılıkla gereksiz olan stdin.clearerr().)

Eğer bu işlevlere giriş akımını da belirtebilsek, bu iş tamam olur. Çünkü readln aslında File türünün bir üye işlevi. Eğer File türündeki dosyayı zaten açmışsak:

            satır = strip(dosya.readln());

dosya'nın oku'ya bir şekilde verilmesi gerekir: örneğin işlev parametresi olabilir. Veya; dosyayı barındıran bir nesne olabilir; oku, onun bir üye işlevi olur:

    Okuyucu(stdin).oku!int();   // stdin'den
    Okuyucu(dosya).oku!int();   // dosya'dan 

Ama başka bir konuyu da düşünmek gerek: Mesajın stdout'a yazılıyor olmasına bakarsak, burada kullanıcıyla bir etkileşim söz konusu. Yani amaç, bir insanla etkileşmek. stdout'a yazıp sonra dosyadan okumak garip olur. Öte yandan, mesaj yazdırmayan yüklemelerini kullanırsak öyle bir gariplik de kalmaz tabii. :)

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-19, 00:40:41 (UTC -08:00)