280 likes | 537 Views
BPR152 ALGORİTMA VE PROGRAMLAMA - II. Öğr . Gör. Bayram AKGÜL bayramakgul@bartin.edu.tr http ://myo.bartin.edu.tr/akgul. Konular. F onksiyon Paramet releri ve Argum anlar Pass-by-value ref o ut Dizi parametreler Değişken sayıda parametre alan fonksiyonlar
E N D
BPR152 ALGORİTMA VE PROGRAMLAMA - II Öğr. Gör. Bayram AKGÜL bayramakgul@bartin.edu.tr http://myo.bartin.edu.tr/akgul
Konular • FonksiyonParametreleri 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
FonksiyonParametreleri & Argumanlar • Parametrelerfonksiyon tanımlanırken fonksiyona dışarıdan gelen değişkenlerdir. • Parametreler fonksiyon tanımlanırken kullanılacak takma isimlerdir. • Argumanlarfonksiyon çağrılırken kullanılan ifadelerdir. // a, b ve c parametrelerdir staticint Topla(int a, int b, int c) { return a + b + c; } staticvoid Main() { int x =2; inty = Topla(x, 3, x *2); // x, 3 ve x*2 argumanlardır } • Fonksiyon çağrılırken kullanılan argumanlaraşağıdakiler gibi olabilir: • x • 3 • x*2
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.
Değer olarak geçme (Pass-by-Value) staticint Fnk(int a, int b, int c) { a += b + c; // a'nın değeri değişiyor return a; } staticvoid 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 argümanı ‘a’ parametresi olarak fonksiyona geçiyor ve değeri değişmesine rağmen ‘x’ in değeri değişmiyor. x: 2, y: 3, z: 4, t: 9 - Argümanların değerini değiştirmek mümkün mü?
Argümanların değerini fonksiyonda değiştirmek • 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 (?) staticvoid Ayristir(double sayi, int tam, double ksr) { tam = (int)sayi; ksr = sayi - tam; } staticvoid 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); } Tam Kısım: 0, kesir kisim:0,00
Adres geçme (Pass-by-Ref) • refparametre: 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. staticvoid Ayristir(double sayi, refint tam, refdouble ksr) { tam = (int)sayi; ksr = sayi - tam; } staticvoid 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); } 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: staticvoidAyristir(doublesayi, outint tam, outdoubleksr) { tam = (int)sayi; ksr=sayi- tam; } staticvoid 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. staticint Fnk(refint a, refint b, refint c) { a += b += c +=1; return a; } staticvoid 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 • 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? using System; classProgram { staticvoid Yaz(int[] dizi) { foreach (int i in dizi) Console.WriteLine(i); } staticvoid Main() { int[] dizi = { 1, 2, 4, 7, 9 }; Yaz(dizi); } }
Parametre olarak diziler 1 2 4 7 1,2 3,4 5,6 Sarı Kırmızı Mavi Yeşil using System; classProgram { staticvoid Yaz(Array dizi) { foreach (object i in dizi) Console.WriteLine(i); } staticvoid 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.
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.
Parametre olarak diziler using System; classProgram { staticvoid EkranaYazdir(int[] dizi) { for (int i =0; i < dizi.Length; i++) Console.Write(dizi[i] +" "); Console.WriteLine("\n"); } staticvoid ikiyeKatla(int[] dizi) { for (int i =0; i < dizi.Length; i++) dizi[i] *=2; } staticvoid 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 } } 1 2 4 7 9 2 4 8 14 18
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. staticvoidEkranaYaz(stringyazi) { Console.Write(yazi); } staticvoidEkranaYaz(intsayi, 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.
Aynı isimde fonksiyonlar! - 1 usingSystem; classMetotlar { staticvoidMetot (int x, int y) { Console.WriteLine("1. metot çağrıldı."); } staticvoidMetot(floatx, float y) { Console.WriteLine("2. metot çağrıldı."); } staticvoidMetot(stringx, string y) { Console.WriteLine("3. metot çağrıldı."); } staticvoid Main() { Metot("deneme", "deneme"); Metot(5, 6); Metot(10f, 56f); Console.ReadLine(); } } • Bu programda üç metot da aynı sayıda parametre almış. • Bu durumdaparametrelerintürlerinebakılır: • AnaprogramdakiMetot("deneme","deneme");satırıylaüçüncümetotçağrılır. • Metot(5,6);metotçağrımınınparametretürlerinin tam uyumluolduğumetotbirincimetottur, o yüzdenbirincimetotçağrılır. • Eğerbirincimetotoluşturulmamış olsaydıikincimetotçağrılacaktı. • Son olarakMetot(10f,56f);satırıyla da ikincimetotçağrılır. 3. metot çağrıldı. 1. metot çağrıldı. 2. metot çağrıldı.
Aynı isimde fonksiyonlar! - 2 usingSystem; classMetotlar { staticvoidMetot(floatx, float y) { Console.WriteLine("1. metot çağrıldı."); } staticvoidMetot(doublex, double y) { Console.WriteLine("2. metot çağrıldı."); } staticvoid Main() { Metot(5, 6); } } • 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. • metot çağrıldı.
Aynı isimde fonksiyonlar! - 3 usingSystem; classMetotlar { staticvoidMetot(floatx, float y) { Console.WriteLine("1. metot çağrıldı."); } staticvoidMetot(intx, int y) { Console.WriteLine("2. metot çağrıldı."); } staticvoid Main() { Metot(5, 6.4f); } } • 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. • metot çağrıldı.
Aynı isimde fonksiyonlar! - 4 usingSystem; classMetotlar { staticvoidMetot(floatx, float y) { Console.WriteLine("1. metot çağrıldı."); } staticvoidMetot(intx, int y) { Console.WriteLine("2. metot çağrıldı."); } staticvoid Main() { Metot('f', 'g'); } } • 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. • 2. metot çağrıldı.
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);
Değişken sayıda parametre staticintToplam(paramsint[] sayilar) { if (sayilar.Length==0)return0; int toplam =0; foreach (intiinsayilar) toplam += i; return toplam; } staticvoid 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)); } 0 5 15 23 64 172
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: • staticdoubleTutarHesapla(double fiyat, int adet) • staticdoubleTutarHesapla(double fiyat, int adet, boolkdv) • staticdoubleTutarHesapla(double fiyat, int adet, boolkdv, doublekdv_orani) • Bu üç fonksiyonu aşırı yükleyerek gelecek slayttaki gibi yapabiliriz.
Opsiyonel Parametreler staticdoubleTutarHesapla(double fiyat, int adet) { returnfiyat * adet; } staticdoubleTutarHesapla(double fiyat, int adet, boolkdv) { double tutar = fiyat *adet; if (kdv) tutar *= (1.18); returntutar; } staticdoubleTutarHesapla(double fiyat, int adet, boolkdv, doublekdv_orani) { double tutar = fiyat * adet;if (kdv) tutar *= (1+kdv_orani); returntutar; } staticvoid 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 staticdoubleTutarHesapla(double fiyat, int adet){ … } staticdoubleTutarHesapla(double fiyat, int adet, boolkdv) { … } staticdoubleTutarHesapla(double fiyat, int adet, boolkdv, doublekdv_orani){ … } staticvoid 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 • Fonksiyonu üç defa yazmaktansa varsayılan parametreler ile aşağıdaki gibi bir defa yazabiliriz. • Bu fonksiyon önceki üç fonksiyonun da işini görür! publicdoubleTutarHesapla(doublefiyat, int adet, boolkdv=false, doublekdv_orani=0.18 ) { double tutar = fiyat * adet; if (kdv) tutar *= (1+kdv_orani); return tutar; } staticvoid 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); } 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. Tutar-1:200 TL, Tutar-2:236 TL, Tutar-3:216 TL
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!
Opsiyonel Parametre - İşlem staticdouble Hesapla(double x, double y, charislem='+') { switch (islem) { case'+': return x + y; case'-': return x - y; case'*': return x * y; case'/': returnx / y; case'%': return x % y; default: return0; } } staticvoid 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, '^')); } 8 8 2 15 1,66666666666667 2 0
Dinlediğiniz için teşekkürler… Öğr. Gör. Bayram AKGÜL