C# İle biLGİsayar programlama temelleri (C# Programlama Kitabı) Svetlin Nakov & Co



Yüklə 3,36 Mb.
səhifə20/31
tarix03.11.2017
ölçüsü3,36 Mb.
#28822
1   ...   16   17   18   19   20   21   22   23   ...   31

9.10 Bir Metottan Sonuç Döndürme



Şimdiye kadar hep, konsola bir şeyler yazan ve daha fazla bir şey yapmayan örnekler verildi. Metotlar genellikle sadece basit bir kod dizisini yürütmekle kalmaz, ancak ek olarak sık sık sonuç da döndürürler. Bunun aslında nasıl olduğuna bir göz atalım.

9.10.1 Sonuç Döndüren Bir Metotun Bildirilmesi



Bir metotun nasıl bildirildiğini tekrar görelim.

static (
)


Daha önce yerinde sadece void koyacağımızı söylemiştik. Şimdi bu tanımı genişleteceğiz çünkü, göreceğimiz üzere, void tek seçenek değildir. void yerine metotun yürütmesinden sonra döndüreceği sonuç türüne bağlı olarak, temel türlerin her birini (int, float, double, …) veya referans türlerini (string veya array) döndürebilirsiniz.
Örneğin, bir karenin alanını hesaplayan ve bunu konsola yazdırmak yerine sonuç olarak döndüren bir metotu ele alalım. Bildirimi aşağıdaki gibi görünecektir:

static double CalcSquareSurface(double sideLength)


Alanın hesaplanması sonucu, görüldüğü gibi, double türünü taşımaktadır.

9.10.2 Dönen Değer Nasıl Kullanılır?



Metot yürütüldükten ve bir değer döndürdükten sonra bu değerin metotun çağrıldığı yere C# tarafından konulduğunu hayal edebiliriz. Sonra program bu değerle çalışmasına devam etmektedir. Döndürülen bu değer, çağıran metot içinde herhangi bir amaç için kullanılabilir.

9.10.2.1 Değişkene Atama



Metot yürütmesinin sonucunu uygun türde bir değişkene atayabilirsiniz:

// GetCompanyLogo() returns a string

string companyLogo = GetCompanyLogo();





9.10.2.2 İfadelerde Kullanımı



Metot sonuç döndürdükten sonra, bu değer ifadelerde de daha sonra kullanılabilir.
Yani, örneğin, fatura hesaplamak için toplam fiyatı bulmak için birim fiyatı almamız ve miktar ile çarpmamız gerekir.

float totalPrice = GetSinglePrice() * quantity;



9.10.2.3 Metot Parametresi Olarak Döndürülen Değerin Kullanımı



Metot yürütmesinden gelen sonucu başka bir metotun parametre listesinde değer olarak geçirebilirsiniz.

Console.WriteLine(GetCompanyLogo());


Bu örnekte, başlangıçta GetCompanyLogo() metotunu çağırıyoruz ve WriteLine() metotuna bir argüman olarak yazıyoruz. GetCompanyLogo() metotu yürütmesini tamamladıktan hemen sonra bir sonuç döndürür. Sonucun “Microsoft Corporation” olacağını farzedelim. Metotun yürütmesinden dönen sonuç, daha sonra C# tarafından metotun yerine konur. Yani kodu şu şekilde temsil edebiliriz:

Console.WriteLine("Microsoft Corporation");



9.10.3 Dönen Değer Türü



Daha önce yukarıda anlatıldığı gibi, metotun döndürdüğü sonuç herhangi bir türden olabilir – int, string, array vb. Ancak, tür yerine void anahtar sözcüğünü kullandığınızda, bu metot değer döndürmez anlamına gelir.

9.10.4 “return” İşleci



Bir metotun değer döndürmesi için return anahtar sözcüğünün ardından metot tarafından bir sonuç olarak döndürülecek bir ifade ile metot gövdesi içinde yerleştirilmesi gerekir:

static (
)

{

// Some code that is preparing the method's result comes here



return ;

}



Sırasıyla, nun türü dür. Örneğin:


static long Multiply(int number1, int number2)

{

long result = number1 * number2;



return result;

}



Bu metotta çarpma sonrasında return kullanarak, metot yürütmesinin sonucu olarak result tamsayı değişkeni üretilecektir.

9.10.4.1 Sonuç ve Dönen Türün Uyumluluğu



Metot ile döndürülen sonuç döndürülen değerin türü ile uyumlu (veya örtük olarak dönüştürülebilir) bir türden olabilir.
Örneğin şu örneği döndürülen değerin türünü int değil, float yaparak ve kodunu da aşağıda gösterildiği şekilde değiştirebilirsiniz:

static float Multiply(int number1, int number2)

{

int result = number1 * number2;



return result;

}



Bu durumda, çarpmanın yürütülmesinden sonra sonuç int türünden olacaktır. return anahtar sözcüğünden sonraki ifadenin türü float olmasa da değer dolaylı olarak float türüne dönüştürülebildiği için döndürülebilir.

9.10.4.2 Return İşlecinden Sonra Bir İfadenin Kullanılması



Kodu karışık / çirkin görünümlü yapmadığı sürece, return anahtar sözcüğünden sonra doğrudan bazı ifadelerin konulmasına izin verilir:

static int Multiply(int number1, int number2)

{

return number1 * number2;



}


Bu durumda number1 * number2 hesaplanmasından sonra bu ifadenin ürettiği sonuç ifade ile yer değiştirecektir ve dolayısıyla return işleci tarafından döndürülecektir.

9.10.4.3 Return İşlecinin Özellikleri



Return yürütmesi iki şey yapar:


  • Metot yürütmesini hemen durdurur.

  • Çağıran metota metot sonucunu döndürür.

return işlecinin ilk özelliği ile ilgili olarak, dikkat etmeliyiz ki metotun yürütmesini durdurduğu için (ve sonrasından başlayarak metot sonunu belirten kapatma parantezine kadar hiçbir kod çalıştırılmayacaktır) return işlecinden sonraki satırlara herhangi bir kod koymamalıyız.
Buna rağmen kod koyarsanız, derleyici bir uyarı mesajı gösterecektir:

static int Add(int number1, int number2)

{

int result = number1 + number2;



return result;
// Let’s try to "clean" the result variable here:

result = 0;

}



Bu örnekte derleme başarılı olacaktır, ancak return sonrasındaki satırlar için, derleyici çıktısı şöyle bir uyarı mesajı verecektir:

Unreachable code detected


Dönen değer türü için metot void tanımlamışsa, o zaman return sonrasında hiçbir ifade döndürülmeyecektir. Bu durumda return kullanımı sadece metotun yürütülmesini durdurmak için kullanılır:


static void PrintPositiveNumber(int number)

{

if (number <= 0)



{

// If the number is NOT positive, terminate the method

return;

}

Console.WriteLine(number);



}


9.10.4.4 Çoklu Return Deyimleri



return işleci hakkında söylenmesi gereken son şey kodun çeşitli yerlerinde çağrılabilir olmasıdır, ancak kullandığımız return işleçlerinden en az birinin metot yürütülürken ulaşılabilir olması güvence altına alınmalıdır.
İki sayı alan ve daha sonra ilk sayı ikincisinden büyükse 1 döndüren, iki sayı birbirine eşitse 0 döndüren, ve ikinci sayı ilkinden büyükse -1 döndüren bir metot örneğine göz atalım:


static int CompareTo(int number1, int number2)

{

if (number1 > number2)



{

return 1;

}

else if (number1 == number2)



{

return 0;

}

else


{

return -1;

}

}



Çoklu return deyimlerine programlamada sıkça karşılaşılır ve çeşitli durumları kontrol eden yukarıdaki gibi metotlar için kullanımı tipiktir.

9.10.5 Neden Döndürülen Değer Türü Metot İmzasının Bir Parçası Değildir?



Aynı adda ve aynı türden parametreleri alan birden fazla metotun döndürülen değer türleri farklı ise buna C# dilinde izin verilmez. Buna göre, aşağıdaki kodun derlemesi başarısız olacaktır:

static int Add(int number1, int number2)

{

return (number1 + number2);



}
static double Add(int number1, int number2)

{

return (number1 + number2);



}


Bu sınırlamanın nedeni, derleyicinin her iki metottan hangisini çağrması gerektiğini bilmiyor olmasıdır. Her iki metot da aynı imzaya (parametrelerin türleri ile birlikte sırası) sahiptir. Unutmayın ki, dönüş değeri metot imzasının parçası değildir. Bu nedenle, metot bildirimleri için aşağıdaki gibi bir hata mesajı iletilecektir:

Type '' already defines a member called 'Add' with the same parameter types


Burada bu metotları bildirmeye çalıştığımız sınıfın adıdır.

9.10.6 Fahrenheit’tan Santigrat’a Dönüşüm – Örnek



Şimdi (kullanıcı tarafından) Fahrenheit derecesiyle ölçülmüş verilen bir vücut sıcaklığını Santigrat derece sıcaklığına dönüştüren ve aşağıdaki mesajı çıktı olarak yazan bir program kodlamak zorundayız: “Santigrat derecesi cinsinden vücut sıcaklığınız X”; burada X sırasıyla Santigrat derecedir. Buna ek olarak Santigrat olarak ölçülen sıcaklık 37 dereceden daha sıcak olduğunda, program aşağıdaki mesaj ile kullanıcıyı hasta olduğu konusunda uyarmalıdır: “Hastasınız!”.
Yeni başlayanlar için, İnternet’te hızlı bir arama yaparak Fahrenheit’tan Santigrat’a önüşüm formülünü şöylece bulabilirsiniz: °C = (°F - 32) * 5 / 9, burada sırasıyla °C Santigrat ile ölçülen sıcaklığı ve °F Fahrenheit ile ölçülen sıcaklığı belirtir.
Bu işi analiz sonucu aşağıdaki alt görevlere parçalayabiliriz:


  • Konsoldan girdi olarak (kullanıcı girmelidir) Fahrenheit derecesinden ölçülü bir sıcaklık alın.

  • Bu sayıyı dönüştürerek karşılık gelen Santigrat derecesinden ölçülen sıcaklık değerini bulun.

  • Santigrat’a dönüştürülmüş sıcaklık için bir mesaj yazdırın.

  • Sıcaklığın 37 °C’ dan daha yüksek olduğu tespit edilirse, kullanıcının hasta olduğunu belirten bir ileti yazdırın.


Yukarıda anlatılan algoritmanın bir örnek uygulaması TemperatureConverter sınıfı ile aşağıda verilmiştir:
Sıcaklık girdisi ve mesaj çıktısını gerçekleştiren işlemler sıradandır, bu yüzden onların açıklamasını atlayacağız ve sıcaklıkları dönüştürme yaklaşımı üzerinde duracağız. Görüldüğü gibi bu kendi başına ayrı bir metota ayrılabilir mantıksal birimdir. Böylece sadece programın kaynak kodu netlik kazanmayacak, ama dahası her ihtiyaç duyduğumuzda o kod parçasını yeniden kullanma şansına sahip olacağız, bunun için sadece aynı metotu kullanmamız yeterlidir. Ölçülen Fahrenheit sıcaklık değerini temsil eden temperatureF adında tek parametreli ConvertFahrenheitToCelcius(…) metotunu bildiriyoruz. Bu metot double türünden ve Santigrat derecesinden hesaplanan vücut ısısını temsil eden bir değer döndürür. Metot’un gövdesinde İnternet’ten bulduğumuz formülü kullanıyoruz (ve C# sözdizimine göre yazıyoruz).


TemperatureConverter.cs

using System;
class TemperatureConverter

{

static double ConvertFahrenheitToCelsius(double temperatureF)



{

double temperatureC = (temperatureF - 32) * 5 / 9;

return temperatureC;

}
static void Main()

{

Console.Write(



"Fahrenheit derecesi cinsinden vücut sıcaklığınızı giriniz: ");

double temperature = double.Parse(Console.ReadLine());


temperature = ConvertFahrenheitToCelsius(temperature);
Console.WriteLine(

"Santigrat derecesi cinsinden vücut sıcaklığınız {0}.",

temperature);
if (temperature >= 37)

{

Console.WriteLine("Hastasınız!");



}

}

}




Çözüm algoritmamızın bu adımını tamamladıktan sonra, geri kalan adımların farklı metotlarda olmaması gerektiğine karar verdik, bu nedenle onların hepsini sınıfın Main() metotu içinde uyguluyoruz.
double.Parse(…) metotu ile, şu mesajı yazdırarak kullanıcının vücut ısısını alıyoruz: "Fahrenheit derecesi cinsinden vücut sıcaklığınızı giriniz".
Daha sonra ConvertFahrenheitToCelcius(…) metotunu çağırıyoruz ve dönen sonucu temperature değişkeninde saklıyoruz.


Console.WriteLine() metotu ile "Santigrat derecesi cinsinden vücut sıcaklığınız X" mesajını yazdırıyoruz; burada X temperature sıcaklık değeri ile değiştirilir.
Yapmamız gereken son adım, sıcaklığın 37 Santigrat dereceden yüksek olup olmadığını kontrol etmektir. Koşullu deyim if kullanarak bunu yapabiliriz. Yani sıcaklık 37 Santigrat dereceden daha yüksek ise, kullanıcının hasta olduğunu belirten bir mesaj basılmalıdır. Aşağıda programın olası bir çıktısı gösterilmiştir:

Fahrenheit derecesi cinsinden vücut sıcaklığınızı giriniz: 100

Santigrat derecesi cinsinden vücut sıcaklığınız 37,777778.

Hastasınız!



9.10.7 İki Ay Arasındaki Fark – Örnek



Aşağıdaki göreve bir göz atalım: 112 arasında (her biri belirli bir aya karşılık gelen) iki sayı alan ve bu aylar arasında kaç ay olduğunu basan bir program yazınız. Konsolda basılan mesajın içeriği Y’den Z’ye X ay aralığı vardır.” olmalıdır. Burada X hesaplamamız gereken ay sayısıdır ve Y ile Z sırasıyla dönem başlangıcını ve sonunu belirleyen ay adlarıdır.
Görevimizi dikkatle okuyarak, daha kolay çözülebilen alt görevlere bölmeye çalışacağız ve sonra bütün çözümü elde etmek için onları birleştireceğiz. Çözmek zorunda olduğumuz alt görevleri şöylece görebiliriz:



  • Dönem başlangıcını ve sonunu belirleyen ay numaralarını girmek.

  • Girilen aylar arasındaki dönemi hesaplamak.

  • Mesajı yazdırmak.

  • Mesajda dönem başı ve dönem sonu için girilen sayıların yerine, Türkçe’de karşılık gelen ay adlarını yazmanız gerekir.


Verilen görevin muhtemel bir çözümü aşağıda gösterilmiştir:

Months.cs

using System;
class Months

{

static string GetMonthName(int month)



{

string monthName;

switch (month)

{

case 1:



monthName = "Ocak";

break;


case 2:

monthName = "Şubat";

break;

case 3:


monthName = "Mart";

break;


case 4:

monthName = "Nisan";

break;

case 5:


monthName = "Mayıs";

break;


case 6:

monthName = "Haziran";

break;

case 7:


monthName = "Temmuz";

break;


case 8:

monthName = "Ağustos";

break;

case 9:


monthName = "Eylül";

break;


case 10:

monthName = "Ekim";

break;

case 11:


monthName = "Kasım";

break;


case 12:

monthName = "Aralık";

break;

default:


Console.WriteLine("Geçersiz ay!");

return null;

}

return monthName;



}
static void SayPeriod(int startMonth, int endMonth)

{

int period = endMonth - startMonth;



if (period < 0)

{

// Fix negative distance



period = period + 12;

}

Console.WriteLine(



"{1} ile {2} arasında {0} aylık bir dönem vardır.",

period, GetMonthName(startMonth),


GetMonthName(endMonth));

}
static void Main()

{

Console.Write("Birinci ay (1-12): ");



int firstMonth = int.Parse(Console.ReadLine());
Console.Write("İkinci ay (1-12): ");

int secondMonth = int.Parse(Console.ReadLine());


SayPeriod(firstMonth, secondMonth);

}

}




Birinci alt görevin çözümü önemsizdir. Main() metotu içinde int.Parse(…) kullanarak hesaplamayı hedeflediğimiz dönem için ayları alırız.
Sonra dönemin hesaplanması ve mesaj yazdırılmasının mantıksal olarak ayrı bir alt görev olarak ayrılabilir olduğunu görüyoruz, bu yüzden iki parametre alan bir SayPeriod() metotu oluşturuyoruz – dönemin başlangıç ve sonunu belirten ay numaralarını temsil eden sayılar. Bu metot bir değer döndürmez, ancak dönem süresini hesaplar ve standart çıktı olan konsola görevde tanımlanan mesajı yazdırır Console.WriteLine(…).
Görünüşe göre, iki ay arasındaki sürenin uzunluğunu bulmak için ilk ayı temsil eden sayıyı son aydan çıkarmak zorundayız. İkinci ay sayısı birinci aydan küçükse, o zaman kullanıcı muhtemelen ikinci ayın bu yılda değil, ama bir sonraki yılda olduğunu varsaydı. Bu nedenle, iki ay arasındaki fark negatif ise, verilen sürenin uzunluğunu bulmak için ona bir yılın uzunluğu olan 12 eklemeniz gerekir. Sonra ay adları için GetMonthName(…) metotunu kullanarak mesajı yazdırmalıyız.
Ay adını sayıyla alan metot her bir girdi sayısına karşılık gelen ay adını alabileceğimiz

koşullu switch-case deyimi ile kolayca oluşturulabilir. Değer [1..12] aralığında değilse, program bir hata bildirir. Daha sonraki "İstisnai Durum İşleme" Bölümü’nde bir hatanın meydana geldikten sonra nasıl bildirileceğini ayrıntılı olarak tartışacağız. İstisnaların (hata bildirimleri) nasıl yakalanacağı ve onlarla nasıl başa çıkılacağı size gösterilecektir. Ancak, şu an için sadece konsola bir hata mesajı yazdıracağız. Bu genellikle yanlış bir davranıştır ve "Yüksek Kalite Programlama Kodu" Bölümü’nün "Bir Metot Ne Yapmalıdır" alt başlığında bunu nasıl önleyeceğinizi öğreneceksiniz.
Sonunda, Main() metotunda SayPeriod() metotunu dönem başı ve dönem sonu için girilen numaralar ile çağırıyoruz. Bunu da gerçekleştirerek, görevi tamamen çözdük.
2 ve 6 girdileri için olası bir çıktı aşağıda gösterilmiştir:

Birinci ay (1-12): 2

İkinci ay (1-12): 6

Şubat ile Haziran arasında 4 aylık bir dönem vardır.




9.10.8 Girdi Verisinin Doğrulanması – Örnek



Şimdiki görevimizde konsolda “Şimdi zaman kaçtır?” sorusunu kullanıcıya soran bir program yazmalıyız. Daha sonra kullanıcı iki sayı girmelidir – biri saat, biri dakika için. Girilen veri geçerli bir zamanı temsil ediyorsa, program “Zaman şimdi ss:dd gösteriyor.” mesajını çıktı olarak yazdırmalıdır. Burada ss sırasıyla saat ve dd dakika anlamına gelir. Girilen saat veya dakika geçerli değilse, programın “Geçersiz zaman!” mesajını yazdırması gerekiyor.
Dikkatle görevi okuduktan sonra, şu alt görevlere ayrılabilir olduğunu görüyoruz:


  • Saat ve dakika için girdi verilerini alın.

  • Veri girişinin geçerli olup olmadığını kontrol edin (girdi doğrulama).

  • Bir hata iletisi veya geçerli zaman mesajı – ile ilgili mesajı yazdırın.


Girdi verilerinin alınmasının ve çıktı mesajlarının yazılmasının artık bir sorun olmayacağını düşünüyoruz, bu yüzden girdi veri doğrulaması üzerinde duracağız, yani saatler ve dakikalar için sayıların doğrulaması. Saatlerin 0 ile 23 (dahil) aralığında olduğunu, ve sırasıyla dakikaların 0 ile 59 (dahil) aralığında bulunduğunu biliyoruz. Veriler (saat ve dakika için) aynı karaktere sahip olmadıkları için, iki ayrı metot oluşturmaya karar verdik. Bunlardan biri saat geçerliliğini kontrol ederken, diğeri dakika geçerliliğini kontrol edecektir.
Bir çözüm aşağıda gösterilmiştir:


DataValidation.cs

using System;
class DataValidation

{

static void Main()



{

Console.WriteLine("Şimdi zaman kaçtır?");


Console.Write("Saat: ");

int hours = int.Parse(Console.ReadLine());


Console.Write("Dakika: ");

int minutes = int.Parse(Console.ReadLine());


bool isValidTime =

ValidateHours(hours) && ValidateMinutes(minutes);


if (isValidTime)

{

Console.WriteLine("Zaman şimdi {0}:{1} gösteriyor.",



hours, minutes);

}

else



{

Console.WriteLine("Geçersiz zaman!");

}

}

static bool ValidateHours(int hours)



{

bool result = (hours >= 0) && (hours < 24);

return result;

}
static bool ValidateMinutes(int minutes)

{

bool result = (minutes >= 0) && (minutes <= 59);



return result;

}

}




Saat kısmını kontrol eden metotun ismi ValidateHours() olarak adlandırılmıştır ve int türünde bir sayı alarak girilen sayı geçerli bir saat ise değeri true, değilse – değeri false olan bool türünde bir sonuç döndürür:


static bool ValidateHours(int hours)

{

bool result = (hours >= 0) && (hours < 24);



return result;

}



Dakika geçerliliğini kontrol eden metotu bildirmek için basit bir mantık kullandık. Bir tamsayı değeri olan ve dakikayı temsil eden bir parametre aldığı ve bool türünde bir değer döndürdüğü için bu metotu ValidateMinutes() olarak adlandırdık. Girdi numarası geçerli bir dakika değeri ise, metot sonuç olarak true, değilse – false döndürecektir:

static bool ValidateMinutes(int minutes)

{

bool result = (minutes >= 0) && (minutes <= 59);



return result;

}



Görevin en karmaşık kısmını tamamladığımız için, Main() metotunu bildiriyoruz. Gövdesinde, görevimizde tanımlanan soruyu soruyoruz – “Şimdi zaman kaçtır?”. Ardından int.Parse(…) metotu ile saat ve dakika için konsoldan sayıları okuyoruz, bu sayılar sonra hours ve minutes değişklenlerinde tutuluyor:

Console.WriteLine("Şimdi zaman kaçtır");
Console.Write("Saat: ");

int hours = int.Parse(Console.ReadLine());


Console.Write("Saat: ");

int minutes = int.Parse(Console.ReadLine());




Sırayla bildirdiğimiz ValidateHours() ve ValidateMinutes() metotlarını çağırarak ve tabii ki her birine saat ve dakika için uygun değişkenleri geçirdikten sonra, doğrulamanın sonucu bool türünde bir değişkende tutulur – isValidTime. Bir bütün olarak, girdi verilerini doğrulamak için metot çağırma sonuçlarını mantıksal “ve” işleci && ile birleştiriyoruz:

bool isValidTime =

ValidateHours(hours) && ValidateMinutes(minutes);




Veri girişinin geçerli olup olmadığı sonucunu isValidTime değişkeninde sakladıktan sonra, verilen görevin son sorunuyla başa çıkmak – girişin geçerli olup olmadığı bilgisini kullanıcıya yazdırmak için if koşullu deyimini kullanıyoruz. isValidTime doğruysa, Console.WriteLine(…) metotu ile konsola “Zaman şimdi ss:dd gösteriyor.” mesajını yazdırıyoruz. Burada sırasıyla sshours değişkeninin değerini ve ddminutes değişkeninin değerini göstermektedir. Koşullu deyimin else bölümünde, girilen zamanın geçersiz olduğunu yazdırıyoruz – “Geçersiz zaman!”.
Programın olası çıktısı, doğru veri aldığı takdirde, aşağıda gösterilmiştir:

Şimdi zaman kaçtır?

Saat: 17

Dakika: 33

Zaman şimdi 17:33 gösteriyor.




Ve yanlış veri aldığında, programın nasıl davranacağı aşağıda gösterilmiştir:

Şimdi zaman kaçtır?

Saat: 33

Dakika: -2

Geçersiz zaman!


9.10.9 Sıralama – Örnek



Bir değer kümesini artan sırada sıralayan (sıraya koyan) bir metot oluşturmayı deneyelim. Sonuç, sıralanmış sayıları içeren bir dize olacaktır.
Bu düşünceyle, başa çıkmamız gereken alt görevlerin iki tane olduğunu varsayabiliriz:


  • Onları sıraya koyması için, metotumuza sayıları nasıl vereceğimiz

  • Bu sayıları nasıl sıralayacağımız


Metotumuz parametre olarak sayı dizisini almak zorundadır, bu diziyi sıraladıktan sonra geri döndürmesi gerekir:

static int[] Sort(int[] numbers)

{

// The sorting logic comes here …


return numbers;

}



Bu çözüm, görev gereksinimlerini karşılıyor gibi görünmektedir. Ancak bu çözümü daha çok optimize edebiliriz. Argümanın bir tamsayı dizisi olması yerine, değişken sayıda tamsayı parametreleri alan bir dizi şeklinde bildirebiliriz.
Böylece küçük bir sayı kümesi için metotu çağırdığımızda önceden diziyi başlatmak zorunda kalmayacağız. Daha büyük sayı kümeleri için, “9.9.3.1 Değişen Sayıda Argüman Alan Bir Metot Nasıl Bildirilir?” altbölümünde gördüğümüz gibi, tamsayıları metot parametresi olarak geçmek yerine, tamsayılarla başlatılmış bir diziyi doğrudan metota geçebiliriz. Bu nedenle, birinci bildirimimiz şu şekle dönüşür:

static int[] Sort(params int[] numbers)

{

// The sorting logic comes here …


return numbers;

}



Şimdi diziyi nasıl sıralayacağımıza karar vermemiz gerekiyor. Bunun yapılması için en kolay yollardan biri “seçim sıralaması” algoritmasını kullanmaktır. Bu yöntem, diziyi iki bölümden oluşuyor olarak görmektedir – sıralanmış ve sıralanmamış. Sıralanan kısmı dizinin sol tarafında, sıralanmamış kısmı ise sağ tarafındadır. Algoritmanın her adımı için, sıralanan bölüm sağ tarafa doğru tek eleman ile genişletilir ve sıralanmamış bölüm sol kısmından bir eleman ile küçülür.
Bir örnek ile göz atalım. Şu sıralanmamış diziyi ve seçim sıralaması ile elemanlarını sıralamak istediğimizi varsayalım:


Algoritmamızın her adımında, dizinin sıralanmamış bölümündeki en küçük elemanı bulmamız gerekiyor.


Sonra en küçük eleman dizinin sıralanmamış bölümündeki ilk eleman ile takas edilmelidir:


Sonra dizinin sıralanmamış kısmının geri kalanında yine en küçük elemanı arıyoruz, (ilki hariç tüm elemanlar arasından):


Bu en küçük eleman şimdiki sıralanmamış kısmın ilk elemanı ile takas edilir.





Dizinin sıralanmamış kısmı 0 uzunluğuna ulaşıncaya kadar, yani boş olana kadar, bu adım tekrar edilir:



Sonuç olarak dizi sıralanmış olur:


Yukarıda açıklanan (seçim sıralaması) algoritmayı uygulayan kodun bir varyasyonu aşağıda gösterilmiştir:


static int[] Sort(params int[] numbers)

{

// The sorting logic:



for (int i = 0; i < numbers.Length - 1; i++)

{

// Loop operating over the unsorted part of the array



for (int j = i + 1; j < numbers.Length; j++)

{

// Swapping the values



if (numbers[i] > numbers[j])

{

int temp = numbers[i];



numbers[i] = numbers[j];

numbers[j] = temp;

}

}

} // End of the sorting logic



return numbers;

}




Sayı listesini konsola çıktı olarak yazdıran bir PrintNumbers(params int[]) metotu bildirelim ve daha sonra bu örneği test etmek için doğrudan Main(…) metotu içine birkaç satır kod ilave edelim:


SortingEngine.cs

using System;
class SortingEngine

{

static int[] Sort(params int[] numbers)



{

// The sorting logic:

for (int i = 0; i < numbers.Length - 1; i++)

{

// Loop that is operating over the un-sorted part of



// the array

for (int j = i + 1; j < numbers.Length; j++)

{

// Swapping the values



if (numbers[i] > numbers[j])

{

int oldNum = numbers[i];



numbers[i] = numbers[j];

numbers[j] = oldNum;

}

}

} // End of the sorting logic



return numbers;

}
static void PrintNumbers(params int[] numbers)

{

for (int i = 0; i < numbers.Length; i++)



{

Console.Write("{0}", numbers[i]);

if (i < (numbers.Length - 1))

{

Console.Write(", ");



}

}

}


static void Main()

{

int[] numbers = Sort(10, 3, 5, -1, 0, 12, 8);



PrintNumbers(numbers);

}

}




Bu kod derlendikten ve yürütüldükten sonra sonuç tam olarak beklendiği gibi olur – dizi artan sırada sıralanmıştır:


-1, 0, 3, 5, 8, 10, 12




Yüklə 3,36 Mb.

Dostları ilə paylaş:
1   ...   16   17   18   19   20   21   22   23   ...   31




Verilənlər bazası müəlliflik hüququ ilə müdafiə olunur ©muhaz.org 2024
rəhbərliyinə müraciət

gir | qeydiyyatdan keç
    Ana səhifə


yükləyin