11 Eylül 2020 Cuma

QuickBasic - 7: Alt program ve Fonksiyon

Yayınlama: 2000
Güncelleme: 11 Eylül 2020
Programlarımızdaki kodlar arttıkça veya programın işlevleri arttıkça bazı tekrar eden kod grupları olabilir.

Ya da içinde birkaç değer değiştirerek aynı işlemleri yapmak gerekir. Bunun için alt programlar(alt rutin, subroutine) kullanılır.

Ayrıca fonksiyonlar ve alt programlar kullanmak, program kodlarınızın düzenlenebilirliğini ve okunurluğunu kolaylaştıracaktır.

GOTO

GOTO komutunu daha önce döngü oluştururken de görmüştük. GOTO ile alt program oluşturmak hiç kullanışlı değildir.

Aslında GOTO ve GOSUB komutlarına çok az ihtiyaç duyacaksınız.
Sadece önceki basic dillerine uyumlu olsun diye konulmuş.
GOTO ile program akışı belirtilen satıra atlar ve çalışmaya oradan devam eder.

Örnek:
PRINT "MERHABA DÜNYA"
GOTO 10
PRINT "BU SATIRI GÖREBİLECEK MİSİNİZ?"
10 PRINT "PROGRAM SONA ERDİ"
END

GOSUB ... RETURN

Kullanımı:
GOSUB satır_no | satır_etiketi
GOSUB ve ardından bir satır etiketi ya da satır numarası yazılmalı.

GOSUB ile alt programlar oluşturulur. GOSUB da GOTO gibi program akışı belirtilen satıra atlaması sağlanır. Fakat GOTO'dan farklı olarak RETURN komutunun olduğu satırdan kaldığı satıra geri dönerek çalışmasına devam eder.

Alt programı, istediğimiz satırdan istediğimiz kadar çağırabiliriz.
Gosub ile atladığımız satırdan sonra RETURN bulunmazsa geri dönüş olmaz.

GOSUB yerine SUB kullanmak daha kullanışlı ve modüler yapı olacaktır.

Örnek 1:
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
Örnek 2:
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 ... END 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 zorlaşır. QuickBasic'te modüler programlama için Sub ve Function komutları geliştirilmiştir.

Oluşturduğunuz modülleri diğer QuickBasic 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.

Başlangıç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 alt programlamayı kullanacaksınız belki de.

SUB yapısı:
SUB altprogramadi (varsa parametreleri) [STATIC]
..
..
[EXIT SUB] ' alt programdan çıkılmak istenirse
..
..
END SUB ' alt program sonu
[ ile ] arası şart değil gerekirse kullanılır.
altprogramadi: değişken adı tanımlaması gibidir. Alt rutin bu isimle çağrılır.

Alt rutin iki şekilde çağrılır. İşlev bakımından ikisi arasında fark yoktur
1) CALL altprogramadi(parametre1, parametre2, ...)
2) altprogramadi parametre1, parametre2, ...
Parametre yoksa sadece altprogramadi yazılır.

STATIC:
Belirtilmediğinde, alt program sonlandığında alt program içinde kullanılan değişken değerleri sıfırlanır. Tekrar alt program çağrıldığında değişken değeri 0 olur. Değişken string ise değeri boştur ("")

Belirtilirse, alt program içindeki değişken değerleri STATIC olarak tanımlanmış olur. Yani alt program sonlandığında değerleri bellekte saklanır. Tekrar alt program çağrıldığında önceki değerleri ile devam eder.

EXIT SUB: Yazılan satırdan sonrası çalıştırılmadan alt programı sonlandırır. Genelde alt programı test etmek için ya da bir şarta bağlı olarak çıkış sağlamak için kullanılır.
Örneğin: IF A>40 THEN EXIT SUB

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

Eklenen alt program ayrı bir sayfa olarak görünür.

SUB, FUNCTION listesini görmek ve istediğinizi düzenlemek için menüden View / SUBs... veya klavyeden F2 tuşuna basın.

Örnek:
CLS
yaziyaz "Merhaba", 3
CALL yaziyaz("Dünya", 7)
CALL yaziyaz("QuickBasic", 12)
yaziyaz "v4.5", 15

SUB yaziyaz (yazi$, satir AS INTEGER) STATIC
	r% = r% + 1
	LOCATE satir
	COLOR r% + 10
	PRINT r%, yazi$
	PRINT STRING$(30, "-")
END SUB

Uygulama

Menüden File / New Program ile yeni bir program yazmaya 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ş QuickBasic dosyamız oluyor ve alt programların anası(MAIN)dır.
Dosyayı kaydettiğimizde bu isim değişir.
yaziyaz ise alt program ismi.


Alt tarafta seçili olanlar:

Edit in Active: Seçili alt programı düzenlemek için aç
Edit in Split: Seçili alt programı ayrı bölme olarak aç
Delete: Modülü yani alt programı sil
Move: Modülü açık olan başka bir QuickBasic 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ı çalıştırın.
Sonra kodları aşağıdaki gibi düzenleyip çalıştırın.
CLS
yaziyaz
yaziyaz
Buradaki kodlama kolaylığını anlamaya çalışın.
QuickBasic'te 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.

Ö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
Üstteki örnekteki STATIC ekini silip farkı görün.

DECLARE

Alt program adı ve parametreleri program satırları başına DECLARE ile ilave edilir.
Kaydedilmemiş bir dosyayı kaydettiğinizde; Untitled yazısı kaydettiğiniz isimle değişir. Ayrıca ana program kodlarının en başına
DECLARE SUB altprogramadi ()
satırını otomatik ekler. Normalde alt programın ana programa dahil edilmesi için bu satırın yazılması gereklidir. Ancak QuickBasic editörü bunu otomatik olarak yapıyor.

Parametre kullanımı:

Alt programa bazı değerler gönderip, gönderilen değerlere göre farklı sonuçlar üretmesini sağlayabiliriz.
Önceki örnekteki SUB'da parametre yoktu.
Parametrelerde kullanılan değişkenlerin veri tipleri belirtilmezse SINGLE olarak kabul edilir.

Örnekler:
SUB yaziortala (satir AS INTEGER, yazi AS STRING)
aynı satırı aşağıdaki gibi yazabiliriz. Bir fark oluşturmayacaktır.
SUB yaziortala (satir%, yazi$)
Örnek:
CLS
DECLARE SUB yaziortala (satir AS INTEGER, yazi AS STRING) 
cizgi$ = STRING$(60, "-")
yaziortala 1, cizgi$
yaziortala 2, "Merhaba"
yaziortala 3, "Bugün QuickBasicte Goto, GoSub, Sub ve Function u öğrendim"
'farklı bir kullanım: CALL ile alt programı çağırma 
CALL yaziortala(5, "QuickBasic Öğrenmek çok kolay") 
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ı yazdırmayı deneyin
    yazisagayasla 4 , "Merhaba"
    gibi.

DEF FN

Verileri işleyip işlenen veriden sonuç üreten yönteme fonksiyon denir.
QuickBasic'te çok sayıda dahili fonksiyon bulunur.

Örnek:
ASC, ATN, CDBL, COS, CSNG, CSRLIN, CHR$, CVD ... Diğerleri için QuickBasic'te menüden Help / Index'e bakınız.

Ancak bu dahili fonksiyonlar tüm ihtiyacı karşılamaz. QuickBasic ve birçok programlama dilinde kullanıcının kendi fonksiyonu yazması için özellik bulunur.
QuickBasic'te 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 ... END FUNCTION

Function'ların yapısı SUB'lar gibidir. SUB'da açıklananlar bunda da geçerlidir.
Function'un farkı verilen değerler üzerinde işlem yapıp bir sonuç ile geri döndürmesidir.

QuickBasic'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 kendi fonksiyonumuzu oluşturalım.

Örnek 1:
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 2:
CLS
PRINT buyuksayi(15, 25)

FUNCTION buyuksayi (sayi1, sayi2)
    IF sayi1 > sayi2 THEN
        buyuksayi = sayi1
    ELSE
        buyuksayi = sayi2
    END IF
END FUNCTION
Örnek 3:
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 4:
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 "QuickBasic öğ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 "QuickBasicte 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.

Alt programdaki tüm değişkenlerin STATIC olması için SUB veya FUNCTION tanımlama satırı sonuna STATIC eklenir.
Örneğin: FUNCTION test (p1, p2) STATIC

COMMON

COMMON, SHARED gibidir ama daha genel bir tanımlama yapılır.
QuickBasic 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.


Önceki Bölüm: 6: Diziler Sonraki Bölüm: 8: Karakterler ve metinlerle ilgili işlemler

Hiç yorum yok:

Yorum Gönder