BUYUKDIN.C:
================================================== ==
main()
{
struct hayvan {
char ismi[25];
char cinsi[25];
int yasi;
} *evcil[12], *point; /* bu, 13 tane pointer ve
0 degisken tanimliyor */
int index;
/* ilk once, dinamik sahayi ivir zivirla dolduralim. */
for (index = 0;index < 12;index++) {
evcil[index] = (struct hayvan *)malloc(sizeof(struct hayvan));
strcpy(evcil[index]->ismi,"General");
strcpy(evcil[index]->cinsi,"Karisik cins");
evcil[index]->yasi = 4;
}
evcil[4]->yasi = 12; /* Bu atamalar, bazi sahalara */
evcil[5]->yasi = 15; /* nasil luzumsuz bilgi */
evcil[6]->yasi = 10; /* yazilabilecegini gosterir. */
/* yukarda tanimladiklarimizi yazalim. */
for (index = 0;index <12;index++) {
point = evcil[index];
printf("%s, bir %s, ve %d yasindadir.n", point->ismi,
point->cinsi, point->yasi);
}
/* Iyi programlama teknigi, dinamik yaratilmis sahanin, */
/* sisteme iade edilmesini soyler.. */
for (index = 0;index < 12;index++)
free(evcil[index]);
}
=================================================
Bu program, bir oncekine cok benzer. Basit tutmak icin, 12 elemanlik bir
pointer dizisi tanimliyoruz, ve bir "point" isimli bir pointer daha
tanimliyoruz.
Size yeni olan "*evcil[12]" terimini biraz anlatmakta fayda var. Burada
yaptigimiz 12 tane pointer'dan olusan bir dizi tanimladik. Ilki "evcil[0]"
ve sonuncusu "evcil[11]". Aslinda, bir diziyi indekssiz kullanmak, o
dizinin adresini verdiginden, kendi basina "evcil" demekle, pointerin
pointerini tanimlamis oluyoruz. Bu C de tumuyle yasaldir, ve hatta daha
ileri de gidebilirsiniz - fakat cabucak kafaniz karisir. Dolayisi ile,
"int ****pt" demek, yasaldir, ve bu bir pointer'in pointer'inin
pointer'inin pointer'ini tanimlar - sayet dogru saydiysam. Iyice C ye
alisincaya kadar bu tip seylerden kacinmanizi tavsiye ederim.
Simdi, 12 tane pointer'imiz var, ve biz bunlar herhangi bir pointer gibi
kullanabiliriz. Bir dongu icinde kendimize dinamik yer acip, icine
istedigimiz verileri yazabiliriz. Rastgele secilmis bazi sahalara yeniden
bilgi atadiktan sonra, ekrana sonuclari yaziyoruz. "point" isimli pointer,
sadece size gosterme amaci ile kullanilmistir. Veri, "evcil[n]" diyerek
tanimlanabilirdi. Son olarak 12 veri bloku "free" ile serbest birakilir ve
program sona erer.
c dersleri 12.bölüm
BUYUK VE KUCUK HARFLER
BUY-KUC.C:
==================================================
#include <STDIO.H>
#include <ctype.h> /* Not: Derleyiciniz bunu gerektirmeyebilir */
main()
{
FILE *fp;
char satir[80], kutukismi[24];
char *c;
printf("Kutuk ismini girin -> ");
scanf("%s",kutukismi);
fp = fopen(kutukismi,"r");
do {
c = fgets(satir,80,fp); /* bir satir oku */
if (c != NULL) {
karistir_butun_karakterleri(satir);
}
} while (c != NULL);
fclose(fp);
}
karistir_butun_karakterleri(satir)
/* Bu fonksiyon butun buyuk harfleri kucuge, butun kucukleri
de buyuge cevirir. Diger butun karakterleri etkilemez. */
char satir[];
{
int index;
for (index = 0;satir[index] != 0;index++) {
if (isupper(satir[index])) /* buyuk harfse,1 doner */
satir[index] = tolower(satir[index]);
else {
if (islower(satir[index])) /* kucuk harfse,1 doner */
satir[index] = toupper(satir[index]);
}
}
printf("%s",satir);
}
=================================================
Bu basit programdaki yeni fonksiyonlar sunlardir:
isupper(); Karakter buyuk harfmidir?
islower(); Karakter kucuk harfmidir?
toupper(); Karakteri buyuk harf yap.
tolower(); Karakteri kucuk harf yap.
ilk fonksiyon, sayet parametresi olarak gecirilen deger, buyuk harf ise
('A'-'Z'), 1 degerini dondurur, sayet baska bir karakter ise, 0 degeri doner.
ikincisi, sayet parametresi kucuk harf ise, 1 degerini dondurur.
3uncu ve son fonksiyonlar ise, parametre olarak gecirilen karakteri buyuk
yada kucuk harfe degistirirler.
KARAKTERLERIN SINIFLANDIRILMASI
KARKLAS.C:
=================================================
#include <stdio.h>
#include <ctype.h> /* Derleyiciniz bunu gerektirmeyebilir */
main()
{
FILE *fp;
char satir[80], kutukismi[24];
char *c;
printf("Kutukismi -> ");
scanf("%s",kutukismi);
fp = fopen(kutukismi,"r");
do {
c = fgets(satir,80,fp); /* bir satir oku */
if (c != NULL) {
veriyi_say(satir);
}
} while (c != NULL);
fclose(fp);
}
satiri_say(satir)
char satir[];
{
int beyazlar, kars, rakamlar;
int index;
beyazlar = kars = rakamlar = 0;
for (index = 0;satir[index] != 0;index++) {
if (isalpha(satir[index])) /* 1 eger satir[] alfabetik ise */
kars++;
if (isdigit(satir[index])) /* 1 eger satir[] rakam ise */
rakamlar++;
if (isspace(satir[index])) /* 1 eger satir[] bosluk ise tab, */
beyazlar++; /* yada yeni satir ise */
} /* sayan dongunun sonu */
printf("%3d%3d%3d %s",beyazlar,kars,rakamlar,satir);
}
================================================
Bircok yerde, n yi, yeni bir satiri belirtmek icin kullandik, fakat cok
kullanilan baska kontrol karakterleri de vardir. Bu sekilde tanimlidirlar:
n Yeni satir
t Tab
b Bir hane geri
" Cift tirnak
\ Ters bolu
NULL (sifir)
Gordugunuz program, bir karakterin tipini belirleyen fonksiyonlar
kullanir. Kullandigi 3 fonksiyon sunlardir:
isalpha(); Karakter alfabetik mi?
isdigit(); Karakter bir rakam mi?
isspace(); Karakter n , t yada bosluk mu?
Program yeterince basit, bu nedenle daha fazla detaylara girmiyorum..
Bu yeni fonksiyonlarin kullanimi da, ayni "isupper" yada "toupper"
fonksiyonlari gibidir.
c++ dersleri 13.bölüm
Komut Satirinda Verilen Parametrelerin Okunmasi
Parametre Nedir?
Parametre kullancinin, program isminin yaninda yazdigi ek bilgilerdir.
Parametreler, birbirinden bosluk ile ayrilirlar. Kullanici, herhangi bir
komutun yaninda parametreler girebilir. SIMDINE.C de de gorebileceginiz gibi,
bu parametreleri programa gecirmek son derece kolaydir. Bunu yapmak icin,
main(adet,kelime)
int adet;
char *kelime[];
{
seklinde tanimlanmalidir. 'adet' degiskeni, kac tane parametre girildigini
sayar. Bu, sayet hic parametre girilmemisse, 1 dir, ve parametre
girildikce, bu deger artar. Ornegin,
rm -ie myfile.out
orneginde, adet=3 dur, yani komut satirinda birbirinden boslukla ayrilmis
3 sozcuk vardir.
'Kelime' degiskeni ise, bir pointerlar dizisidir. Bu dizinin her elemani,
bellekteki parametrelerin, baslangic adreselerini tutar. Yani,
kelime[0] ----->> rm.exe
kelime[1] ----->> -ie
kelime[2] ----->> myfile.out
gibidir. Daima, 'kelime' nin 0 inci elemani, programin isminin baslangic
adresini tutar, bundan sonra gelen diger 1,2 ve diger indeksler, diger
parametrelerin baslangic adreselerini tutarlar. Kullanimlari, ornegin,
normal bir char buffer[80] tipli bir diziye atamak icin, soyle olabilir:
strcpy(buffer,kelime[2]);
tabii, isim kelime, ve adet olmak zorunda degildir, herhangi birsey
olabilir. C de alisilmis tutum, 'adet' yerine 'argc' ve 'kelime' yerine
'argv' sozcuklerinin kullanilmasidir. Kelimenin kac tane indeksi oldugu,
'adet' degiskeninden bulunabilir: Kelime, daima (adet-1) tane indekse
sahiptir.
c dersleri 14.bölüm
C ve MS-DOS ile Ekran Duzeni
Simdiye kadar kacindigim bir konu ise, ekrani silme, cursor'un yerini
ogrenme yada degistirme, ekranin calisma modunu degistirme gibi konular
iceren ekran duzenidir. Aslinda C nin bir parcasini olusturmamakla
birlikte, bu konu programcilar icin cok onemlidir.
C ye sonradan eklenen bir 'uzanti' oldugu, ve sadece MS yada PC-DOS ile
calisan bilgisayarlarda kullanilabilecegi icin, burada gorecegimiz
int86() fonksiyonu, su anda sadece Microsoft C, ve Turbo C tarafindan
desteklenmektedir. Derleyiciniz baska ise, bu fonksiyon cagirilis
metodunu degistirmeniz gerekebilir.
Cok sayida degisik turde ekran tipleri ile kullanilabilecegi icin, C de
tanimlanmis, hazir ekran fonksiyonlari yoktur. Bu fonksiyonlar,
kullanilacak cihazin yapisina gore tanimlanabilir. Bu konu icerisinde,
elimizdekinin bir IBM-PC yada uyumlu bilgisayar oldugunu kabul edecegiz.
Ekrana Nasil Eriselim?
Temelde, 3 cesit yoldan ekrana erisebiliriz:
1) bir BIOS interruptu ile,
2) DOS'un ANSI.SYS i ile,
3) Direk donanima 'karisarak'.
Her bir metodun avantaj ve dezavantajlari vardir. Daha derine dalmadan
once, dilerseniz bu 'interrupt' lafinin manasini cozelim:
Interrupt
IBM PC ailesi, donanim yada yazilim tarafindan yaratilabilecek
interruptlar ile idare edilebilir. Bir interrupt olustugunda,
bilgisayarin calismasi, bu interruptu halledebilecek bir rutine
yollanir. Bu rutinlerin baslangic adresleri, 'interrupt vektor
tablosu'nda saklanir. Bu tablo, bilgisayarin hafizasinin en alt
kesiminde, ilk bir kilobytelik yerde bulunur. Bu sahada 255 ayri
interrupt icin yer ayrilmistir.
Ornegin, 5. interrupt olustugunda, sistem ilk olarak butun
registerleri (birazdan anlatacagim) saklar, ve bu ilk 1K lik tablodan,
5. "kutu" ya bakip buradaki adresi okur. Sonra, buradan ogrendigi
adrese atlar ve orada ne islemler varsa yapar. Bunlar bitince, tekrar
kaldigi isleme geri doner.
Donanim Interruptlari (Hardware Interrupts): Bunlar, sistem tarafindan
cagirilan rutinlerdir. Ornegin sistem, her saniyede 18.2 kere bir
interrupt ile saatini ilerletmektedir. Bu cagirim, yada interrupt,
donanim tarafindan yaratilmaktadir. Diger bir baska interrupt ise, 9.
klavye interruptudur. Her tusa basildiginda, bu donanim interruptu
olusur.
Yazilim Interruptlari (Software Interrupts): Bunlar ise, herhangi bir
programin cagirabilecegi bir rutinler kutuphanesidir. Ekrana birsey
yazmak gerektigine, yada silmek gerektiginde, bunu bir interrupt
cagirarak yapariz.
BIOS nedir? (BIOS==Basic Input/Output System)
BIOS'un gorevi, bilgisayarin yapmasi gereken temel servisleri yerine
getirmektir. Genis anlamda, BIOS IBM'in icindeki yongalarda bulunan
rutinler kutuphanesidir. BIOS, DOS ile donanim arasinda bir yerde
bulunur. Bir taraftan, bir programdan yapilmasi gereken standart BIOS
komutunu alir. Programimiz, BIOS a bu istegi, bir interrupt vasitasi
ile bildirir. BIOS un diger tarafi ise, bilgisayarin donanim parcalari
(ekran, disk drive, seri port, vs.) ile iliski kurar. BIOS'un bu
tarafi ise, dikkati cekmek icin bir interrupt yaratan bir donanim ile
konusur.
DOS nedir?
DOS ise, bir baska kutuphanedir. Ozellikle diske erisimde uzmanlasmis
olan DOS, bundan baska ekrana yazma, yaziciya bilgi yollama, vs. gibi
servisleri de kapsar. DOS'un da ayni BIOS gibi interruptlari ve
sagladigi bircok servis vardir. Aslinda DOS, cogu bu servisler icin
BIOS'dan yardim gormektedir.
Aklinizda bulunsun: BIOS yongalarda bulunur, DOS ise sonradan
yuklenir.
Simdi, BIOS ile nasil ekran kontrolu yapabilecegimizi gorelim. Bir
kere, butun BIOS ekran fonksiyonlari, bir interrupt ile cagirilir,
bunun da interrupt numarasi 16 dir. Herhangi bir BIOS fonksiyonunu
kullanmak icin yapmamiz gerekenler, once bazi registerleri
degistirmek, onaltinci interruptu cagirmak, ve sonuclari zevkle
seyretmektir.
Register?
IBM-PC ailesinin kullandigi 8088 yongasinin, calismasinda kullandigi
bazi ozel sahalar vardir. Bu sahalara "register" ismi verilir. IBM-PC
de, toplam olarak ondort tane register vardir. PC bunlari, aritmetik
islemler, karsilastirmalar gibi islerde kullanir. Bunlardan dort
tanesini BIOS interruptlari ile kullanacagiz. Bu kullanacaklarimizin
isimleri, AX,BX,CX ve DX dir. Bunlar ayni birer degisken gibi
iclerinde degerler tasiyabilirler. Bu registerlerin bir ozelligi ise,
ister tam olarak, yani butun AX'i birden, istersek de yarim yarim (AH
ve AL yi) degerlerini degistirmemiz mumkundur.
Yani, dilersek AX in icine bir 16 bitlik veri koyabiliriz, yada AL ve
AH lerin iclerine sekizer bitlik veri koyabiliriz. Hep AX i
kullandigima bakmayin, BX i BL ve BH, CX i CH ve CL diye, DX i DL ve
DH diye ayirmamiz mumkun.
Dilerseniz soyle dusunun: Sayet CX dersek, asagidaki butun yapiyi
kastediyoruz:
+--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+
| | | |
+--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+
CH CL
Fakat, CH yada CL dersek yarisini kastediyoruz. Yani CX=5 desek,
yukaridaki kutulara:
+--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+
| 0 0 0 0 0 0 0 0| | 0 0 0 0 0 1 0 1|
+--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+
CH CL
koymus oluruz.. (binary 101, 5 e esittir) Fakat CH=6 desek,
+--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+
| 0 0 0 0 0 1 1 0| | 0 0 0 0 0 1 0 1|
+--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+
CH CL
CL nin eski degerine dokunmamis oluruz. Bir onceki ornekte icine '101'
koydugumuz icin, CL hala o degerde kaldi. Aslinda butun bunlari
bilmemize luzum yok, fakat ileride isinize yarayabilir.
Cursor Pozisyonunu Ayarlamak:
Dilerseniz ilk olarak ekranin istedigimiz bir yerine atlayip, oraya
birseyler yazmayi deneyelim. Bunun icin cursor, yani, bundan sonra
yazilacak noktanin degistirilmesi gereklidir. (Cursor, yanip sonen bir
alt-cizgi gorumundedir, ve donanim ile kontrol edilir.)
POSDEGIS.C:
================================================
#include <dos.h>
void yerlestir(satir,kolon) /* Bu fonksiyon, cursoru istedigimiz */
unsigned satir,kolon; /* bir yere koyar */
{
union REGS giris_register,cikis_register;
giris_register.h.ah = 2; /* 2: set-cursor-position fonksiyonu*/
giris_register.h.dh = satir;
giris_register.h.dl = kolon;
giris_register.h.bh = 0; /* hangi sayfayi degistirelim? */
int86(16,&giris_register,&cikis_register); /* cagiralim, yapsin */
}
============================================
Ilk satirda gordugunuz #include <dos.h>, bu programda sart. Cunku daha
sonra gelen 'union' u tanimliyor. Bu union ile, iki tane degisken
tanimliyoruz, bunlar giris_register ve cikis_register olarak. Daha
sonra, bunlarin gereken elemanlarina verileri atiyoruz. Burada, hangi
elemana hangi verinin konacagi, ve servis numarasi (bizde 2) gibi
verileri, ya MS-DOS Technical Reference Manual'dan yada Peter
Norton'un Programmer's Guide To the IBM-PC den bulabilirsiniz. En son
olarak, int86 fonksiyonu ile, 16. interruptu cagiriyoruz. Sistem ilk
olarak gidip o hafizanin ilk 1K sindaki tablodan 16. interruptun
rutinlerinin baslangic adresini ogreniyor. Daha sonra o adrese
atlayip, ikinci fonksiyonunun yerine geciyor, ve register degerlerine
gore istedigimizi yerine getiriyor.
Ozet: Cursor'u Yerlestirme Fonksiyonu
Interrupt no: 16 Servis No: 2
Gereken Veriler: AH=Servis numarasi, yani 2,
DH=satir numarasi,
DL=kolon numarasi,
BH=Kullanilacak Sayfa Numarasi
Bu sayfa numarasi parametresini merak edebilirsiniz. Normal bir
monokrom ekranin, sadece bir sayfasi vardir. Fakat ornegin CGA (Color
Graphics Adaptor), yani renkli adaptoru 'text' yada metin modunda
calistiginda, sayet satira-40 karakter modundaysa 8 sayfa, sayet
satira-80 karakter modundaysa, 4 sayfayi kullanabilir. Herhangi bir
anda bu sayfalardan biri ekranda gosterilebilir. (Evet - sayfa
degistirmek icin bir baska fonksiyon cagirmak gerekli.) Bazi
programlar bu ozelligi, bir sayfayi kullaniciya gosterirken, bir
digerini hazirlayarak, super-hizli ekran goruntuleri saglamakta
kullanirlar. Ikinci merak edebileceginiz sey,
Cursor Pozisyonunu Okumak
olabilir. Bu da, yukaridaki yaziyi anladiysaniz, son derece kolaydir.
Bu sefer, interrupt'u cagirdiktan sonra donen degerlerle de
ilgilenmekteyiz:
POSOGREN.C:
=============================================
#include <dos.h>
void posogren(satir, kolon) /* Bu fonksiyon, cursorun yerini BIOS yardimi */
unsigned *satir, *kolon; /* ile ogrenir */
{
union REGS giris,cikis;
giris.h.ah = 3; /* fonksiyon 3 - cursorun yerini oku */
giris.h.bh = 0; /* 0 inci sayfa.. */
int86(16,&giris,&cikis);
*satir = cikis.h.dh; /* 3. fonksiyondan donen degerler: */
*kolon = cikis.h.dl; /* DH icinde, cursorun satir no su, */
} /* ve DL icinde kolon numarasi.. */
=================================================
Bu programi calistiran ana program, soyle olabilir:
main()
{
int a,b;
posogren(&a,&b);
printf(" Program calistiginda cursor %d. satir, %d. kolonda idin",a,b);
}
a ve b nin adreslerinin gecirildigine dikkatinizi cekerim.
REGS Union'un Parcalari
Iki programdir gordugunuz REGS isimli union'un parcalari, bize
herhangi bir registerin herhangi bir parcasina erismemizi saglar.
Sayet registerin yarisinin degerini degistirmek istiyorsak, yukaridaki
gibi, degiskenden sonra 'h' koyariz, giris.h. gibi.. Bundan sonra ise,
hangi registerin degismesini istedigimizi soyleriz: giris.h.cl gibi.
Sayet bir registerin yarim yarim yerine tumden degistirmek istersek,
'h' yerine 'x' kullanmamiz gerekir: giris.x.bx gibi..
Ekran Tipini Ayarlamak
Yazdiginiz program, sadece seksen kolonluk bir ekranda calismak icin
duzenlenmis olabilir. Bilmeyen bir kullanici da, ekrani 40 kolona
ayarli iken, programi calistirmayi deneyebilir. Bu tip olaylara mani
olmak icin, programinizin basinda, ekrani istediginiz tipe
ayarlayabilirsiniz. Bunun icin, sifirinci servisi kullanabilirsiniz:
EKRANAYA.C:
==============================================
#include <dos.h>
ekranayar(tip) /* Bu fonksiyon, ekrani istegimiz tipe ayarlar */
short tip;
{
union REGS giris,cikis;
giris.h.ah = 0; /* 0 inci servis - mod degistirmek */
giris.h.al = tip; /* CGA; 0: b/w text 40x25, 1: 16 renk 40x25
2: b/w text 80x25 3: 16 renk 80x25
4: 4 renk Gra 320x200 5: 4 gri Gra 320x200
6: b/w Gra 640x200
MONO: 7: b/w text 80x25 */
int86(16,&giris,&cikis); /* ayarlayalim */
}
================================================
Burada, ekranin yeni tipini belirtmemiz gerekli. Bunun icin, 0 ila 15
arasinda bir deger vermemiz gerekiyor. Bu degerlerin 0 ila 6
arasindakiler, CGA (renkli) icin, 7, monokrom icin, ve 8-10 arasi PCJr
icin, ve sonrasi EGA icindir. EGA, 8 ve 9 haric diger butun ekran
modlarini destekler.
Ekrani Silmek
Gordunuz bile! Ekrani silmek, iki yoldan olabilir. Birincisi, ekranin
modunu degistirmek. Degistirdiginiz mod, su anki mod bile olsa, yine
de ekran silinir. Yegane dezavantaj, Compaq tipi makinelerde bu islem
uzun zaman alir. Dolayisi ile, bu isi dogru yapmamiz gerekir:
EKRANSIL.C:
===============================================
#include <dos.h>
void ekransil() /* bu rutin, ekrani siler */
{
union REGS gir;
gir.h.ah = 6; /* ekrani yukari kaydir: servis no su 6
ekrani asagi kaydir: servis no 7 dir. */
gir.h.al = 0; /* kac satir scroll edecegi 'donecegi'
sifir olunca, butun ekrani siler */
gir.h.ch = 0; /* sol ust kosenin satir no su */
gir.h.cl = 0; /* sol ust kosenin kolon no su */
gir.h.dh = 23; /* sag alt kosenin satir no su */
gir.h.dl = 79; /* sag alt kosenin kolon no su */
gir.h.bh = 7; /* yeni yaratilacak satirlar icin renk degeri */
int86(16,&gir,&gir);
}
==============================================
Altinci BIOS servisi sayesinde, ekrani yukari kaydirma metodu ile
silmekteyiz. Ayni servis sayesinde, CX ve DX de gordugunuz degerleri
degistirerek, ekranin sadece bir parcasini 'scroll' etmek yani
kaydirmak mumkundur. Kaydirma yonunu servis numarasini 6 yada 7
yaparak degistirebilirsiniz. Burada gordugunu gir.h.bh deki deger ise,
yeni acilacak satirlarin 'attribute' yani, rengi ve ozellikleri
(parlak, yanip sonen, vs.) dir. Ayrica, yukaridaki ornekte,
gir.h.ch = 0;
gir.h.cl = 0;
yerine, sadece
gir.x.cx = 0;
diyebilirdik.