switch deyimi

switch deyimi bir tamsayı ifadesinin farklı değerleri için, programın akışının farklı noktalara yönlendirilmesini, böylece farklı işlerin yapılmasını sağlar. switch deyimi, else if merdivenine (else if ladder) okunabilirlik yönünden bir seçenek oluşturur. Deyimin genel biçimi aşağıdaki gibidir:

switch, case, default C dilinin anahtar sözcükleridir.

switch deyiminin yürütülmesi

switch parantezi içindeki ifadenin sayısal değeri hesaplanır. Bu değerde bir case ifadesi olup olmadığı sınanır. Eğer böyle bir case ifadesi bulunursa programın akışı o case ifadesini izleyen deyime yönlendirilir. Artık program buradan akarak ilerler. Daha aşağıdaki diğer deyimler de yapılır (fall through)switch parantezi içindeki ifadenin sayısal değerine eşit bir case ifadesi yok ise, programın akışı (varsa) default anahtar sözcüğünü izleyen deyime yönlendirilir.

Yukarıdaki örnekte scanf işlevi ile, standart giriş akımından n değişkenine 3 değeri alınmış olsun. Bu durumda programın ekran çıktısı şu şekilde olur:

Eğer uygun case ifadesi bulunduğunda yalnızca bu ifadeye ilişkin deyim(ler)in yürütülmesi istenirse break kontrol deyiminden faydalanılır. break deyiminin kullanılmasıyla, döngülerden olduğu gibi switch deyiminden de çıkılabilir. Daha önce verilen örnekteki koda break deyimlerini ekliyoruz:

Yukarıdaki kodda scanf işlevi ile, standart giriş akımından n değişkenine yine 3 değeri alınmış olsun. Bu durumda programın ekran çıktısı şu şekilde olur:

Uygulamalarda, switch deyiminde çoğunlukla her case ifadesi için bir break deyimi kullanılır. Tabi böyle bir zorunluluk yoktur.
switch deyiminin ana bloğu tek bir bilinirlik alanı (scope) kabul edilir. Bir case etiketini birden fazla deyimin izlemesi durumunda bu deyimlerin bloklanmasına gerek yoktur. case ifadelerinin belirli bir sırayı izlemesi gibi bir zorunluluk yoktur. switch parantezi içindeki tamsayı ifadesinin değerine eşit bir case ifadesi bulunamaz ise switch deyiminden bir şey yapılmadan çıkılır.

default case

default bir anahtar sözcüktür. switch deyimi gövdesine yerleştirilen default anahtar sözcüğünü ‘:’ atomu izler. Oluşturulan bu case‘e default case denir.
switch parantezi içindeki ifadenin değerine eşit bir case ifadesi bulunamazsa programın akışı default case içine girer. Daha önceki örnek kodda yer alan switch deyimine default case ekliyoruz:

default case tipik olarak sonuncu case yapılsa da bu bir zorunluluk değildir. default case, switch deyimi gövdesi içinde herhangi bir sıradaki case olabilir. Bir switch deyiminde birden fazla default case bulunması geçerli değildir.

Derleyici farklı bir şekilde eniyileme (optimization) yapmaz ise, switch parantezi içindeki ifadenin sayısal değerine eşit bir case ifadesi bulunana kadar, tüm case ifadeleri yukarıdan aşağıya doğru sırayla sınanır. case ifadelerinin oluşma sıklığı ya da olasılığı hakkında elde bir bilgi varsa, olasılığı ya da sıklığı yüksek olan case ifadelerinin daha önce yazılması gereksiz karşılaştırma sayısını azaltabilir, kodun okunmasını ve anlaşılmasını kolaylaştırabilir.

case ifadelerinin, tamsayı türünden (integer types) sabit ifadesi olması gerekir. Sabit ifadeleri, derleme aşamasında derleyici tarafından net sayısal değerlere dönüştürülebilir:

Yukarıdaki case ifadesi geçerlidir. Çünkü 1 + 3 bir sabit ifadesidir. Ama,

Eğer x bir değişkenin ismi ise yukarıdaki case ifadesi geçersizdir. Derleyici, derleme aşamasında sabit ifadesi olmayan bir ifadenin değerini hesaplayamaz.

Yukarıdaki case ifadesi geçerlidir. ‘a’ bir karakter sabitidir (character literal). case ifadesi tamsayı türünden bir sabit ifadesidir.

Yukarıdaki case ifadesi geçersizdir. “a” bir string sabitidir (string literal). Bir string sabiti tamsayı tamsayı sabiti değildir ve case ifadesi olarak kullanılamaz.

Yukarıdaki case ifadesi geçersizdir. 3.5 bir gerçek sayı sabitidir.

C’de kendisi const nesneler sabit ifadesi gereken yerde kullanılamazlar. C++ dilinde sabit ifadesiyle ilk değerlerini almış const nesneler sabit ifadesi gereken yerlerde kullanılabilirler. Aşağıdaki switch deyimi C’de geçersiz C++ dilinde geçerlidir:

Bir switch deyiminde aynı değerde birden fazla case ifadesinin bulunması geçersizdir. Yani tüm case ifadeleri farklı değerlerde olmalıdır:

switch kontrol deyimi yerine bir else if merdiveni yazılabilir. Yani switch deyimi olmasaydı, yapılmak istenen iş, bir else if merdiveni ile de gerçekleştirilebilirdi. Ancak bazı durumlarda else if merdiveni yerine switch deyimi kullanmak kodun okunmasını ve yazılmasını kolaylaştırır. Ayrıca derleyiciler else if merdiveni yerine switch deyiminin kullanılması durumunda  bir  sıçrama tablosu (jump table) oluşturarak daha etkin bir kod üretebilirler. Örneğin:

Yukarıdaki else if merdiveni ile aşağıdaki switch deyimi işlevsel olarak eşdeğerdir:

else if merdivenindeki son basamakta yer alan else kısmının switch deyimindeki default case karşılığı olduğunu görebiliyor musunuz? Her switch deyiminin yerine aynı işi görecek şekilde bir else if merdiveni yazılabilir. Ama her else if merdiveni karşılığı bir switch deyimi yazılamaz. switch parantezi içindeki ifadenin bir tamsayı türünden olması gerektiğini hatırlayalım. case ifadeleri de tamsayı türlerinden sabit ifadesi olmak zorundadır. switch deyimi, tamsayı türünden bir ifadenin değerinin değişik tamsayı değerlerine eşitliğinin sınanması ve eşitlik durumunda farklı işlerin yapılması için kullanılır. Oysa else if merdiveninde her türlü karşılaştırma söz konusu olabilir. Örnek:

Yukarıdaki else if merdiveninin yerine doğrudan bir switch deyimi yazılamaz.

switch deyimi bazı durumlarda else if merdivenine göre çok daha kolay okunabilir ve anlaşılabilir bir yapı oluşturur. Yani switch deyiminin kullanılması her şeyden önce kodun daha kolay okunabilmesini, anlaşılmasını, değiştirilebilmesini sağlar.  switch deyiminin debug edilmesi else if merdivenine göre daha kolaydır.

Birden fazla case ifadesi için aynı işlemlerin yapılması şöyle sağlanabilir:

Bunu yapmanın daha kısa bir yolu yoktur. Bazı kodlayıcılar kaynak kodun yerleşimini aşağıdaki gibi düzenler:

Aşağıdaki programı önce inceleyin, sonra derleyerek çalıştırın:

print_season işlevi, bir ayın sıra numarasını, yani yılın kaçıncı ayı olduğu bilgisini alıyor. Bu ay yılın hangi mevsimi içinde ise, o mevsimin ismini ekrana yazdırıyor. Aynı iş bir else if merdiveniyle nasıl yapılabilirdi? Her if deyiminin koşul ifadesi içinde “mantıksal veya” işleci kullanılabilirdi:

case ifadeleri olarak sembolik sabitlerin (symbolic constants) kullanılması çok sık karşılaşılan bir durumdur:

case ifadeleri olarak karakter sabitleri de kullanılabilir:

case etiketlerini izleyen tamsayı ifadelerinin numaralandırma sabitleri (enumaration constants) olması çok sık karşılaşılan bir durumdur:

case bir anahtar sözcük olsa da teknik olarak bir etikettir (label). C dilinde etiketlerden sonra bir deyimin (statement) bulunması zorunludur:

Yukarıdaki switch deyiminde case 3 etiketinden sonra bir deyim yer almıyor. Kod geçersizdir.

case ifadelerini izleyen deyimlerin sayısının fazla olması kodun okunmasını zorlaştırır. Bu durumda, yapılacak işlemlerin uygun şekilde isimlendirilerek tanımlanmış işlevlerin çağrılmasına dönüştürülmesi iyi bir tekniktir:

Yukarıdaki örnekte case ifadesi olarak kullanılan ADD_RECORD, DELETE_RECORD, FIND_RECORD daha önce tanımlanmış sembolik sabitlerdir. Her bir case için yaptırılacak işlemler birer işlev içinde sarmalanmış.

switch deyimi, başka bir switch deyiminin ya da bir döngü deyiminin gövdesini oluşturabilir:

Yukarıdaki main işlevinde switch deyimi, dıştaki while döngüsünün gövdesini oluşturuyor. switch deyimi, döngü gövdesindeki tek deyim olduğundan, dıştaki while döngüsünün bloklanmasına gerek yoktur. Tabi while döngüsünün bloklanması bir hataya neden olmaz.
Ancak case ifadeleri içinde yer alan break deyimiyle yalnızca switch deyiminden çıkılır. switch deyimini kapsayan while döngüsünün de dışına çıkmak için case ifadesi içinde goto deyimi kullanılabilir.

Şimdi de aşağıdaki programı inceleyin. Programda display_date isimli bir işlev tanımlanıyor. İşlev gün, ay ve yıl değeri olarak aldığı bir tarih bilgisini İngilizce olarak

yukarıdaki formatta ekrana yazdırıyor:

İşlevin tanımında iki ayrı switch deyimi kullanılıyor. İlk switch deyimiyle, gün değerini izleyen (th, st, nd, rd) sonekleri, ikinci switch deyimiyle, aylara ilişkin kısaltmalar (Jan, Feb, Mar…) yazdırılıyor.
case ifadelerini izleyen deyimlerden biri break deyimi olmak zorunda değildir. Bazı durumlarda break deyimi özellikle kullanılmaz. Uygun bir case ifadesi bulunduğunda daha aşağıdaki tüm deyimlerin de yapılması özellikle istenir. Aşağıdaki programı derleyerek çalıştırın:

dayOfYear işlevi aldığı gün, ay ve yıl değerinin ilgili yılın kaçıncı günü olduğunu hesaplıyor. İşlev içinde kullanılan switch deyimini dikkatli bir şekilde inceleyin. switch deyiminin parantezi içinde, dışarıdan gelen ay değerinin 1 eksiği kullanılmış. Hiçbir case içinde bir break deyimi kullanılmamış. Eşdeğer bir case ifadesi bulunduğunda, daha aşağıda yer alan tüm deyimler de yapılır. Böylece, dışarıdan gelen ay değerinden daha düşük olan her bir ayın kaç çektiği bilgisi, gün toplamını tutan sum değişkenine katılmış.
switch deyiminde eğer bir case etiketini izleyen deyim(ler) var ise ancak bu deyim(ler)den sonra bir break  deyimi bulunmuyor ise bu şüpheli bir durumdur.  break deyiminin yazılması unutulmuş olabilir. Derleyiciler ya da statik kod analizi yapan programlar uygun uyarı ayarlarında (warning switches) uyarı iletisi verebilirler. break deyiminin özellikle yazılmamış olması durumunda yorum “fallthrough” açıklamasının yazılması break deyiminin özellikle yazılmamış olduğunu vurgular.

Share

Necati Ergin

C ve Sistem Programcıları Derneğinde eğitmen olarak çalışıyor.

Bunlar da ilginizi çekebilir

Kod Eklemek İçin Okuyun