|
C++ Exception Handling(Hata Yakalama) |
|
Gönderiliyor lütfen bekleyin... |
|
|
Hata yakalama (Exception
Handling) başlıbaşına büyük bir konu olmasına rağmen Hata Yakalama ile ilgili
temel bilgileri basit örneklerlerle anlatmaya çalışacağım. C dili bize çok az hata
yakalama mekanizması sunar. Aşağıdaki kodu inceleyerek hata oluşma durumlarından
neyi kastettiğimizi anlayabilirsiniz.
int BirseylerYap()
{
int *a, c;
FILE *dosya;
a = malloc(sizeof(int) * 10);
if (a == NULL)
return 1;
dosya = fopen("cpp.txt", "rb");
if (dosya == NULL) {
free(a);
return 2;
}
fread(a, sizeof(long), 10, b);
if (a[0] != 0x10) {
free(a);
fclose(dosya);
return 3;
}
fclose(b);
c = a[1];
free(a);
return c;
}
Bu fonksyionla yapmak istediğimiz, birtakım geri dönüş değerlerine göre hatanın
ne olduğunu anlamaktır. Eğer geri dönüş değeri 1 ise alan tahsisatı yapılamadığını,
2 ise cpp.txt dosyasının açılamadığını anlıyoruz. Aslında burada hata ayıklaması
gibi özel bir kavram yoktur.Kendimiz if-else bloklarıyla hatayı bulmaya çalışıyoruz.
Ama c++ 'ın bunların ötesinde yapabildiği şeyler vardır. C++ dili hata yakalama
için özel anahtar sözcükler içerir. Şimdi sırayla bu anahtar sözcükleri anlayabilmek
için basit bir c++ programı yazalım. Hata denetlemesi yapabileceğimiz programımız
şöyle olsun. Kullanıcıdan iki değer alacağız.Ve ilk alınan değeri
ikinci alınan değere böleceğiz.
Eğer
biraz matematik bilgisine sahipsek kullanıcı ikinci değer olarak sıfır girdiğinde
hata olacaktır. Çünkü bir sayının sıfıra bölünmesi matematiksel olarak sonsuzu
ifade eder.Bilgisayar programcılığında ise sonsuz diye bir şey yoktur,
herşey sonludur.(siz sonsuz döngüler yaptığımıza bakmayın)
Şimdi C++ 'da exception handling nasıl yapılır ona bakalım. C++ 'da hata yakalama
mekanizması try,catch ve throw anahtar
sözcükleriyle yapılır. try ve catch birer komut bloklarıdır. Hatanın ayıklanmasını
istediğimiz bölgeyi try blokları içine almamız gerekir. Hata yakalandığında
işletilecek kodlar ise catch blokları içinde olmalıdır. Peki try bloku ile catch bloku
arasındaki iletişim nasıl sağlanacak, bunun cevabı ise throw anahtar sözcüğüdür.
Hatanın oluşmasına sebeb olacak ifadeden sonra catch bloğuna hatanın türü ile
ilgili bilgi göndeririz. Aşağıdaki programda throw ile atılan bir int bilgidir.
catch bloğu ise bu bilgiyi alarak bir hata mesajı verir. Unutmayın throw ile
atılan mesajdan sonra programımızı eğer exit() gibi bir fonksiyonla bitirmezsek
catch bloğundan sonra programın akışı devam edecektir. Bu yüzden eğer programımızla
ilgili hayati bir hata yakalarsak catch bloğu içinde exit() ile programı tamamen
sonlandırmamız gerekir.
int main(void){
float a,b,c;
try{
cin >> b >> c ;
if (c==0) throw 1
a=b/c;
}
catch(int i)
{
cout << i<< " Hata oluştu"
}
return 0;
}
Gördüğünüz gibi yukarıdaki
programda
eğer kullanıcı ikinci değer olarak sıfır girerse programımız catch bloğuna
gelir ve ekrana "1 Hata oluştu" mesajı yazılır. Elbette exception
handling mekanizması bu kadar basit işler için değildir. Asıl amacımız
sınıflar ile ilişki kurarak hata ayıklamak.Hatta throw ile kullanmak için
her sınıf için ayrı birer hata sınıfları bile oluşturabiliriz. Hata diye bir sınıfımızın
olduğunu düşünelim. Şu ifade son derece legal bir durumdur. " throw(Hata err);
". Hatta, Hata sınıfına ait bir varsayılan kurucu(constructor) işlevinin de
olduğunu düşünürseniz şöyle bir kod da yazabiliriz. "
throw Hata(); ". Catch bloğuna gönderdiğimiz Hata adlı sınıf nesnesini
Catch bloğunda ise şöyle yakalarız. "catch(Hata err);" Şimdi bu söylediklerimizi
bir örnekle gösterelim. Örneğimizde MetreSantim diye
bir sınıfımız
olacak. Amacımız bir uzunluk ölçüsünü iki değer olarak tutmak(Metre ve santim). Sınıfımızın
iki tane m(metre) ve cm(santim) olacak şekilde iki tane üye değişkeni olacak.
Sınıfımızın biri kurucu olmak üzere put ve show gibi 3 tane de üye
işlevi olacaktır. Amacımız put() ya da kurucu işlevi ile oluşturulacak nesnelerin
santimetre değerini 100 'den küçük olacak şekilde tutmak.(Not: 4 metre 150
santim yerine 5 metre 50 santim demek daha mantıklı bence:)) Tabi bunu yaparken yukarıdaki
örnekten daha gelişmiş bir hata ayıklama mekanizması kullanacağız. Bir
Hata sınıfımız olacak ve bu hata sınıfı ile cm olarak girilen değeri ve bu
değerin hangi fonksiyon tarafından gönderildiğini saklayacağız. Hata sınıfının MetreSantim
sınıfına özgü olduğunu vurgulamak için ise iç içe(nested) sınıf tanımlaması
yapacağız. Yani Hata sınıfının bildirimini MetreSantim sınıfının içinde yapacağız.
Hata sınıfı, hatanın(throw işleminin) hangi fonksiyondan geldiğini tutacak char
türden bir dizi ve hataya sebep olan değeri tutan int türden elemanlardan oluşacaktır.
Aşağıdaki kodları inceleyerek hata mekanizmasının nasıl çalıştığını çok iyi
anlayabilirsiniz. Satır aralarındaki yorumları iyice anlamaya çalışın.
#include
#include
#include
//Yukarıda belirttiğimiz gibi MetreSantim sınıfının bildirimi
class
MetreSantim{
int m;
int cm;
public:
MetreSantim(int m1, int cm1);
void Put(int m1,int cm1);
void Show();
class Hata{
public:
int deger;
char str[200];
Hata(int hatadegeri,char *fonk){
deger=hatadegeri;
strcpy(str,fonk);
}
};
};
/*Sınıf bildirimi Sonu. Hata sınıfına ait kurucu fonksiyonu
Hata'nın geldiği fonksiyonun ismini ve hataya sebep olan değeri işler.*/
MetreSantim::MetreSantim(int
m1,int cm1){
if ( cm1 > 99 ) throw(Hata(cm1,"Kurucu İşlev"));
m=m1;
cm=cm1;
}
/*MetreSantim kurucu işlevi içinde throw işlemi ile bir
Hata nesnesi oluşturup Catch bloğuna gönderiyoruz.Hata sınıfının kurucu işlevinin
parametrik yapısına dikkat edniz.*/
void MetreSantim::Put(int m1,int cm1)
{
if ( cm1 > 99 ) throw(Hata(cm1,"Put Fonksiyonu"));
m=m1;
cm=cm1;
}
/*MetreSantim
sınıfına ait Put() fonksiyonu da yakalamak
istediğimiz hataya neden olabildiği için santimetre olarak 100 'den büyük değer
girildiğinde throw ile catch bloğuna bir hata nesnesi fırlatıyoruz.Tabi hata
nesnesine uygun bilgileri yerleştiriyoruz.*/
void MetreSantim::Show()
{
cout << "(" << m << ","
<< cm << ")" << endl;
}
/*Show() fonksiyonun ne yaptığını anlatmama gerek yok
sanırım.Tabi ekranda hiçbir zaman "(5,150)" şeklinde bir yazı göremeyiz.Bizim de
istediğimiz buydu zaten değilmi?*/
void main(void)
{
try {
MetreSantim x(5,10);
x.Show();
x.Put(10,150);
}
catch(MetreSantim::Hata err)
{
cout << "Santimetre olarak "
<< err.deger << "değerini giremessiniz ->>" <<
err.str << endl;
}
}
/*Main
de try bloku içine hata oluşabilecek kodları yazıyoruz.x.put(10,150); dediğimizde
Put() işlevi içinden catch blokuna throw ile gelineceği için ekrana "Santimetre
olarak 150 değerini giremezsiniz->>Put Fonksiyonu" yazısı çıkacaktır.
Eğer MetreSantim x(5,10); yerine MetreSantim
x(5,150); yazsaydık bu sefer ekrana "Santimetre
olarak 150 değerini giremezsiniz->>Kurucu İşlev" yazısı çıkacaktı*/
Umarım exception
handling konusuna bu kısa girişten sonra iyice aşina olmuşsunuzdur. Exception
handling konusu ile ilgili diğer yazılarımız için C#nedir?com 'u takip etmenizi
öneririm. Bundan sonraki yazılarımızda Standart hata yakalama sınıflarının yapısını
ve nasıl kullanıldıklarını öğreneceğiz.
Makale:
C++ Exception Handling(Hata Yakalama) C++ ve C++.NET dili Sefer Algan
|
|
|
-
-
Eklenen Son 10
-
Bu Konuda Geçmiş 10
Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
Son Eklenen 10 Makale Yükleniyor
Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor
|
|