Etiketler

25 Mayıs 2020 Pazartesi

QuickBasic Kursu: Bölüm 7: Goto, Gosub, Sub, Function

Önceki Bölüm: QuickBasic Kursu: Bölüm 6: Diziler
Yayınlama Eylül 2007
Güncelleme: 18 Haziran 2020
Programlarımızdaki kodlar arttıkça veya programın işlevleri arttıkça bazı tekrar eden işlemler gerekli olabilir.
Ya da içinde birkaç şey değiştirerek aynı işlemler yapmak gerekir. Bunun için alt programlar kullanılır.
Ayrıca fonksiyonlar ve alt programlar kullanmak programınızın okunurluğunu kolaylaştıracaktır.

GOTO

GOTO komutunu daha önce döngü oluştururken de görmüştük.
Aslında GOTO ve GOSUB komutlarına çok az ihtiyaç duyacaksınız.
Sadece diğer basic dillerine uyumlu olsun diye konulmuş.
Program kodunun herhangi bir yerinde işleyişini bırakıp başka bir noktadan çalışması için kullanılır. GOTO ve ardında bir etiket yada satır numarası yazılmalıdır.
PRINT "MERHABA DÜNYA"
GOTO 10
PRINT "BU SATIRI GÖREBİLECEK MİSİNİZ?"
10 PRINT "PROGRAM SONA ERDİ"
END

GOSUB

GOSUB ile alt programlar oluşturabiliriz.
GOSUB da GOTO gibi programın işleyişi bırakıp başka bir noktadan başlaması sağlanır.
Fakat farklı olarak RETURN komutunu görünce kaldığı yere geri dönerek çalışmasına devam eder.
Alt programa, istediğimiz yerden istediğimiz kadar atlayabiliriz.
GOSUB ve ardından bir etiket ya da satır numarası yazılmalı.
Gosub ile atladığımız yerde RETURN bulunmazsa geri dönüş olmaz.

GOSUB yerine SUB kullanmak daha kullanışlı ve modüler yapı olacaktır.
Hatta "Kodlarınızda GOTO ve GOSUB kullanıyorsanız kendinizi yeterince geliştirememişsiniz" diye bir düşünce de var.
CLS
GOSUB CIZGICIZ 
PRINT "MERHABA DÜNYA"
GOSUB CIZGICIZ
PRINT "QUICK BASIC"
GOSUB CIZGICIZ
PRINT "PROGRAMLAMA DİLİ"
GOSUB CIZGICIZ
END ' programı burada sonlandırmazsak
' alt program da çalışır ve hata oluşur
CIZGICIZ:
PRINT "----------------"
RETURN
2. program
CLS
PRINT "çift sayılar(1-100)"
DO
 A = A + 1
 IF (A MOD 2) = 0 THEN GOSUB CIFTSAYI
LOOP UNTIL A = 100
END
CIFTSAYI:
PRINT A;
RETURN

SUB

GW-Basic gibi diğer eski BASIC dillerinde SUB veya FUNCTION özellikleri yoktur.
O yüzden program kodları büyüdükçe okumak ve kontrol etmek epey zor olacaktır. Ayrıca modüler programlama için Sub ve Function komutları geliştirilmiştir.

Oluşturduğunuz alt rutinleri diğer Qbasic dosyalarına kolaylıkla ekleyebilir, taşıyabilirsiniz. Sizin ya da başkalarının yazdığı alt rutinleri kütüphane(library) dosyasından kullandığınız dosyaya referans ile çağırıp(INCLUDE) Sub ya da fonksiyonları kullanabilirsiniz. Böylece; tekrar kod yazma ve kod karmaşasından kurtulmuş olursunuz.

İlk başta SUB ve FUNCTION'ların faydalarını anlamak zor olabilir.
Alıştığınızda bir defa yapacağınız işlemler için bile bunları kullanacaksınız belki de.

Sub yapısı:
SUB altprogram_ismi (varsa parametreleri) [STATIC]
..
..
[EXIT SUB] ' alt programdan çıkılmak istenirse
..
..
END SUB ' alt program sonu
[ ile ] arası şart değil gerekirse kullanılır.

Bir SUB veya FUNCTION eklemek için EDIT menüsündeki New Sub... ya da New Function dan faydalanabilirsiniz ya da direkt boş satırdan SUB veya FUNCTION ile başlayıp yazabilirsiniz.

Alt programı eklediğinizde bunlar ayrı bir sayfa olarak görünür.
SUB, FUNCTION listesini görmek ve istediğinizi incelemek için menüden View / SUBs... veya klavyeden F2 tuşuna basın.

Uygulama:

Menüden File / New Program ile yeni bir projeye başlayın.
SUB yaziyaz yazıp ENTER' e bastığımızda hemen iki alt satıra END SUB yazıldığını göreceksiniz.


Aşağıdaki kodları SUB ile END sub satırları arasına ekleyin.
PRINT "================="
PRINT "==   MERHABA   =="
PRINT "================="
F2 tuşuna basın Alt programları listeleyen ekran gelecek.
Untitled kaydedilmemiş Qbasic dosyamız oluyor ve alt programların anası(MAIN) oluyor.
Dosyayı kaydettiğimizde bu isim değişir.
yaziyaz ise alt program ismi.

Alt tarafta seçili olanlar:
Edit in Active: Düzenlemek için aç
Edit in Split: Düzenleme ekranına ayrı bir bölme olarak aç
Delete: Modülü yani alt programı sil
Move: Modülü açık olan başka bir Qbasic dosyaya taşı.

Siyah şerit Untitled üzerindeyken ENTER'e basın.
Şimdi oluşturduğumuz alt programı çağıracağız.
Çağırmak için yalnızca yaziyaz yazabiliriz.
Ama programın okunurluğu açısından CALL yaziyaz ile çağırmak en doğrusu olacaktır.

F5 ile programımızı çalıştırdığımızda çalıştığını göreceksiniz.
Kodları şu hale getirip çalıştırın.
Buradaki kodlama kolaylığını öğrenmeye çalışın.
CLS
yaziyaz
yaziyaz
Qbasic'de aynı anda çok sayıda dosya açılabilir.
Açık dosyayı kapatmadan başka bir dosya açmak(eklemek) için: Menüden File / Load File... kullanın.
Eğer menüde Load File... görünmüyorsa menüden OPTIONS/Full Menus'ü seçili yapın.

Normalde alt programlardaki değişkenler, alt programdan çıkıldığında değişken değerleri sıfırlanır.
SUB ya da FUNCTION tanımlama satırının sonuna STATIC eklendiğinde alt programdaki değişken değerleri korunur(bellekte tutulur). Aşağıdaki örneği STATIC olmadan deneyip farkını görün.
Örnek:
DECLARE SUB saydir ()
CLS
FOR n = 1 TO 5
    CALL saydir
NEXT

SUB saydir STATIC
    a = a + 1
    b = b + 5
    c = c + 10
    PRINT "a="; a, "b="; b, "c="; c
END SUB
Çıktı:
a=1    b=5     c=10
a=2    b=10    c=20
a=3    b=15    c=30
a=4    b=20    c=40
a=5    b=25    c=50

DECLARE

Dosyayı kaydettiğinizde; Untitled yazısı kaydettiğiniz isimle değişecek.
Ayrıca ana program kodlarının en başına
DECLARE SUB yaziyaz ()
satırının otomatik eklendiğini göreceksiniz. Normalde alt programın ana programa dahil edilmesi için bu satırın yazılması gereklidir. Ancak Qbasic editörü bunu bizim yerimize otomatik yapıyor.

Parametre kullanımı:

Alt programa bazı değerler gönderip, gönderilen değerlere göre farklı sonuçlar üretmesini sağlayabiliriz.
Az önceki SUB da parametre yoktu.
Parametrenin  veri tipinin ne olacağını belirtmekte fayda var.
Belirtilmezse SINGLE olarak kabul edilir.
Bazı örnekler:
SUB yaziortala (satir AS INTEGER, yazi AS STRING)
aynı satırı şöyle de yazabiliriz
SUB yaziortala (satir%, yazi$)
'Örnek program:
CLS
DECLARE SUB yaziortala (satir AS INTEGER, yazi AS STRING) 
cizgi$ = STRING$(60, "-")
yaziortala 1, cizgi$
yaziortala 2, "Merhaba"
yaziortala 3, "Bugün Qbasic de Goto, GoSub, Sub ve Function u öğrendim"
'farklı bir kullanım: CALL ile alt programı çağırma 
CALL yaziortala(5, "Qbasic Öğrenmek çok zevkli") 
yaziortala 6, cizgi$
SUB yaziortala (satir AS INTEGER, yazi AS STRING)
   uzunluk% = LEN(yazi)
   LOCATE satir, (80 - uzunluk%) / 2
   PRINT yazi
END SUB

PROBLEM:

  1. Yukarıdaki programı alt program kullanmadan yapmaya çalışın.
  2. Alt program kullanarak sağa yaslı yazı yardırmayı deneyin
    yazisagayasla 4 , "Merhaba"
    gibi.

DEF FN

Verileri işleyip işlenen veriden sonuç üreten yönteme fonksiyon denir.
Qbasic'de çok sayıda dahili fonksiyon bulunur.
Örnek: ASC, ATN, CDBL, COS, CSNG, CSRLIN, CHR$, CVD ... Diğerleri için Qbasic'de menüden Help / Index'e bakınız.

Ancak bu dahili fonksiyonlar tüm ihtiyacı karşılamaz. Qbasic ve birçok programlama dilinde kullanıcının kendi fonksiyonu yazması için özellik bulunur.
Qbasicde bu özellik DEF FN veya FUNCTION ile yapılır. DEF FN eski BASIC dilleri ile uyum için konulmuştur.
Kendini çağırma(recursive) özelliği yoktur. Bunun yerine modüler yapıya sahip kendini çağırabilen FUNCTION tavsiye edilir.

DEF FN Kullanımı:
1) Tek satır ile:

DEF FNfonksiyonadı [parametre listesi] = fonksiyonkodu

Örnek:
DEF FNortalama (sinav1, sinav2, sinav3) = (sinav1 + sinav2 + sinav3) / 3
ort = FNortalama(62, 70, 87)
PRINT ort '73
2) Blok olarak:
DEF FNfonksiyonadı [parametre listesi]
...
FNfonksiyonadı = fonksiyonkodu
...
END DEF
Örnek:
DEF FNdereceRadyana# (derece AS DOUBLE)
    radyan# = derece * (4 * ATN(1) / 180#)
    FNdereceRadyana# = radyan#
END DEF
PRINT FNdereceRadyana#(90)
x = FNdereceRadyana#(30)
PRINT SIN(x) '.5
DEF FN ile tanımlanan fonksiyon, tanımlama satırından önce kullanılamaz.
Kullanılırsa Function not defined (Fonsiyon tanımlanmamış) hatası verir.

FUNCTION

Functionların yapısı SUB lar gibidir. SUBdaki açıklananlar bunda da geçerlidir.
Function'un farkı verilen değerler üzerinde işlem yapıp bir sonuç ile geri döndürmesi. Qbasic in kendi yapısındaki birçok komutun Function özelliği vardır. Örneğin: X = SQRT(81) yazdığımızda verilen 81 sayısı SQRT(karekök alma) fonksiyonu tarafından işlenir ve sonuç olarak 9 döner.
Bu sonuç X değişkenine atanır. Şimdi biz kendimiz bir fonksiyon oluşturalım.
X = karesi(15)
PRINT X
PRINT "20 nin karesi = "; karesi(20)
PRINT "1.4 ün karesi = "; karesi(1.4)
FUNCTION karesi (sayi AS DOUBLE)
    DIM sonuc AS DOUBLE
    sonuc = sayi * sayi
    karesi = sonuc
END FUNCTION
Function da tek satır ile sonucu alabilirdik. Anlaşılır olması bakımından uzun yazıldı.
Kısa olarak:
FUNCTION karesi (sayi AS DOUBLE)
    karesi = sayi * sayi ' alternatif: karesi = sayi ^ 2
END FUNCTION
Örnek 1:
CLS
PRINT enbuyuksayi(15, 25)
FUNCTION enbuyuksayi (sayi1, sayi2)
    IF sayi1 > sayi2 THEN
        enbuyuksayi = sayi1
    ELSE
        enbuyuksayi = sayi2
    END IF
END FUNCTION
Örnek 2:
DIM sayi(10)
CLS
FOR n = 0 TO 10
    READ sayi(n)
NEXT
x = ortalama(sayi())
PRINT "Sayıların ortalaması:"; x
DATA 25,61,5,84,92,46,74,8,63,15,37
FUNCTION ortalama (sayilar())
    FOR n = LBOUND(sayilar) TO UBOUND(sayilar)
        t = t + sayilar(n)
    NEXT
    ortalama = t / n
END FUNCTION
Örnek 3:
CLS
derece = 30
radyan = DegToRad(derece)
PRINT "Derce  :"; derece
PRINT "Radyan :"; radyan
PRINT "Sinüs  :"; SIN(radyan)
PRINT "Kosinüs:"; COS(radyan)
FUNCTION DegToRad (deg)
    Pi = 4 * ATN(1) 'Pİ sayısı
    DegToRad = deg * (Pi / 180)
END FUNCTION

DEGİŞKEN KAPSAMI

Varsayılan olarak tanımlanan değişken tanımlandığı modül içinde değerini korur. Diğer modüllerde geçerliliği olmaz. Diğer modüllerde aynı adla bir değişken varsa bu değişken o modül kapsamındadır. Diğerini etkilemez.
Örnek 1:
CLS
DIM a
a = 5
CALL modul1
PRINT "Ana programda A Değeri:"; a
SUB modul1
    PRINT "Alt programda A değeri:"; a
END SUB
Çıktı:
Alt programda A değeri: 0
Ana programda A değeri: 5
Örnek: 2
CLS
DIM A
A = 100
CALL modul1
PRINT "Ana programda A Değeri:"; A
SUB modul1
    A = 125
    PRINT "Alt programda A değeri:"; A
END SUB
Çıktı:
Alt programda A değeri: 125
Ana programda A değeri: 100

SHARED

Bazen de bir değişkenin değerini kaybetmeden tüm SUB ve FUNCTION içinde geçerli olması istenebilir. Buna değişkeni global tanımlama(genel, ana ve alt programlarda geçerli) diyoruz. Alt program içinde DIM ile yapılan değişken tanımlamaları yerel tanımlamadır (lokal, sadece alt program içinde geçerlidir)
Ana programda paylaşımlı değişken tanımlamak için DIM SHARED kullanılır.
Alt programda tanımlanan değişkenin ana modülde de geçerli olması için SHARED ile tanımlanması gerekir. Alt programda SHARED ile tanımlanan değişken tanımlanan modülde ve ana modülde geçerli olur. Diğer modüllerde geçerli olmaz.
Aşağıdaki örneklerdeki DIM SHARED satırını iptal edip sonucu gözlemleyin.
Örnek 1:
DIM SHARED satir AS INTEGER
CLS
satir = 2
LOCATE satir: PRINT "Merhaba"
yaziortala "Qbasic öğreniyorum"
satir = satir + 1
LOCATE satir: PRINT "Çalışan başarır"
yaziortala "İstiyorsan başarırsın"
SUB yaziortala (yazi AS STRING)
    satir = satir + 1
    LOCATE satir, (80 - LEN(yazi)) / 2
    PRINT yazi
END SUB
Örnek 2:
DIM SHARED a
CLS
a = 2
PRINT a '2
CALL karesi
PRINT a ' 4
CALL kupu
PRINT a ' 64
CALL kupu
PRINT a ' 262144
SUB karesi
    a = a * a
END SUB
SUB kupu
    a = a ^ 3
END SUB
Örnek 3:
CLS
a = 50
PRINT "Ana Modül, A="; a '50
CALL modul1
PRINT "Ana Modül, A="; a '150
CALL modul2
PRINT "Ana Modül, A="; a '150
CALL modul3
PRINT "Ana Modül, A="; a '150
SUB modul1
SHARED a
PRINT "Modül 1, A="; a '50
a = a + 100
PRINT "Modül 1, A="; a '150
END SUB
SUB modul2
    PRINT "Modül 2, A="; a '0
    a = 2020
    PRINT "Modül 2, A="; a '2020
END SUB
SUB modul3
    PRINT "Modül 3, A="; a '0
    a = 1000
    PRINT "Modül 3, A="; a '1000
END SUB
Örnek 3'de A değişkeni sadece Ana ve modul1 de paylaşımlıdır. Diğer modüllerdeki A değişkeni farklı bir değişken olarak değerlendirilir ve sadece kendi modülü içinde değerini korur. SHARED satırını silip tekrar çalıştırın ve sonucu gözlemleyin.

STATIC

Alt program içinde tanımlanan değişkenin değeri alt programdan çıkıldığında değeri sıfırlanır.
Alt program tekrar çağrıldığında eski değerin tutulması için değişken STATIC ile tanımlanır.
Örnek 1:
CLS
a = 100
FOR n = 1 TO 10
    CALL topla
NEXT
PRINT a
SUB topla
    STATIC a
    a = a + 20
    PRINT a
END SUB  
Örnek 2:
CLS
yaziortala "Merhaba !"
yaziortala "Qbasicde Function ve Sub Kullanmak kodlamayı kolaylaştırıyor"
yaziortala "Öğrenmem gereken daha çok şey var sanırım."
SUB yaziortala (yazi AS STRING)
    STATIC satir AS INTEGER
    satir = satir + 1
    LOCATE satir, (80 - LEN(yazi)) / 2
    PRINT yazi
END SUB
Burada dikkat ederseniz SUB a satır numarasını göndermedik 0 dan başladı her SUB başlamasında 1 arttı ve yazılar alt alta ortalı olarak yazıldı.
STATIC i DIM ile değiştirin farkı göreceksiniz.

COMMON

COMMON, SHARED gibidir ama daha genel bir tanımlama yapılır.
Qbasic ile CHAIN komutuyla başka bir bas dosyaya bağlantı kurabiliriz.
Değişken COMMON ile tanımlama yapılırsa değeri bağlantı kurulan bas dosyada da geçerli olur.
Zaten başlangıçta tek bas dosya üzerinde çalışacağınızdan bu gerekli olmayacak.

Sonraki Bölüm:
QuickBasic Kursu: Bölüm 8: Karakterlerle ilgili işlemler

QuickBasic Ana Sayfa

Hiç yorum yok:

Yorum Gönderme