BPR152 ALGORİTMA VE PROGRAMLAMA - II Öğr. Gör. Bayram AKGÜL
2 Fonksiyon Parametreleri ve Argumanlar –Pass-by-value –ref –out –Dizi parametreler –Değişken sayıda parametre alan fonksiyonlar Fonksiyonların aşırı yüklenmesi Opsiyonel parametreler Konular
3 Fonksiyon Parametreleri & Argumanlar Parametreler fonksiyon tanımlanırken fonksiyona dışarıdan gelen değişkenlerdir. –Parametreler fonksiyon tanımlanırken kullanılacak takma isimlerdir. Argumanlar fonksiyon çağrılırken kullanılan ifadelerdir. // a, b ve c parametrelerdir static int Topla(int a, int b, int c) { return a + b + c; } static void Main() { int x = 2; int y = Topla(x, 3, x * 2); // x, 3 ve x*2 argumanlardır } Fonksiyon çağrılırken kullanılan argumanlar aşağıdakiler gibi olabilir: ―x ―3 ―x*2
4 Parametre & Argüman Türleri C# ta, normal olarak kullanılan argümanlar değerleri ile kullanılır (passed-by-value) –Fonksiyon çağrılırken tüm argümanlar hesaplanıyor ve değerleri karşılık gelen parametreye aktarılıyor. –Bu durumda Fonksiyon çalışması sırasında parametrenin değerinin değişmesi argümanın değerini etkilemez.
5 Değer olarak geçme (Pass-by-Value) static int Fnk(int a, int b, int c) { a += b + c; // a'nın değeri değişiyor return a; } static void Main() { int x = 2; int y = 3; int z = 4; int t = Fnk(x, y, z); Console.Write("x: {0}, y: {1}, z: {2}, t: {3}", x, y, z, t); } x: 2, y: 3, z: 4, t: 9 x argümanı ‘a’ parametresi olarak fonksiyona geçiyor ve değeri değişmesine rağmen ‘x’ in değeri değişmiyor. - Argümanların değerini değiştirmek mümkün mü?
6 Argümanların değerini fonksiyonda değiştirmek static void Ayristir(double sayi, int tam, double ksr) { tam = (int)sayi; ksr = sayi - tam; } static void Main() { int i = 0; double f = 0.0; Ayristir(2.35, i, f); Console.Write("Tam Kısım: {0}, kesir kisim:{1:F2}", i, f); } Ondalıklı bir sayının tam ve virgülden sonraki kısmını ayırıp ekrana yazdıran bir fonksiyon yazmak istiyoruz. –sayi = 2.35 tam kisim: 2, kesir kisim: 0.35 –Muhtemelen bu işi yapacak fonksiyon (?) Tam Kısım: 0, kesir kisim:0,00
7 Adres geçme (Pass-by-Ref) static void Ayristir(double sayi, ref int tam, ref double ksr) { tam = (int)sayi; ksr = sayi - tam; } static void Main() { int i = 0; double f = 0.0; Ayristir(2.35, ref i, ref f); Console.Write("Tam Kısım: {0}, kesir kisim:{1:F2}", i, f); } ref parametre: değişkenlerin metotlara adres gösterme yoluyla aktarılmasını sağlar. –ref sözcüğüyle bir değişkenin metoda adres gösterme yoluyla aktarılabilmesi için ana programda değişkene bir ilk değer verilmelidir. Yoksa hata verir. Tam Kısım: 2, kesir kisim:0,35
out parametre Kullanımı ref anahtar sözcüğüyle tamamen aynıdır. –Tek farkı out ile belirtilen değişkenlere esas programda bir ilk değer verilmesinin zorunlu olmamasıdır. –Örneğin aşağıdaki kullanım tamamen doğrudur: 8 static void Ayristir(double sayi, out int tam, out double ksr) { tam = (int)sayi; ksr = sayi - tam; } static void Main() { int i; double f; Ayristir(2.35, out i, out f); Console.Write("Tam Kısım: {0}, kesir kisim:{1:F2}", i, f); }
ref & out ref veya out anahtar sözcükleri ile geçilen parametreler fonksiyonda değişirse değişim ana programa da yansır. –Çünkü değişkenlerin aslında adresleri gönderilmiştir. 9 static int Fnk(ref int a, ref int b, ref int c) { a += b += c += 1; return a; } static void Main() { int x = 2, y = 3, z = 4; int t = Fnk(ref x, ref y, ref z); Console.Write("x: {0}, y: {1}, z: {2}, t: {3}", x, y, z, t); } x: 10, y: 8, z: 5, t: 10
Parametre olarak diziler 10 using System; class Program { static void Yaz(int[] dizi) { foreach (int i in dizi) Console.WriteLine(i); } static void Main() { int[] dizi = { 1, 2, 4, 7, 9 }; Yaz(dizi); } Buradaki Yaz metodu kendisine parametre olarak verilen dizinin elemanlarını alt alta yazar. Bu fonksiyona gönderilen parametrenin int türünden dizi olması gerekir. Her hangi türden bir dizi göndermek istersek ne yapmalıyız?
Parametre olarak diziler 11 using System; class Program { static void Yaz(Array dizi) { foreach (object i in dizi) Console.WriteLine(i); } static void Main() { int[] dizi1 = { 1, 2, 4, 7}; double[] dizi2 = { 1.2, 3.4, 5.6}; string[] dizi3 = { "Sarı", "Kırmızı", "Mavi", "Yeşil" }; Yaz(dizi1); Yaz(dizi2); Yaz(dizi3); } Buradaki Yaz metodu kendisine parametre olarak gönderilen herhangi bir dizinin elemanlarını alt alta yazar. Bu fonksiyona gönderilen parametrenin sadece dizi olması yeterlidir ,2 3,4 5,6 Sarı Kırmızı Mavi Yeşil ,2 3,4 5,6 Sarı Kırmızı Mavi Yeşil
Dizi parametreleri Dizi parametrelerinde yapılan bir değişiklik gerçek diziyi etkiler. Çünkü diziler parametre olarak kullanıldığında dizinin kendisi yerine adresi gönderilir. Dolayısıyla aynı bellek bölgesi üzerinde işlem yapılır. 12
Parametre olarak diziler 13 using System; class Program { static void EkranaYazdir(int[] dizi) { for (int i = 0; i < dizi.Length; i++) Console.Write(dizi[i] + " "); Console.WriteLine("\n"); } static void ikiyeKatla(int[] dizi) { for (int i = 0; i < dizi.Length; i++) dizi[i] *= 2; } static void Main() { int[] dizi = { 1, 2, 4, 7, 9 }; EkranaYazdir(dizi); // ilk halini yazdır ikiyeKatla(dizi); // dizi değişecek EkranaYazdir(dizi); // son halini yazdır }
Fonksiyonların aşırı yüklenmesi C#'ta parametre sayısı ve/veya parametrelerin türleri farklı olmak şartıyla aynı isimli birden fazla fonksiyon oluşturulabilir. Buna fonksiyonların aşırı yüklenmesi denir. 14 static void EkranaYaz(string yazi) { Console.Write(yazi); } static void EkranaYaz(int sayi, int sefer) { for (int i = 0; i < sefer; i++) Console.Write(sayi); } Farklı sayılarda ve türlerde parametrelerle aynı isimli fonksiyon!
Aşırı yüklenmiş Fonksiyonların Çağrılışı: C#, bir fonksiyon çağrıldığında ve çağrılanla aynı isimli birden fazla fonksiyon bulunduğunda fonksiyonun çağrılış biçimine bakar. Yani ana programdaki fonksiyonda girilen parametrelerle oluşturulmuş olan fonksiyonların parametrelerini kıyaslar. –Önce parametre sayısına bakar. –Eğer aynı isimli ve aynı sayıda parametreli birden fazla metot varsa; –Bu sefer parametre türlerinde tam uyumluluk arar, –Parametre türlerinin tam uyumlu olduğu bir metot bulamazsa; –Bilinçsiz tür dönüşümünün mümkün olduğu bir metot arar, –Onu da bulamazsa programımız hata verir. 15
Aynı isimde fonksiyonlar! using System; class Metotlar { static void Metot (int x, int y) { Console.WriteLine("1. metot çağrıldı."); } static void Metot(float x, float y) { Console.WriteLine("2. metot çağrıldı."); } static void Metot(string x, string y) { Console.WriteLine("3. metot çağrıldı."); } static void Main() { Metot("deneme", "deneme"); Metot(5, 6); Metot(10f, 56f); Console.ReadLine(); } 3. metot çağrıldı. 1. metot çağrıldı. 2. metot çağrıldı. 3. metot çağrıldı. 1. metot çağrıldı. 2. metot çağrıldı. Bu programda üç metot da aynı sayıda parametre almış. Bu durumda parametrelerin türlerine bakılır: Ana programdaki Metot("deneme","deneme"); satırıyla üçüncü metot çağrılır. Metot(5,6); metot çağrımının parametre türlerinin tam uyumlu olduğu metot birinci metottur, o yüzden birinci metot çağrılır. Eğer birinci metot oluşturulmamış olsaydı ikinci metot çağrılacaktı. Son olarak Metot(10f,56f); satırıyla da ikinci metot çağrılır.
Aynı isimde fonksiyonlar! using System; class Metotlar { static void Metot(float x, float y) { Console.WriteLine("1. metot çağrıldı."); } static void Metot(double x, double y) { Console.WriteLine("2. metot çağrıldı."); } static void Main() { Metot(5, 6); } 1.metot çağrıldı. Bu programda iki metodun da parametre sayısı eşit, iki metotta da tam tür uyumu yok ve iki metotta da bilinçsiz tür dönüşümü mümkün. Bu durumda en az kapasiteli türlü metot çağrılır. Yani bu programda birinci metot çağrılır.
Aynı isimde fonksiyonlar! using System; class Metotlar { static void Metot(float x, float y) { Console.WriteLine("1. metot çağrıldı."); } static void Metot(int x, int y) { Console.WriteLine("2. metot çağrıldı."); } static void Main() { Metot(5, 6.4f); } 1.metot çağrıldı. Bu programda iki metodun da parametre sayısı eşit, iki metotta da tam tür uyumu yok! Parametrelerden bilinçsiz dönüşüm yapılabilecek fonksiyon çağırılır. Yani bu programda birinci metot çağrılır.
Aynı isimde fonksiyonlar! using System; class Metotlar { static void Metot(float x, float y) { Console.WriteLine("1. metot çağrıldı."); } static void Metot(int x, int y) { Console.WriteLine("2. metot çağrıldı."); } static void Main() { Metot('f', 'g'); } 2. metot çağrıldı. Bu programda iki metodun da parametre sayısı eşit, iki metotta da tam tür uyumu yok! Parametrelerden bilinçsiz dönüşüm yapılabilecek fonksiyon çağırılır. char hem inte hem de floata bilinçsiz olarak dönüşebilir. Ancak int daha az kapasiteli olduğu için birinci metod çağırılır.
Değişken sayıda parametre alan Fonksiyonlar Şimdiye kadar fonksiyonlarımıza gönderdiğimiz parametre sayısı belliydi ve bu parametre sayısından farklı miktarda parametre girersek programımız hata veriyordu. İstediğimiz sayıda parametre girebileceğimiz fonksiyonlar yazabilir miyiz? int t1 = Toplam(5,10); int t2 = Toplam(7,12,45); int t3 = Toplam(123, 12, 5, 7, 9, 4, 12); 20
Değişken sayıda parametre 21 static int Toplam(params int[] sayilar) { if (sayilar.Length == 0) return 0; int toplam = 0; foreach (int i in sayilar) toplam += i; return toplam; } static void Main() { Console.WriteLine(Toplam()); Console.WriteLine(Toplam(5)); Console.WriteLine(Toplam(5, 10)); Console.WriteLine(Toplam(2, 9, 12)); Console.WriteLine(Toplam(7, 12, 45)); Console.WriteLine(Toplam(123, 12, 5, 7, 9, 4, 12)); }
Opsiyonel parametreler Bir fonksiyonun birden fazla amaç için kullanılmasını sağlayabiliriz. İsteğe bağlı parametreler kullanarak bu durumu sağlayabiliriz. Örnek: Aşağıdaki üç fonksiyonu düşünelim: static double TutarHesapla(double fiyat, int adet) static double TutarHesapla(double fiyat, int adet, bool kdv) static double TutarHesapla(double fiyat, int adet, bool kdv, double kdv_orani) –Bu üç fonksiyonu aşırı yükleyerek gelecek slayttaki gibi yapabiliriz. 22
Opsiyonel Parametreler 23 static double TutarHesapla(double fiyat, int adet) { return fiyat * adet; } static double TutarHesapla(double fiyat, int adet, bool kdv) { double tutar = fiyat * adet; if (kdv) tutar *= (1.18); return tutar; } static double TutarHesapla(double fiyat, int adet, bool kdv, double kdv_orani) { double tutar = fiyat * adet; if (kdv) tutar *= (1 + kdv_orani); return tutar; } static void Main() { double t1 = TutarHesapla(100, 2); double t2 = TutarHesapla(100, 2, true); double t3 = TutarHesapla(100, 2, true, 0.08); Console.WriteLine("Tutar-1:{0} TL, Tutar-2:{1} TL, Tutar-3:{2} TL", t1, t2, t3); } Tutar-1:200 TL, Tutar-2:236 TL, Tutar-3:216 TL
Opsiyonel Parametreler 24 static double TutarHesapla(double fiyat, int adet){ … } static double TutarHesapla(double fiyat, int adet, bool kdv) { … } static double TutarHesapla(double fiyat, int adet, bool kdv, double kdv_orani){ … } static void Main() { double t1 = TutarHesapla(100, 2); double t2 = TutarHesapla(100, 2, true); double t3 = TutarHesapla(100, 2, true, 0.08); Console.WriteLine("Tutar-1:{0} TL, Tutar-2:{1} TL, Tutar-3:{2} TL", t1, t2, t3); } Fonksiyon ilk çağırılışta iki parametreli fonksiyon çalışacaktır. İkinci çağırılışta üç parametreli fonksiyon çalışacaktır. Üçüncü çağırılışta ise dört parametreli fonksiyon çalışacaktır.
Opsiyonel Parametreler 25 public double TutarHesapla(double fiyat, int adet, bool kdv=false, double kdv_orani=0.18 ) { double tutar = fiyat * adet; if (kdv) tutar *= (1 + kdv_orani); return tutar; } static void Main() { double t1 = TutarHesapla(100, 2); double t2 = TutarHesapla(100, 2, true); double t3 = TutarHesapla(100, 2, true, 0.08); Console.WriteLine("Tutar-1:{0} TL, Tutar-2:{1} TL, Tutar-3:{2} TL", t1, t2, t3); } Tutar-1:200 TL, Tutar-2:236 TL, Tutar-3:216 TL Opsiyonel Parametreler: Eğer fonksiyon iki parametre ile çağırılırsa kdv’nin değeri false ve kdv_oranı 0.18 olacaktır. Eğer fonksiyon üç parametre ile çağırılırsa yine kdv_oranı 0.18 olacaktır. Fonksiyonu üç defa yazmaktansa varsayılan parametreler ile aşağıdaki gibi bir defa yazabiliriz. Bu fonksiyon önceki üç fonksiyonun da işini görür!
Opsiyonel Parametreler Üzerine Notlar ref veya out parametreler opsiyonel olarak tanımlanamaz! Opsiyonel parametreler tüm parametrelerin en sağında olmak zorundadır, normal parametreler arasında opsiyonel parametreler tanımlanamaz! Bir fonksiyonda hepsi en sağda tanımlanmak şartı ile birden fazla opsiyonel parametre olabilir. Opsiyonel parametrelerden bazılarına değer geçerek bazılarına ise değer geçmeden kullanmak istiyorsanız değer geçeceğiniz parametreler solda olmak zorundadır! –Örneğin önceki sılaytta hazırladığımız TutarHesapla fonksiyonunu aşağıdaki gibi kullanamazsınız! double t = TutarHesapla(100, 2, 0.08); // ERROR! 26
Opsiyonel Parametre - İşlem 27 static double Hesapla(double x, double y, char islem = '+') { switch (islem) { case '+': return x + y; case '-': return x - y; case '*': return x * y; case '/': return x / y; case '%': return x % y; default: return 0; } static void Main() { Console.WriteLine(Hesapla(5, 3)); Console.WriteLine(Hesapla(5, 3, '+')); Console.WriteLine(Hesapla(5, 3, '-')); Console.WriteLine(Hesapla(5, 3, '*')); Console.WriteLine(Hesapla(5, 3, '/')); Console.WriteLine(Hesapla(5, 3, '%')); Console.WriteLine(Hesapla(5, 3, '^')); } , ,
DINLEDIĞINIZ IÇIN TEŞEKKÜRLER… Öğr. Gör. Bayram AKGÜL28