Subject: 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:
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:
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:
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
Ö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
acehreli
Show profile
Link to this post
