Üçlü İşleç ?:
?:
işleci, temelde bir if-else
deyimi gibi çalışır:
if (/* koşul */) { /* doğruluk işlemleri */ } else { /* doğru olmama işlemleri */ }
if
deyimi, koşul doğru olduğunda doğruluk işlemlerini, aksi durumda diğer işlemleri işletir. Hatırlarsanız, if
bir deyimdir ve bu yüzden kendi değeri yoktur; tek etkisi, programın işleyişini etkilemesidir.
?:
işleci ise bir ifadedir ve if-else
ile aynı işi, ama bir değer üretecek şekilde gerçekleştirir. Yukarıdaki kodu ?:
kullanarak şöyle yazabiliriz (bölüm açıklamalarını kısaltarak gösteriyorum):
/* koşul */ ? /* doğruluk işlemi */ : /* doğru olmama işlemi */
?:
işleci üç bölümündeki üç ifade yüzünden üçlü işleç olarak adlandırılır.
Bu işlecin değeri; koşula bağlı olarak ya doğruluk işleminin, ya da doğru olmama işleminin değeridir. İfade olduğu için, ifadelerin kullanılabildiği her yerde kullanılabilir.
Aşağıdaki örneklerde aynı işi hem ?:
işleci ile, hem de if
deyimi ile gerçekleştireceğim. ?:
işlecinin bu örneklerdeki gibi durumlarda çok daha kısa olduğunu göreceksiniz.
- İlkleme
Artık yıl olduğunda 366, olmadığında 365 değeri ile ilklemek için:
int günAdedi = artıkYıl ? 366 : 365;
Aynı işi
if
ile yapmak istesek; bir yol, baştan hiç ilklememek ve değeri sonra vermektir:int günAdedi; if (artıkYıl) { günAdedi = 366; } else { günAdedi = 365; }
if
ile başka bir yol; baştan artık yıl değilmiş gibi ilklemek ve adedi sonra bir arttırmak olabilir:int günAdedi = 365; if (artıkYıl) { ++günAdedi; }
- Yazdırma
Yazdırılan bir mesajın bir parçasını
?:
ile duruma göre farklı yazdırmak:writeln("Bardağın yarısı ", iyimser ? "dolu" : "boş");
Aynı işi yapmak için mesajın baş tarafını önce yazdırabilir ve gerisini sonra
if
ile seçebiliriz:write("Bardağın yarısı "); if (iyimser) { writeln("dolu"); } else { writeln("boş"); }
if
ile başka bir yol, bütün mesajı farklı olarak yazdırmaktır:if (iyimser) { writeln("Bardağın yarısı dolu"); } else { writeln("Bardağın yarısı boş"); }
- Hesap
Tavla puanını mars olup olmama durumuna göre
?:
ile 2 veya 1 arttırmak:tavlaPuanı += marsOldu ? 2 : 1;
if
ile puanı duruma göre 2 veya 1 arttırmak:if (marsOldu) { tavlaPuanı += 2; } else { tavlaPuanı += 1; }
if
ile başka bir yol; baştan bir arttırmak ve mars ise bir kere daha arttırmak olabilir:++tavlaPuanı; if (marsOldu) { ++tavlaPuanı; }
Bu örneklerden görüldüğü gibi kod ?:
işleci ile çok daha kısa olmaktadır.
Üçlü işlecin türü
?:
işlecinin değeri denetlenen koşula bağlı olarak ya doğruluk ifadesinin ya da doğru olmama ifadesinin değeridir. Bu iki ifadenin ortak bir türlerinin bulunması şarttır.
Ortak tür, oldukça karmaşık bir yöntemle ve iki tür arasındaki tür dönüşümü ve türeme ilişkilerine de bağlı olarak seçilir. Ek olarak, ortak türün çeşidi ya sol değerdir ya da sağ değer. Bu kavramları ilerideki bölümlerde göreceğiz.
Şimdilik, ortak türü açıkça tür dönüşümü gerektirmeden her iki değeri de tutabilen bir tür olarak kabul edin. Örneğin, int
ve long
türleri için ortak bir tür vardır çünkü her ikisi de long
türü ile ifade edilebilir. Öte yandan, int
ve string
türlerinin ortak bir türü yoktur çünkü ikisi de diğerine otomatik olarak dönüşemez.
Hatırlarsanız, bir ifadenin türü typeof
ve .stringof
ile öğrenilebilir. Bu yöntem üçlü ifade için seçilen ortak türü öğrenmek için de kullanılabilir:
int i; double d; auto sonuç = birKoşul ? i : d; writeln(typeof(sonuç).stringof);
double
türü int
değerlerini ifade edebildiğinden (ve bunun tersi doğru olmadığından), yukarıdaki üçlü ifadenin türü double
olarak seçilmiştir:
double
Geçerli olmayan bir örnek olarak bir forum sitesinin oluşturduğu bir mesaja bakalım. Bağlı olan kullanıcı sayısı 1 olduğunda mesaj "Tek" kelimesi ile yazılsın: "Tek kullanıcı bağlı". Kullanıcı sayısı 1'den farklı olduğunda ise rakamla gösterilsin: "3 kullanıcı bağlı".
"Tek" ve 3 arasındaki seçim ?:
işleciyle doğrudan yapılamaz:
writeln((adet == 1) ? "Tek" : adet, // ← derleme HATASI " kullanıcı bağlı");
Ne yazık ki o kod yasal değildir çünkü koşul sonucunda seçilecek iki ifadenin ortak türü yoktur: "Tek"
bir string
olduğu halde, adet
bir int
'tir.
Çözüm olarak adet
'i de string
'e dönüştürebiliriz. std.conv
modülünde bulunan to!string
işlevi kendisine verilen ifadenin string
karşılığını üretir:
import std.conv; // ... writeln((adet == 1) ? "Tek" : to!string(adet), " kullanıcı bağlı");
Bu durumda ?:
işlecinin her iki ifadesi de string
olduğundan kod hatasız olarak derlenir ve çalışır.
Problem
Program kullanıcıdan bir tamsayı değer alsın; bu değerin sıfırdan küçük olması zararda olmak, sıfırdan büyük olması da kazançlı olmak anlamına gelsin.
Program verilen değere göre sonu "zarardasınız" veya "kazançlısınız" ile biten bir mesaj yazdırsın. Örneğin "100 lira zarardasınız" veya "70 lira kazançlısınız". Daha uygun görseniz bile bu bölümle ilgili olabilmesi için if
koşulunu kullanmayın.