D.ershane D Programlama Dili Dersleri

düzen: [format], bilginin giriş ve çıkışta nasıl düzenlendiği
iç olanak: [core feature], dilin kütüphane gerektirmeyen bir olanağı
işaretli tür: [signed type], eksi ve artı değer alabilen tür
işaretsiz tür: [unsigned type], yalnızca artı değer alabilen tür
işlev: [function], programdaki bir kaç adımı bir araya getiren program parçası
parametre: [parameter], işleve işini yapması için verilen bilgi
parametre değeri: [argument], işleve parametre olarak verilen bir değer
Phobos: [Phobos], D dilinin standart kütüphanesi
... bütün sözlük

Bölümler
İngilizce Kaynaklar
Diğer



Çıktı Düzeni

Diğer derslerden farklı olarak, bu bölüm D dilinin iç olanaklarıyla ilgili değil. Burada anlatılanlar tamamen kütüphane olanakları olarak gerçekleştirilmişlerdir ve Phobos'un çıktı düzeni için kullandığı std.format modülünün olanaklarıdır.

D'nin giriş ve çıkış için kullandığı düzen belirteçlerinin temelde C dilindekiler gibi olduğunu ama bazı farkları bulunduğunu göreceksiniz.


Bir ön hatırlatma olarak bütün düzen dizgisi karakterleri aşağıdaki tablodaki gibidir:

Ayar Karakterleri (birden fazla kullanılabilir)
     -     sola dayalı
     +     işaretli
     #     diğer şekilde
     0     solda 0'lı
  boşluk   solda boşluklu

Düzen Karakterleri
     s     belirteçsiz gibi
     b     ikili
     d     onlu
     o     sekizli
     x,X   onaltılı
     e,E   on üzerili
     f,F   virgüllü
     g,G   e veya f gibi
     a,A   onaltılı kesirli

Şimdiye kadar çıktı için writeln gibi işlevleri gerektiğinde birden fazla parametreyle kullanmıştık. Bu parametreler otomatik olarak karakter eşdeğerlerine dönüştürülerek sırayla çıkışa gönderiliyorlardı.

Bazen bu yeterli değildir. Çıktının belirli bir düzene uyması gerekebilir. Örneğin bir faturanın maddelerini yazdıran şu koda bakalım:

    faturaMaddeleri ~= 1.23;
    faturaMaddeleri ~= 45.6;

    for (int i = 0; i != faturaMaddeleri.length; ++i) {
        writeln("Madde ", i + 1, ": ", faturaMaddeleri[i]);
    }

Çıktısı:

Madde 1: 1.23
Madde 2: 45.6

Oysa faturadaki değerlerin belirli bir düzende, örneğin her zaman için virgülden sonra iki haneyle ve geniş bir alanda sağa dayalı olarak yazılmaları okuma açısından önemli olabilir. (Not: Ben bu derste günlük kullanıma uygun olarak "virgül" diyeceğim; ama kesirli sayılarda virgül yerine nokta karakteri kullanılır.):

Madde 1:     1.23
Madde 2:    45.60

İşte çıktı düzeni, böyle konularda yarar sağlar. Şimdiye kadar kullandığımız çıktı işlevlerinin isminde f harfi geçen karşılıkları da vardır: writef() ve writefln(). İsimlerindeki f harfi "düzen, biçim" anlamına gelen "format"ın kısaltmasıdır. Bu işlevlerin ilk parametresi diğer parametrelerin nasıl yazdırılacaklarını belirleyen düzen dizgisidir.

Örneğin yukarıdaki çıktıyı veren bir düzen dizgisi writefln ile şöyle yazılabilir:

    writefln("Madde %d:%9.02f", i + 1, faturaMaddeleri[i]);

Düzen dizgisi, normal karakterlerden ve özel düzen belirteçlerinden oluşur. Her düzen belirteci % karakteriyle başlar ve bir düzen karakteri ile biter. Yukarıdaki dizgide iki tane düzen belirteci var: %d ve %9.02f.

Her belirteç, düzen dizgisinden sonra verilen parametrelerle sıra ile eşleşir. Örneğin %d ile i + 1, ve %9.02f ile faturaMaddeleri[i]... Her belirteç, eşleştiği parametrenin çıktı düzenini belirler. (Düzen belirteçlerinde parametre numaraları da kullanılabilir. Bunu aşağıda göstereceğim.)

Düzen dizgisi içinde bulunan ve belirteçlere ait olmayan karakterler, oldukları gibi yazdırılırlar. Yukarıdaki dizgi içindeki normal karakterleri kırmızı renkle şöyle gösterebiliriz: "Madde %d:%9.02f".

Düzen belirteci, çoğunun belirtilmesi gerekmeyen altı parçadan oluşur. Bu bölümlerden birisi olan numara'yı daha aşağıda göstereceğim. Diğer beş bölüm şunlardır (Not: okumayı kolaylaştırmak için aralarında boşluk kullanıyorum; bu bölümler aslında bitişik olarak yazılırlar):

   %  ayar_karakterleri  genişlik  duyarlık  düzen_karakteri

Baştaki % karakterinin ve sondaki düzen karakterinin yazılması şarttır, diğerleri ise isteğe bağlıdır.

% karakterinin böyle özel bir anlamı olduğu için, çıktıda % karakterinin kendisi yazdırılmak istendiğinde %% şeklinde çift olarak yazılır.

düzen_karakteri

b: Tamsayı, ikili sayı düzeninde yazdırılır.

o: Tamsayı, sekizli sayı düzeninde yazdırılır.

x ve X: Tamsayı, onaltılı sayı düzeninde yazdırılır; x için küçük harfler, X için büyük harfler kullanılır.

d: Tamsayı, onlu sistemde yazdırılır; eğer işaretli bir türse ve değeri sıfırdan küçükse, başına eksi işareti gelir; aksi durumda işaretsiz bir tür gibi yazdırılır.

    int değer = 12;

    writefln("İkili   : %b", değer);
    writefln("Sekizli : %o", değer);
    writefln("Onaltılı: %x", değer);
    writefln("Ondalık : %d", değer);
İkili   : 1100
Sekizli : 14
Onaltılı: c
Ondalık : 12

e: Kesirli sayı, aşağıdaki bölümlerden oluşacak şekilde yazdırılır.

E: e ile aynı düzende, ama çıktıda E harfiyle

f ve F: Kesirli sayı, onlu sistemde yazdırılır; virgülden önce en az bir hane bulunur; varsayılan duyarlık 6'dır.

g: Kesirli sayı, eğer üs değeri -5 ile duyarlık arasında olacaksa, f gibi; değilse e gibi yazdırılır. duyarlık virgülden sonrasını değil, belirgin hane sayısını belirtir; virgülden sonra belirgin hane yoksa virgül de yazdırılmaz; virgülden sonra en sağdaki sıfırlar yazdırılmazlar.

G: g ile aynı düzende, ama E veya F kullanılmış gibi yazdırılır

a: Kesirli sayı, onaltılı sistemde ve aşağıdaki bölümlerden oluşacak şekilde yazdırılır:

A: a ile aynı düzende, ama çıktıda 0X ve P karakterleriyle

    double değer = 123.456789;

    writefln("e ile: %e", değer);
    writefln("f ile: %f", değer);
    writefln("g ile: %g", değer);
    writefln("a ile: %a", değer);
e ile: 1.234568e+02
f ile: 123.456789
g ile: 123.457
a ile: 0x1.edd3c07ee0b0bp+6

s: Parametrenin değeri; düzen dizgisi kullanılmadığı zamandaki gibi, türüne uygun olan şekilde yazdırılır:

    bool b = true;
    int i = 365;
    double d = 9.87;
    string s = "düzenli";
    auto n = File("deneme_dosyasi", "r");
    int[] dz = [ 2, 4, 6, 8 ];

    writefln("bool  : %s", b);
    writefln("int   : %s", i);
    writefln("double: %s", d);
    writefln("string: %s", s);
    writefln("nesne : %s", n);
    writefln("dizi  : %s", dz);
bool  : true
int   : 365
double: 9.87
string: düzenli
nesne : File(55738FA0)
dizi  : [2, 4, 6, 8]
genişlik

Değer için çıktıda ayrılan alanın genişliğini belirler. Eğer genişlik olarak * kullanılmışsa, genişlik değeri bir sonraki parametrenin değeri olarak alınır. Eğer eksi bir sayıysa, - ayar karakteri kullanılmış gibi çalışır.

    int değer = 100;

    writefln("On karakterlik alanda :%10s", değer);
    writefln("Beş karakterlik alanda:%5s", değer);
On karakterlik alanda :       100
Beş karakterlik alanda:  100
duyarlık

Eğer belirtilmişse, nokta karakterinden sonra yazılır. Kesirli sayı türünden olan değerlerin çıktıda kullanılacak olan duyarlığını belirler. Eğer duyarlık olarak * kullanılmışsa, duyarlık değeri bir sonraki parametrenin değeri olarak alınır (o değer int olmak zorundadır). Duyarlık eksi bir sayıysa gözardı edilir.

    double kesirli = 1234.56789;

    writefln("%.8g", kesirli);
    writefln("%.3g", kesirli);
    writefln("%.8f", kesirli);
    writefln("%.3f", kesirli);
1234.5679
1.23e+03
1234.56789000
1234.568
    auto sayı = 0.123456789;
    writefln("Sayı: %.*g", 4, sayı);
Sayı: 0.1235
ayar_karakterleri

Birden fazla ayar karakteri kullanabilirsiniz.

-: parametre değeri; kendisine ayrılan alanda sola dayalı olarak yazdırılır; bu ayar, 0 ayar karakterini geçersiz kılar

    int değer = 123;

    writefln("normalde sağa dayalı:|%10d|", değer);
    writefln("sola dayalı         :|%-10d|", değer);
normalde sağa dayalı:|       123|
sola dayalı         :|123       |

+: değer artı ise başına + karakteri yazdırılır; bu ayar, boşluk ayar karakterini geçersiz kılar

    writefln("eksi değerde etkili değil: %+d", -50);
    writefln("artı değer, + ile        : %+d", 50);
    writefln("artı değer, + olmadan    : %d", 50);
eksi değerde etkili değil: -50
artı değer, + ile        : +50
artı değer, + olmadan    : 50

#: kullanılan düzen_karakteri'ne bağlı olarak, değeri başka şekilde yazdırır

    writefln("Sekizli sıfırla başlar        : %#o", 1000);
    writefln("Onaltılının başına 0x gelir   : %#x", 1000);

    writefln("Gerekmese de virgüllü olur    : %#g", 1f);
    writefln("Sağdaki sıfırlar da yazdırılır: %#g", 1.2);
Sekizli sıfırla başlar        : 01750
Onaltılının başına 0x gelir   : 0x3e8
Gerekmese de virgüllü olur    : 1.00000
Sağdaki sıfırlar da yazdırılır: 1.20000

0: sayılarda (değer nan veya infinity değilse), sol tarafa değer için ayrılan alan dolacak kadar 0 yazdırılır; duyarlık da belirtilmişse bu ayar etkisizdir

    writefln("Sekiz genişlikte: %08d", 42);
Sekiz genişlikte: 00000042

boşluk karakteri: değer artı ise, eksi değerlerle alt alta düzgün dursun diye başına tek bir boşluk karakteri yazdırılır

    writefln("Eksi değerde etkisi yok: % d", -34);
    writefln("Artı değer, boşluklu   : % d", 56);
    writefln("Artı değer, boşluksuz  : %d", 56);
Eksi değerde etkisi yok: -34
Artı değer, boşluklu   :  56
Artı değer, boşluksuz  : 56
Parametre numaraları

Yukarıda düzen dizgisi içindeki düzen belirteçlerinin parametrelerle teker teker ve sırayla eşleştirildiklerini gördük. Aslında düzen belirtecinde parametre numarası da kullanılabilir. Bu, belirtecin hangi parametre ile ilgili olduğunu belirler. Parametreler 1'den başlayarak artan sırada numaralanırlar. Parametre numarası % karakterinden hemen sonra ve $ karakteri ile birlikte yazılır:

   %  numara$  ayar_karakterleri  genişlik  duyarlık  düzen_karakteri

Bunun bir yararı, aynı parametrenin birden fazla yerde yazdırılabilmesidir:

    writefln("%1$d %1$x %1$o %1$b", 42);

Yukarıdaki düzen dizgisi 1 numaralı parametreyi dört düzen belirteci yoluyla onlu, onaltılı, sekizli, ve ikili sayı sistemlerinde yazdırmaktadır:

42 2a 52 101010

Parametre numaralarının bir diğer kullanım alanı, aynı parametrelerin farklı düzen dizgileriyle kullanılabilmesi ve bu sayede mesajların farklı konuşma dillerinin yazım kurallarına uydurulabilmesidir. Örneğin belirli bir dersteki öğrenci sayısı Türkçe olarak şöyle bildiriliyor olsun:

    writefln("%s sınıfında %s öğrenci var.", sınıf, adet);
1A sınıfında 20 öğrenci var.

Programın örneğin İngilizce'yi de desteklemesi gerektiğini düşünelim. Bu durumda düzen dizgisinin dile uygun olarak daha önceden seçilmiş olması gerekir. Aşağıdaki yöntem bu iş için üçlü işleçten yararlanıyor:

    auto düzenDizgisi = (dil == "tr"
                         ? "%s sınıfında %s öğrenci var."
                         : "There are %s students in room %s.");

    writefln(düzenDizgisi, sınıf, adet);

Ne yazık ki, parametreler düzen belirteçleriyle birer birer eşleştirildiklerinde sınıf ve adet bilgileri İngilizce mesajda ters sırada çıkarlar. Sınıf bilgisi adet yerinde, adet bilgisi de sınıf yerindedir:

There are 1A students in room 20. ← Yanlış: Adet 1A, sınıf 20!

Bunun önüne geçmek için düzen dizgisinde hangi belirtecin hangi parametreye karşılık geldiği 1$ ve 2$ biçiminde parametre numaralarıyla belirtilebilir:

    auto düzenDizgisi = (dil == "tr"
                         ? "%1$s sınıfında %2$s öğrenci var."
                         : "There are %2$s students in room %1$s.");

    writefln(düzenDizgisi, sınıf, adet);

Artık mesajın hem Türkçesi hem de İngilizcesi düzgündür:

1A sınıfında 20 öğrenci var.
There are 20 students in room 1A.
Problemler
  1. Girilen tamsayıyı onaltılı düzende yazdıran bir program yazın.
  2. Girilen kesirli sayıyı bir yüzde değeri olarak ve virgülden sonra 2 haneyle yazdıran bir program yazın. Örneğin 1.2345 girildiğinde ekrana yalnızca %1.23 yazsın.

... çözümler