Matematiksel Fonksiyonlar
Matematiksel fonksiyonların tipleri double dır. Bu fonksiyonlardan biri program içinde kullanılacaksa math.h başlık dosyası program içine ekelenmelidir. Bu kısımda bu fonksiyonlardan en sık kullanılanlar (sin(),cos(),tan,pow(),sqrt()) anlatılacaktır.
sin() – cos() – tan()
| Fonksiyon | Açıklama | Örnek |
| double sin(double x) | x sayısının sinüs değerini radyan cinsinden hesaplar | y = sin(0.22) |
| double cos(double x) | x sayısının kosinüs değerini radyan cinsinden hesaplar | y = cos(0.14) |
| double tan(double x) | x sayısının tanjant değerini radyan cinsinden hesaplar | y = tan(0.82) |
Ders7: Karşılaştırma Deyimleri
C dilinde if, switch ve ? olmak üzere üç tip karşılaştırma işlemi yapılır. Ancak ? bir operatördür. if karşılaştırma deyimi ile, diğer programlarda olduğu gibi if-else yapısı kurulabilir. switch deyimi, bir değişkenin içeriğine göre program akışını yönlendirme işlemini yapar.
if, if-else Yapısı
Bu deyimler koşullu işlem yapma deyimidir. if ve else tek bir karşılaştırma deyimi olup else kullanımı isteğe bağlıdır. Eğer bu koşul olumlu ise if den sonraki bölüm yürütülür ve else den sonraki bölüm atlanır. Koşul olumsuz ise if den sonraki küme atlanır ve eğer varsa, else den sonraki kümedeki işlemler gerçekleştirilir.
if(koşul)
{
...
deyimler; (küme)
...
}
Program 7.1 de basit olarak if deyiminin kullanımı gösterilmiştir. Programda bu deyim kullanılırken kümenin başngıcı ce bitişini gösteren, küme parantezleri kullanılmamıştır. Eğer if deyiminden sonra icra edilecek deyimler tek satırdan oluşuyorsa, bu işaretlerin kullanılmasına gerek yoktur. Yada if deyimden sonra { ve } işaretleri kullanılmamışsa, bu deyimi takip eden sadece ilk satır işleme konur.
Program 7.1 : if deyiminin kullanımı
1: /* if deyiminin kullanımı */
2:
3: #include <stdio.h>
4:
5: int x, y;
6:
7: main()
8: {
9: /* test etmek için iki değer girin */
10:
11: printf("\nBir tamsayı değeri girin, x: ");
12: scanf("%d", &x);
13: printf("\nBir tamsayı değeri girin, y: ");
14: scanf("%d", &y);
15:
16: /* değerleri karşılaştır ve sonucu ekrena yaz */
17:
18: if (x == y)
19: printf("x, y ye eşit\n");
20:
21: if (x > y)
22: printf("x, y den büyük\n");
23:
24: if (x < y)
25: printf("x, y den küçük\n");
26:
27: return 0;
28: }
Bir tamsayı değeri girin, x: 100
Bir tamsayı değeri girin, y: 10
x, y den büyük
Bir tamsayı değeri girin, x: 10
Bir tamsayı değeri girin, y: 100
x, y den küçük
Bir tamsayı değeri girin, x: 10
Bir tamsayı değeri girin, y: 10
x, y ye eşit
5. satırında global olarak bildirilen x ve y tamsayı değişkenleri, 12 ve 14. satırlarda scanf fonksiyonu ile klavyeden okutulmuştur. 18, 21 ve 24. satırlarda kullanılan if deyimlerindeki koşul ifadeleri (Bkz Tablo 2.5) ile x, y sayıları karşılaştırılmış ve sonuç ekrana uygun bir biçimde gösterilmiştir.
if deyiminin else ile birlikte kullanımı şu şekildedir:
if(koşul)
{
...
deyimler;(küme1)
...
}
else
{
...
deyimler;(küme2)
...
}
Program 7.2 de if-else yapısı irdelenmiştir. Bu program dijital elektronikte kullanılan VEYA mantık kapısının bir similasyonudur. İki girişli VEYA kapısının davranışı; eğer girişlerin her ikisi de 0 ise çıkış 0, aksi takdirde sonuç 1 olacak şeklindedir. VEYA kapısının görevini veya_kapisi(x,y) fonksiyonu üslenmiştir. Burada x ve y giriş değişkenleridir. Fonksiyonun geri dönüş değeri iki tanedir. Çünkü kapının çıkışı, girişlerdeki dijital seviyelere bağlı olarak, iki durumludur, (1-0).
Program 7.2 : if-else yapısı
1: /* Dijital VEYA kapısı simulasyonu */
2:
3: #include <stdio.h>
4:
5: int veya_kapisi( int x,int y );
6:
7: int x,y,z;
8:
9: main()
10: {
11: x = 1; /* mantıksal 1 */
12: y = 0; /* mantıksal 0 */
13:
14: z = veya_kapisi(x,y); /* VEYA işlemi yapılıyor... */
15:
16: printf("%d ve %d nin VEYA işlemi : %d dir\n",x,y,z);
17:
18: return 0;
20: }
21:
22: int veya_kapisi(x,y)
23: {
24: if( x==0 && y==0 ) return 0;
25: else return 1;
26: }
11. ve 12. satırlarda tamsayı olarak tanımlanan x ve y değişkenlerine sırasıyla 1 ve 0 değerleri atanmıştır. z değişkenine ise veya_kapisi(x,y) fonksiyonun geri dönüş değeri atanmıştır. 24. satırda, Tablo 2.5 te verilen mantıksal VE operatörü ile iki farklı durum tek koşul yapısında birleştirilmiştir. Bu şekilde bütün mantık kapıları tanımlanırsa, bir çok dijital elektronik devryi tasarlamak mümkün olur. Bu yolla 8×1 Multiplexer oluşturabilirmisiniz?
Eğer program içinde kullanılacak koşulların sayısı 2 den çok ise şu yapı kullanılır:
if(koşul)
{
...
deyimler;(küme1)
...
}
else if
{
...
deyimler;(küme2)
...
}
else if
{
...
deyimler;(küme3)
...
}
.
.
.
else
{
...
deyimler;(kümeN)
...
}
Program 7.3 , ikinci dereceden bir polinomun köklerini hesaplamaktadır. Programda delta değerinin 0 dan küçük olması durumda köklerin karmaşık sayıya dönüşeceğide göz önüne alınmıştır. Bu program if, else if ve else yapısı göstermek için oldukça iyi bir örnektir.
Program 7.3 : if, else if, else yapısı
1: /* Diskirminant hesabı.
2: ** ax^2 + bx + c = 0 denkleminin,
3: ** karmaşık sayılı kökler dahil, çözümü.
4: */
5: #include <stdio.h>
6: #include <math.h> /* sqrt için */
7:
8: float a,b,c,delta,x1,x2,x,kok_delta;
9: main()
10: {
11: printf("a, b, c değerlerini girin:\n");
12: scanf("%f %f %f",&a,&b,&c);
13:
14: delta = b*b - 4*a*c;
15:
16: if( delta > 0.0 )
17: {
18: x1 = ( -b + sqrt(delta) )/( 2*a );
19: x2 = ( -b - sqrt(delta) )/( 2*a );
20:
21: printf("\nReel kökler :");
22: printf("\nx1 = %f ve x2 = %f",x1,x2);
23: }
24:
25: else if( delta < 0.0 )
26: {
27: kok_delta = ( sqrt(-delta) ) / (2*a);
28: x = -0.5*b/a;
29:
30: printf("\nKarmaşık kökler :");
31: printf("\nx1 = %f + %fi ve x2 = %f - %fi",x,kok_delta,x,kok_delta);
32: }
33:
34: else
35: {
36: x = -0.5*b/a;
37:
38: printf("\nKökler eşit :");
39: printf("\nx1 = x2 = %f",x);
40: }
41:
42: return 0;
43: }
a, b, c değerlerini girin:
2. 3.5 -4.89
Reel kökler :
x1 = 0.916822 ve x2 = -2.666822
a, b, c değerlerini girin:
4. 4. 1.
Kökler eşit :
x1 = x2 = -0.500000
a, b, c değerlerini girin:
1. 1. 1.
Karmaşık kökler :
x1 = -0.500000 + 0.866025i ve x2 = -0.500000 - 0.866025i
12. satırda denklemin reel katsayıları a, b ve c klavyeden okunmaktadır. Daha sonra delta değerinin üç farklı durumu için elde edilecek kökler hesaplanır. 25. satırdaki delta değerinin 0 dan küçük olduğu durum, reel olmayan kökleri hesaplamak için kullanılır.
switch – case Yapısı
Bu deyim bir değişkenin içeriğine bakarak, programın akışını bir çok seçenekten birine yönlendiren bir deyimdir. case(durum) deyiminden sonra değişkenin durumu yazılır ve akabinde gelen satır işlenir. Bütün durumların aksi söz konu olduğunda gerçekleştirilmesi istenen deyimler default deyiminden sonraki kısımda bildirilir. Genel yazım biçimi;
switch(degisken)
{
case sabit1:
...
deyimler;
...
case sabit2:
...
deyimler;
...
.
.
.
case sabitN :
...
deyimler;
...
default:
...
varsayılan_deyimler;
...
}
Program Program 7.4 te switch fonksiyonun basit bir kullanımı gösterilmiştir.
Program 7.4 : switch-case yapısının kullanımı
1: /* switch - case yapısının kullanımı */
2: #include <stdio.h>
3:
4: main()
5: {
6: char kr;
7:
8: printf("Lütfen bir karakter girin\n");
9: kr = getchar(); /* tek bir karakterin okunması */
10:
11: switch (kr){
12: case 'a':
13: printf("a harfine bastınız\n");
14: case 'b':
15: printf("b harfine bastınız\n");
16: default:
17: printf("a veya b ye basmadınız\n");
18: }
19: return 0;
20: }
Lütfen bir karakter girin
c
a veya b ye basmadınız
Lütfen bir karakter girin
a
a harfine bastınız
b harfine bastınız
a veya b ye basmadınız
Lütfen bir karakter girin
b
b harfine bastınız
a veya b ye basmadınız
Program 7.4 te klavyeden okunan tek bir karakter değişkenin içeriğine bakılıp uygun dallanmalar yaptırılmıştır. 9. satırda değişken getchar() fonksiyonu ile okutulmuştur. Eğer a veya b karakterlerinden biri girilirse, ekrana bu harflerin girildiğine dair mesaj yazılacak, aksi takdirde bu karakterin dışında bir karakterin giriş olarak kullanıldığı gösteren bir mesaj yazılacaktır. Örneğin c karakteri klavyeden girilmiş ise a veya b ye basmadınız gibi. Fakat a karakterleri girildiğinde ekrana her üç durumda yazdırılmaktadır. Bunun sebebi, case 'a': durumunda sırasıyla 13, 15 ve 17. satırların işleme konmasıdır. Bunu engellemek için 13. satırdan sonra programın başka bir yere yönlendirilmesi gerekir. Bu yönlendirme bir sonraki derste anlatılacak olan break deyimi ile yapılır. break bir işlemin sona erdirilmesi için kullanılan bir deyimdir. (Bkz Program 7.5 ).
Program 7.4 te case 'a': durumu için 13, 15 ve 17. satırlar da işleme konumuştu. Eğer klavyeden a değişkeni girip ekrana sadece a harfine bastınız iletisi yazdırılmak isteniyorsa, 13. satıra break deyimi ilave edilmelidir. break deyiminin kullanımı Program 7.5 te verilmiştir.
Program 7.5 : switch-case yapısı ve break kullanımı
1: /* switch - case yapısı ve break kullanımı */
2: #include <stdio.h>
3:
4: main()
5: {
6: char kr;
7:
8: printf("Lütfen bir karakter girin\n");
9: kr = getchar(); /* tek bir karakterin okunması */
10:
11: switch (kr){
12: case 'a':
13: printf("a harfine bastınız\n");break;
14: case 'b':
15: printf("b harfine bastınız\n");break;
16: default:
17: printf("a veya b ye basmadınız\n");break;
18: }
19: return 0;
20: }
Lütfen bir karakter girin
a
a harfine basırınız
Program 7.5 in Program 7.4 ten farkı 13, 15 ve 17. satırların sonuna break deyimlerinin konmuş olmasıdır. Derleyici bu deyim ile karşılaştığında, bulunduğu yapının içinden koşulsuz olarak ayrılır ve takip eden işleme başlar. Program 7.5 te break ile switch - case yapısı terkedilmiştir.
Program 7.6 switch-case yapısın fonksiyonlarla kullanımı ile ilgili önemli bir örnektir. Programda, menü puts fonksiyonları kullanılarak ekrana yazdırılmış ve arkasından bir karakter okunarak, menüden hangisinin seçildiği kr değişkenine aktarılmıştır; switch-case yapısı ile uygun olan fonksiyonlara dallandırılmıştır.
Program 7.6 : switch-case yapısının fonksiyonlarla kullanımı
1: /* switch-case yapısının fonksiyonlarla kullanımı */
2:
3: #include <stdio.h>
4:
5: char menu(void);
6: int topla( int a,int b );
7: int carp( int a,int b );
8:
9: main()
10: {
11: char oku;
12: int x,y,sonuc;
13:
14: x = 10; /* x e bir değer atanıyor */
15: y = 20; /* y e bir değer atanıyor */
15:
16: oku = menu();
17: switch( oku )
18: {
19: case '1':
20: sonuc = topla(x,y);
21: printf("Toplamları : %d",sonuc);
22: break;
23: case '2':
24: sonuc = carp(x,y);
25: printf("Çarpımları : %d",sonuc);
26: break;
27: case '3':
28: printf("Program sonu...");
29: exit();
30: }
31: }
32:
33: /* menu fonksiyonu */
34: char menu(void)
35: {
36: char kr;
37: puts("[1]. Toplama");
38: puts("[2]. Carpma");
39: puts("[3]. Çıkış");
40: puts("Seçiminiz ?");
41:
42: kr = getchar();
43: return kr;
44: }
45:
46: /* topla fonksiyonu */
47: int topla( int a,int b )
48: {
49: return (a+b);
50: }
51:
52: /* carp fonksiyonu */
53: int carp( int a,int b )
54: {
55: return (a*b);
56: }
[1]. Toplama
[2]. Çarpma
[3]. Çıkış
Seçiminiz ?
1
Toplamları : 30
Program 7.6 da 14. ve 15. satırlarda tanımlanan x ve y tamsayılarına başlangıç değerleri atanmıştır (x ve y scanf fonksiyonu ile klavyeden okutulabilirdi). oku karakter değişkenine menu fonksiyonunun geri dönüş değeri (kr) atanmış ve switch fonksiyonuna 17. satırda parametre olarak aktarılmıştır. 19. satırdaki durum gerçekleştiğinde x ve y sayılarının toplamları topla fonksiyonu ile sonuc değişkenine aktarılmıştır. Bu değişkenin içeriği 21. satırda ekrana yazılmıştır. 22. satırdaki break deyimi ile switch-case yapısı terkedilmiştir. Yani switch deyiminden sonraki satır (main fonksiyonuna ait } işareti) işleme konuştur. Program sonlanmıştır. Aynı şeyler 23. satırdaki durum içinde geçerlidir. 27. satırdaki durum gerçekleştiğinde ekrana Program sonu... ifadesi yazılır ve exit() fonksiyonu ile şartsız olarak program sonlandırılır.
? Karşılaştırma Operatörü
C dilinde if-else karşılaştırma deyiminin yaptığı işi sınırlı olarak yapan bir operatördür. Genel yazım biçimi:
(koşul) ? deyim1 : deyim2;
İlk önce koşul sınanır. Eğer koşul olumluysa (1 ise) deyim1 aksi takdirde deyim2 değerlendirilir. deyim1 ve deyim2 de atama işlemi yapılamaz. Ancak koşul deyiminde atama işlemi yapılabilir. deyim1 ve deyim2 yerine fonksiyon da kullanılabilir. Aşağıda bu deyimin kullanımına ait örnekler verilmiştir.
x = ( a > b ) ? a : b;
Yukarıdaki ifadede koşul a’nın b’den büyük olmasıdır. Eğer olumluysa x adlı değişkene a, değilse b değeri atanır. Bu şekilde kullanım if-else yapısı ile kurulmak istenirse:
if( a > b ) x = a;
else x = b;
şeklinde olacaktır.
Program 7.7 : ? – if-else yapısının kullanımı
1: /* ? ve if-else yapısının kullanımı */
2: #include <stdio.h>
3:
4: main()
5: {
6: int x,y,z;
7:
8: printf("x : ");scanf("%d",&x); /* x okunuyor */
9: printf("y : ");scanf("%d",&y); /* y okunuyor */
10:
11: if( x ) /* x 0 dan farklı mı? */
12: z = ( y > x ) ? x*y : x+y; /* y>x ise z=x*y, değilse z=x/y */
13: else
14: z = 0;
15:
16: printf("z = %d",z);
17:
18: return 0;
19: }
x : 0
y : 6
z = 0
x : 5
y : 9
z = 45
x : 8
y : 2
z = 10
Program 7.7 nin 6. satırda tamsayı olarak tanımlanan x,y,z değişkenleri 8. ve 9. satırlarda okutulmuştur. 11. satırdaki if deyimindeki koşul biraz farklıdır. Genel olarak koşul bu şekilde bildirilirse, koşulun 0 dan farklı olup olmadığı sınanır.
Yani if( x ) ile if( x!=0 ) aynı anlamdadır. Bu kullanım çok yagındır. Eğer x 0 dan farklı ise koşul olumlu olarak değerlendirilecektir. 12. satırda ? ile bir sınama yapılmaktadır. Eğer y, x den büyük ise z değişkenine x*y, aksi takdirde x+y değeri atanmaktadır. Eğer x=0 ise 14. satırda z değişkenine 0 değeri atanmaktadır. if ve else deyimlerinden sonra { ve } karakterlerinin kullanılmadığına dikkat edin. Eğer bu şekilde kullanılırsa, bu deyimlerden sonra gelen ilk satır işleme konur. 11. satırdaki koşul doğru ise 12. satır, aksi takdirde 14. satır işleme konur.
Ders8: Döngüler
Bu tip deyimler bir kümenin belli bir koşul altında yinelenmesi için kullanılır. while, do...while ve for olmak üzere üç tip döngü deyimi vardır. C de diğer programlama dillerinde olduğu gibi, bu deyimlerle istenildiği kadar iç-içe döngü yapısı kullanılabilir.
while
Tekrarlama deyimidir. Bir küme ya da deyim while kullanılarak bir çok kez yinelenebilir. Yinelenmesi için koşul sınaması çevrim başında yapılır. Koşul olumlu olduğu sürece çevrim yinelenir. İki veya daha çok koşul mantıksal operatörler birleştirilerek verilebilir. Bu deyimin kullanımı Program 8.1 de gösterilmiştir. Genel yazım biçimi:
while(koşul)
{
...
döngüdeki deyimler; [küme]
...
}
Program 8.1 : while döngüsünün kullanımı
1: /* while kullanımı */
2: #include <stdio.h>
3:
4: main()
5: {
6:
7: int x=0;
8:
9: while(x <= 10)
10: printf("%d\n",x++);
11:
12: return 0;
14: }
0
1
2
3
4
5
6
7
8
9
10
Program 8.1 in amacı, 0-10 arasındaki sayıları ekrana yazdırmaktır. 9. satırdaki while ifadesinden sonra { işareti kullanılmamıştır. Bu durumda, sadece takip eden satır (10. satır) döngü nün içine dahil edilir.
do … while
Bu deyim while dan farkı, koşulun döngü sonunda sınanmasıdır. Yani koşul sınanmadan çevrime girilir ve döngü kümesi en az bir kez yürütülür. Koşul olumsuz ise döngüden sonraki satıra geçilir. Bu deyimin kullanımı Program 8.2 de gösterilmiştir. Genel yazım biçimi:
do
{
...
döngüdeki deyimler;
...
}while(koşul);
Program 8.2 : do-while döngüsünün kullanımı
1: /* do-while kullanımı */
2: #include <stdio.h>
3:
4: main()
5: {
6: int sayi;
7:
8: do
9: {
10: printf("Bir sayı girin : ");
11: scanf("%d",&sayi);
12: printf("Bu sayının iki katı : %d\n",2*sayi);
13:
14: }while( sayi>0 ); /* koşul */
15:
16: puts("Çevrim sona erdi.");
17:
18: return 0;
19: }
Bir sayı girin : 2
Bu sayının iki katı : 4
Bir sayı girin : 5
Bu sayının iki katı : 10
Bir sayı girin : 9
Bu sayının iki katı : 18
Bir sayı girin : 0
Bu sayının iki katı : 0
Çevrim sona erdi.
14. satırdaki koşul olumlu olduğu sürece (klavyeden girilen sayi > 0 olduğu sürece), klavyeden yeni bir değer 11. satırda okunur. Aksi takdirde sayi <=0 ise çevrimin sona erdiğine dair mesaj 16. satırdaki puts fonksiyonu ile verilir.
for
Diğer döngü deyimleri gibi bir öbeği bir çok kez tekrarlamakta kullanılır. Koşul sınaması while da olduğu gibi döngüye girmeden yapılır. Bu döngü deyimin içinde diğerlerinden farklı olarak başlangıç değeri ve döngü sayacına sahip olmasıdır. Bu deyimin kullanımı Program 8.3 de gösterilmiştir Genel yazım biçimi:
for( başlangıç ; koşul ; artım )
{
...
döngüdeki deyimler;
...
}
Program 8.3 : for döngüsü ile faktoriyel hesabı
1: /* for döngüsünün kullanımı */
2: #include <stdio.h>
3:
4: long faktoriyel(int n);
5:
6: main()
7: {
8: int x;
9:
10: printf("\nFaktoriyeli hesaplanacak sayı girin : ");
11: scanf("%d",&x);
12:
13: if(x<0)
14: printf("Sayı 0 dan hüçük; faktoriyeli hesaplanamaz.");
15: else
16: printf("faktoriyeli : %ld dir",faktoriyel(x));
17:
18: return 0;
19: }
20:
21: /* n! değerini hesaplar */
22: long faktoriyel(int n)
23: {
24: long i,fact=1;
25:
26: /* bu döngu ile fact = n! = 1*2*3*...*n değeri hesaplanır */
27: for(i=1;i<=n;i++)
28: {
29: fact *= i;
30: }
31:
32: return fact; /* geri dönüş değeri long tipinde */
33: }
Faktoriyeli hesaplanacak sayı girin : 3
faktoriyeli : 6 dir
Faktoriyeli hesaplanacak sayı girin : 10
faktoriyeli : 3628800 dir
Faktoriyeli hesaplanacak sayı girin : 0
faktoriyeli : 1 dir
Faktoriyeli hesaplanacak sayı girin : -4
Sayı 0 dan hüçük; faktoriyeli hesaplanamaz.
11. satırda okunan x tamsayısının faktoriyeli 16. satırda ekrana yazdırılır. Eğer x < 0 ise 14. satırdaki mesaj ekrana çıkar. faktoriyel() fonksiyonu kendisine parametre olarak gelen değişkenin, facktoriyelini 27. satırdaki for döngüsünü kullanarak hesaplar. Fonksiyonun geri dönüş değeri long tipinde tanımlanmıştır. Çünkü faktoriyel değeri 2 bayt tan büyük bir tamsayı olabilir.
Bir programda birden çok döngü yapısı iç içe kullanılabilir. İç içe döngülerin kullanımı Program 8.4 de gösterilmiştir.
Program 8.4 : iç-içe for döngülerinin kullanılması
1: /* iç-içe for döngüleri */
2:
3: #include <stdio.h>
4:
5: void kutu_ciz( int, int);
6:
7: main()
8: {
9: kutu_ciz( 8, 35 );
10:
11: return 0;
12: }
13:
14: void kutu_ciz( int satir, int sutun )
15: {
16: int sut;
17: for ( ; satir > 0; satir--)
18: {
19: for (sut = sutun; sut > 0; sut--)
20: printf("X");
21:
22: printf("\n");
23: }
24: }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Program 8.4 de sadece 20. satır defalarca işleme konur. Program çalıştırıldığında 8*35=280 adet X, ekrana bastırılır. 5. satırda kutu_ciz() fonksiyonunun prototipi tanımlanmıştır. Bu fonksiyonun parametreleri (satir, sutun) ile çizilecek olan kutunun ebatları belirlenir. 8 satır ve 35 sütun için main() fonsiyonundan 9. satırda çağırılmıştır. 17. satırda ilk for döngüsü çevrime başlar. Fakat bir başalangıç değeri belirtilmemiştir, çünkü bu değer(satir) fonksiyondan buraya aktarılır. 19. satırda ikinci for döngüsü çevrime başlar ve 20. satır bu döngünün içinde değerlendirilir. Yani satir’in herbir değeri için, bütün sutun değerleri tekrarlanır. İkinci döngü tamamlandığında 22. satırda alt satıra geçilir ve birinci çevrim yeni bir değer için yinelenir.
printf() fonksiyonu ile desimal(taban-10) syılarıların nasıl yazdırılacağı bundan önceki kısımlarda gösterilmişti. Program 8.5 de Hexadesimal(taban-16) sayıların bu fonksiyon kullanılarak yazdırılması gösterilmiştir.
Program 8.5 : Desimal ve heksadecimal sayıların bastırılması
1: /* 0-15 desimal sayıların, hexadesimal sayı sistemine çevrilmesi.
2: ** %d -> desimal , 10 tabanındaki sayı
3: ** %x -> hexadesimal (küçük_harf), 16 tabanındaki sayı
4: ** %X -> hexadesimal (büyük_harf), 16 tabanındaki sayı
5: */
6: #include <stdio.h>
7:
8:: main()
9: {
10: int i;
11:
12: printf("Hex(büyük harf) Hex(küçük harf) Desimal\n");
13: for (i=0; i<16; i++){
14: printf("%X %x %d\n", i, i, i);
15: }
16: return 0;
17: }
Hex(büyük harf) Hex(küçük harf) Desimal
0 0 0
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
6 6 6
7 7 7
8 8 8
9 9 9
A a 10
B b 11
C c 12
D d 13
E e 14
F f 15
Sonsuz Döngü
Bir döngü işlemini sonsuz kere tekrarlarsa bu döngü sonzuz döngü olarak adlandırılır. Böyle bir döngü için, koşul çok önemlidir. Örneğin while döngüsü için:
...
while(1)
{
printf("Sonsuz döngü içindeyim...\n");
}
...
yada
...
while(7>3)
{
printf("Sonsuz döngü içindeyim...\n");
}
...
Her iki durumda da çevrimler, sonsuz döngü durumundadır. Çünkü while(1) ve while(7>3) deki ifadelerde, koşul hep olumludur. Bu, durumda çevrim sonsuz döngüye girer.
for döngüsünde, başlangıç, koşul ve artım parametrelerinden herhangi birini kullanmak isteğe bağlıdır. Her hangi biri verilmediğinde döngünün nasıl davranacağı iyi yorumlanmalıdır. Örneğin for döngüsünün hiçbir parametresi verilmezse, döngü sonsuz çevrime girer. Yani:
for(;;)
printf("Sonsuz döngü içindeyim...\n");
gibi.
Break
Bir C programında, bir işlem gerçekleştirilirken, işlemin sona erdirilmesi bu deyim ile yapılır. Örneğin, döngü deyimleri içindekiler yürütülürken, çevrimin, koşuldan bağımsız kesin olarak sonlanması gerektiğinde bu deyim kullanılır. Örneğin:
...
do{
scanf("%d",&x);
if(x==0) break;
printf("%d",x);
}while(1);
...
yukarıdaki program parçasında, do … while döngüsünün koşu hep olumludur. Bu durumda döngü sonnsuzdur. Fakat döngü içinde if deyimindeki koşul gerçekleşirse, dögü koşuluna bakılmaksızın döngü terkedilir. bu işlemi sağlayan break deyimidir.
Continue
Bir döngü içerisinde continue deyimi ile karşılaşılırsa, ondan sonra gelen deyimler atlanır. Yani döngü, bir sonraki çevrime girer. Örneğin:
...
for(x=-50;i<=50;x++){
if(x<0) continue; /* x<0 ise alttaki satırı atla */
printf("%f",sqrt(x));
}
...
Program parçasının çıktısı:
0.000000
1.000000
1.414213
1.732050
.
.
.
7.071067
Ders9: Diziler
Dizi bir kümedir. Aynı tipte verilere tek bir isimle erişmek için kullanılır. Bir dizinin bütün elemanları bellekte peşpeşe saklanır.
Dizi Tipi Genel bildirimi Örnek
Tek boyutlu diziler tip ad[eleman_sayısı] int veri[10];
İki boyutlu diziler tip ad[satir_say][sutun_say] float mat[5][4];
Çok boyutlu diziler tip ad[boyut_1][boyut_2][boyut_3]...[ boyut_n] double x[2][4][2];
Aşağıda dizilerin kullanımı il ilgili 10 adet örnek sunulmuştur. Örnekleri dikkatle inceleyin.
Program 9.1 : Dizi elamanlarına erişim.
1: main(){
2: int i,x[5];
3: x[0]=5;
4: x[1]=25;
5: x[2]=-40;
6: for(i=0;i<3;i++)
7: printf("%d\n",x[i]);
8: }
Program 9.2 : Dizilere başlangıç değeri verme
1: main(){
2: int i,x[5]={5,0,6};
3: int y[]={1,5,9};
4: puts("X Y");
5: for(i=0;i<3;i++)
6: printf("%d %d\n",x[i],y[i]);
7: }
Program 9.3 : Karakter dizisi (String)
1: main(){
2: int i;
3: char ad[][15] ={"Ahmet",
4: "Mehmet","Can"};
5: int kilo[]={70,60,52};
6: float boy[] ={1.70,1.85,1.45};
7: puts("\nISIM\tKILO\tBOY");
8: for(i=0;i<3;i++)
9: printf("%s\t%d\t%1.3f\n",ad[i],kilo[i],boy[i]);
10: }
Program 9.4 : Beş sayının ortalama hesabı
1: main(){
2: int i,x[5],toplam =0;
3: float ort;
4: for(i=0;i<5;i++){
5: printf("%d. eleman : ",i+1);
6: scanf("%d",&x[i]);
7: toplam += x[i];
8: }
9: ort = (float) toplam/5;
10: printf("ortalamalari : %f",ort);
11: }
Program 9.5 : Dizilerin fonksiyonla kullanma
1: void yaz(int x[]);
2: main(){
3: int x[10];
4: yaz(x);
5: }
6:
7: void yaz(int x[]){
8: int i;
9: for(i=0;i<10;i++)
10: printf("%d\n",x[i]);
11: }
12:
Program 9.6 : Dizinin bellekte kapladığı alan
1: main(){
2: char dizi1[10];
3: int dizi2[10];
4: float dizi3[10];
5: double dizi4[10];
6: printf( "%d\n",sizeof(dizi1) );
7: printf( "%d\n",sizeof(dizi2) );
8: printf( "%d\n",sizeof(dizi3) );
9: printf( "%d\n",sizeof(dizi4) );
10: }
Program 9.7 : On elemanlı bir diziye ait elamanların sırlanaması
1: main(){
2: int x[10],i,j,gec;
3: puts("5 tane sayi gir:");
4: for(i=0;i<5;i++)
5: {
6: printf("%d.sayi : ",i);
7: scanf("%d",&x[i]);
8: }
10:
11: for(i=0;i<4;i++)
12: {
13: for(j=i+1;j<5;j++)
14: {
15: if( x[j]<x[i] )
16: {
17: gec = x[i];
18: x[i] = x[j];
19: x[j] = gec;
20: }
21: }
22: }
23:
24:
25: for(i=0;i<5;i++)
26: printf("\n%d",x[i]);
27:
28: }
Program 9.8 : İki matrisin toplamı
1: main(){
2: int i,j,A[3][3],B[3][3],C[3][3];
3: puts("iki matrisin toplami:");
4: puts("A matrisinin elemanlarini girin:");
5: for(i=0;i<3;i++){
6: for(j=0;j<3;j++){
7: printf("A(%d,%d)=",i+1,j+1);
8: scanf("%d",&A[i][j]);
9: }
10: }
11:
12: puts("B matrisinin elemanlarini girin:");
13: for(i=0;i<3;i++){
14: for(j=0;j<3;j++){
15: printf("B(%d,%d)=",i+1,j+1);
16: scanf("%d",&B[i][j]);
17: }
18: }
19:
20: puts("A+B matrisinin elemanlari:");
21: for(i=0;i<3;i++){
22: for(j=0;j<3;j++){
23: C[i][j] = A[i][j] + B[i][j];
24: printf("C(%d,%d)=%d\n",i+1,j+1,C[i][j]);
25: }
26: }
27:
28: }
Program 9.9 : Elemanları (0,100) arsında olan rasgele dizi
1: #include <time.h>
2: #include <stdlib.h>
3: main(){
4: int i,x[10];
5: randomize(); /* rasgele sayı üretecini başlatır */
6: for(i=0;i<10;i++)
7: {
8: x[i]=random(100); /* 0-100 arasında rasgele sayı seçiliyor */
9: printf("%d\n",x[i]);
10: }
11: }
Program 9.10 : Dizi elemanlarının bellekteki sıralanış adresleri
1: main(){
2: int i,x[10];
3: puts("x dizisinin elemanlarının sıralanışı");
4: for(i=0;i<10;i++)
5: printf("%p\n",&x[i]);
6: }
Ders10: Pointer Kavramı (işaretçiler)
Pointer Nedir?
Bilgisayarın ana belleği (RAM) sıralı kaydetme bölgelerinden(gözlerinden) oluşmuştur. Her göze bir adres atanmıştır. Bu adreslerin değerleri 0 ila RAMe bağlı olarak MAX arasında değerler alabilir.
Programlama dillerinde bir değişken tanımlandığında, o değişkene tipine bağlı olarak RAMden bir bölge ayrılır. Örneğin rate adlı bir değişken tanımladığımızı varsayalım. Bu değişken bellekte Şekil 10.1 deki bir yere yazılır.
Şekil 10.1 : rate adlı değişkenin bellekteki adresi
Pointer(işaretçi), bellek alanındaki bir gözün adresinin saklandığı değişkendir. Pointerlara, veriler(yani değişkenlerin içeriği) değil de, o verilerin bellekte saklı olduğu bellek gözlerinin başlangıç adresleri atanır. Bir pointer, diğer değişkenler gibi, sayısal bir değişkendir. Bu sebeple kullanılmadan önde program içinde bildirilmelidir. Pointer değişkenler şöyle tanımlanır:
tipadı *ptradı;
Burada tipadı herhangi bir C tip adı olabilir. Değişkenin önüne konan * karakteri indirection operatörü olarak adlandırılır ve tipadı ile bildirilen ptradı değişkenini işaret eder. Örneğin:
char *kr1; /* karakter için */
int *x; /* tamsayı için */
float *deger,sonuc; /* deger pointer tipinde sonuc sıradan bir reel değişkenler */
Yukarıda bildirilen pointer değişkenlerden; kr bir karakterin, x bir tamsayının ve deger bir gerçel sayının bellekte saklı olduğu yerlerin adreslerini tutar. Fakat sonuc adlı float değişken sıradan bir gerçel sayıdır.
Bir pointera, bir değişkenin adresini atamak için & adres-operatörü kullanılır. Bu operatör bir değişkenin önüne konursa, o değişkenin içeriği ile değilde adresi ile ilgileniliyor anlamına gelir. Örneğin karakter tipindeki rate adlı bir değişken ve p_rate ise pointer tipinde, rate değişkenini işaret eden bir değişken olsun. Bu durum Şekil 10.2 de gösterilmektedir:
Şekil 10.2 : rate adlı sıradan bir değişken ve onu işaret eden p_rate adlı pionter değişkeninin bellekteki dizilimi
Derleyicide şöyle ifade edilir:
char rate;
char *p_rate;
...
p_rate = &rate;
Yani p_rate pointeri rate değişkeninin saklandığı adresi işaret etmektedir. Program Program 10.1 pointer kavramını anlamak için oldukça önemli bir örnektir.
Program 10.1 : ilk Pointer programı
/*ptr01.c*/
1: main()
2: {
3: int x, *isaret;
4:
5: x = 888;
6: işaret = &x;
7:
8: printf("x in degeri = %d\n",x);
9: printf("x in adresi = %x\n",isaret);
10: printf("x in değeri = %d\n",*isaret);
11: printf("x in adresi = %x\n",&x);
12: }
x in degeri = 888
x in adresi = ffde
x in degeri = 888
x in adresi = ffde
Özetle, eğer ptr adında bir pointera, deg adlı bir değişkene sahipseniz ve ptr = & deg; şeklinde bir atama yapmışsanız:
- *ptr ve deg, deg adlı değişkenin içeriği ile ilgilidir.
- ptr ve & deg, deg adlı değişkenin adresi ile ilgilidir.
- * indirection opreratörü olarak adlandırılır.
- & adres operatörüdür.
Dinamik DizilerBir dizi daha önce anlatıldığı gibi, programın başında kaç elemanlı olduğu belirtilerek bildirilirse, derleyici o dizi için gerekli bellek alanını program sonlandırılıncaya kadar saklı tutar ve o alan başka amaçlar için kullanılmaz. Dizilerde dinamik çalışma, programın çaklıştırılması sırasında gerekli bellek alanının işletim sisteminden istenmesi ve işi bittiğinde bu alanın geri verilmesidir. Bu amaçla standart kütüphanede malloc(), calloc(), realloc() ve free() fonksiyonları vardır. Bu şekilde dizileri kullanmak için:
...
tip *ptr;
...
ptr = malloc(50); /* herbiri 8 bit olan 50 elemanlık yer isteniyor */
.
. /* kullanılıyor */
.
free(ptr); /* geri veiliyor */
...
Program 10.2 ile basit olarak dinamik bir dizinin kullanımı gösterilmiştir.
Program 10.2 : Dinamik bir dizinin kullanımı
1: #include <stdio.h>
2: #include <stdlib.h>
3:
4: main(){
5: int *x,i,N,toplam=0;
6: float ortalama;
7:
8: printf("Eleman sayısı ");
9: scanf("%d",&N);
10:
11: x = (int *) malloc(N*sizeof(int)); /* N tane int gözü
12: isteniyor (Nx2 byte) */
13:
14: puts("Elemanları girin:");
15: for(i=0;i<N;i++){
16: printf("%d.eleman = ",i+1);
17: scanf("%d",&x[i]); /* x[i] ile *(x+i) aynı anlamda !... */
18: toplam += x[i];
19: }
20:
21: free(x); /* ayrılan yer boşaltılıyor... */
22:
23: ortalama = (float) toplam/N;
24:
25: printf("Bu %d sayının ortlaması %f dir\n",N,ortalama);
26:
27: }
5. satırda x değişkeni pointer tipinde tanımlanmıştır. N sayısı 9. satırda klavyeden okutlmuştur. 11. satırda x pointeri için malloc() fonksiyonu ile bellekten N tane int tipinde bellek gözü istenmiştir. malloc() fonksiyonu bellekten istenen yerin başlangıç adresini x değişkenine aktarır. N tane yer istendiğine göre, x, artık N elemanlı bir dizidir. Buna göre x[0] ayrılan bölgenin ilk adresindeki değişkeni temsil eder. Benzer olarak diğer elemanlar da, bellekte peşpeşe sıralanır. Bu yüzden, x 17. satırda bir dizi gibi okutulmuştur. Eğer x bir dizi gibi ifade edilmek istenmiyorsa i. eleman x[i], *(x+i) şeklinde de kullanılabilir. x in elemanların toplamı toplam adlı değişkene 18. satırda aktarılmaktadır. 21. satırda x için ayrılan bellek alanı free fonksiyonu ile serbest bırakılmıştır.
Program 10.2 sıradan bellek kullanımından oldukça farklıdır. Eğer x bir pointer değil de, sıradan bir dizi gibi bildirilseydi, programın başında x in eleman sayısı mutlaka belirtilmesi gerekirdi. Bu bize, pointer kullanımın ne kadar önemli olduğunu gösterir.
Pointer Tipindeki FonksiyonlarBir fonksiyon tanımlanırken, parametreleri pointer olabileceği gibi, tipi de pointer olabilir. Bu, o fonksiyonun kendisini çağırana bir adres göndereceği anlamına gelir. Bu tip uygulamalar özellikle string uygulamalarında sık kullanılır.
Program 10.3 de, geri dönüş değeri int tipinde olan bir pointer fonksiyon örneği verilmiştir. Bu fonksiyon iki sayının toplamının saklandığı toplam adlı değişkenin adresini, çağırılan yere gönderir.
Program 10.4 : Geri dönüş değeri, pointer olan bir fonksiyon
1: #include <stdio.h>
2:
3: int *topla(int,int);
4:
5: main(){
6: int a,b;
7: int *p;
8:
9: a = 2;
10: b = 4;
11:
12: p = topla(a,b);
13:
14: printf("Toplam : %d (adresi %p)\n",*p,p);
15: }
16:
17: int *topla(int x,int y)
18: {
19: int *ptr,toplam;
20:
21: toplam = x+y;
22: ptr = &toplam;
23:
24: return ptr;
25: }
Toplamları 6 (adresi 0xbbb7fc4)
Ders11: Stringler (Katarlar)
Giriş
Katar bir char tipinde bildirilen karakter dizisidir. Stringler, içeriği harfler, rakamlar, veya bazı semboller olan text bilgilerini tutmak(saklamak) için kullanılır. C dilinde string bildirimi için bir tip deyimi yoktur. Bu yüzden, bir stringe bir dizi gözüyle bakılır. Genel olarak bir string'in bildirimi:
char string_adı[eleman_sayısı];
şeklindedir. Örneğin 10 elemanlı bir isim bilgisi OgrenciAdi adlı bir string ile tutulmak istenirse:
char OgrenciAdi[10];
şeklinde programın başında bildirilmelidir.
Stringlere Başlangıç Değeri AtamaDiğer dizi bildirimlerinde olduğu gibi, karakter dizilerine başlangıç değeri verilebilir. Örneğin aşağıda verilen iki bildirim aynı anlamdadır:
char ktr[5]={'a','h','m','e','t',''};
char ktr[5]="ahmet";
birinci satırdaki bildirimde '' (NULL) sembolü karakter dizisinin sonlandığını gösterir. Eğer bir karakter dizisinin kaç elemandan oluşacağı belirtilmezse, başlangıçta bildirilen karakter sayısı kaç tane ise dizinin eleman sayı o kadar olduğu varsayılır.
char ktr[]="ahmet"; /* 5 elemanlı */
Stringler bazen bir pointer ile gösterilebilir.
char *ktr="ahmet";
Her dört örnekteki ktr stringinin eleman sayısı 5 tir.
String Üzerinde İşlem Yapan Standart G/Ç Fonksiyonlarıprintf(); ve scanf();
Bu fonksiyonlar diğer tiplerde olduğu gibi formatlı okuma/yazma amaçlı kullanılır. String formatı %s dir. Aşağıda verilen programları iyice inceleyin. Bu öenekler basitten karmaşığa doğru sunulmuştur. Gerekli açıklamalar program üzerinde gösterilmiştir.
Program 11.1 : Bir stringin ekrana yazılması
1: main()
2: {
3: char ktr[20]="Ahmet";
4: printf("%s",ktr);
5: }
Program 11.2 : iki stringin ekrana yazılması
1: main(){
2: char *ileti = "Selam dostum";
3: char isim[] ={'A','l','i',''};
4: printf("%s %s",ileti,isim);
5: }
Program 11.3 : klavyeden okunan stringin ekrana yazılması
1: main(){
2: char ktr[20];
3: printf("\nBir seyler yazin:");
4: scanf("%s",ktr); printf("%s yazdiniz.",ktr);
5: }
Program 11.4 : Bir stringin formatlı yazılması
1: main(){
2: char ad[5]="ahmet";
3: printf("%10s",ad);
4: }
Program 11.5 : Bir stringin printf ile yazılması
1: main(){
2: char *isim = "ahmet";
3: printf(isim);
4: }
Program 11.6 : bir stringin içindeki m karakterinin sayısını öğrenme
1: main(){
2: char ktr[20];
3: int i,sayac = 0;
4: printf("\nBir seyler yazin :");
5: scanf("%s",ktr);
6: for(i=0;ktr[i];i++)
7: if( ktr[i]=='m' ) sayac++;
8: printf("yazilanlarin icinde %d tane m harfi var",sayac);
9: }
puts(); ve gets();
Bu fonksiyonlar sadece stringler üzerinde işlem yapar. printf(); ve scanf(); fonksiyonları gibi klavyeden veri okuma/ekrana bilgi yazma amaçlı kullanılır.
Program 11.7 : puts ve gets fonksiyonları
1: main(){
2: char ktr[20];
3: printf("\nBir seyler yazin: ");
4: gets(ktr); puts(ktr);
5: }
Program 11.8 : bir siringin ilk karkareini yazdırma
1: main(){
2: char ad[10],soyad[20];
3: printf("ADI : ");
4: gets(ad);
5: printf("SOYADI : ");
6: gets(soyad);
7: printf("%c. %s",ad[0],soyad);
8: }
Program 11.9 : puts,gets ve malloc fonksiyonları
1: main(){
2: char *ktr;
3: ktr = (char *) malloc(20);
4: printf("\nBir seyler yazin: ");
5: gets(ktr);
6: puts(ktr);
7: }
Program 11.10 : bir stringin kaç karkaterden oluştuğunu hesaplar
1: main(){
2: char ktr[200];
3: int i;
4: puts("Bir seyler yazin");
5: gets(ktr);
6: for(i=0;ktr[i];i++); /* kosul ktr[i]!='' anlamindadir*/
7: printf("yazilan %d harfdir",i);
8: }
Bazı String FonksiyonlarıBu fonksiyonlar standart C dilinde iki stringi karşılaştırmak, bir stringin içeriğini diğerine kopyalamak ve stringin uzunluğunu bulmak vb işlemler için tanımlı fonksiyonlardır. Bu ve benzeri fonksiyonlar kullanılırken string.h kütüphanesi programın başına ilave edilmelidir. Burada sadece bunlardan bir kaçı Tablo 11.1 de verilmiştir.
str, str1 ve str2 birer string ve kr bir karakter olmak üzere:
Tablo 11.1 : string.h kütüphanesine ait, bazı string fonksiyonları
| strcmp( str1,str2 ); | str1 ve str2 yi karşlaştırır |
| strcpy( str1,str2 ); | str2 yi str1 e kopyalar |
| strcat( str1,str2 ); | str2 yi str1 e ekler |
| strrev( str ); | str yi ters çevirir |
| strlen( str ); | str nin kaç karakterden oluştuğunu hesaplar |
| strchr( str,kr ); | kr ile verilen karakterin str içindeki soldan itibaren yerini verir |
Program 11.11 : İki stringin karşılaştırılması
1: #include <string.h>
2: main(){
3: char ktr1[10],ktr2[10];
4: int sonuc;
5: printf("1. katar:");gets(ktr1);
6: printf("2. katar:");gets(ktr2);
7: sonuc = strcmp(ktr1,ktr2);
8: if(sonuc>0) puts("2. 1.den büyük");
9: else if(sonuc<0) puts("2. 1.den küçük");
10: else puts("2. 1. eşit");
11: }
Program 11.12 : basit bir şifre programı
1: #include <string.h>
2: main(){
3: char sifre[20];
4: printf("SIFRE : ");
5: scanf("%s",sifre);
6: if( strcmp(sifre,"deneme")==0 )
7: puts("sifre dogru girildi");
8: else
9: puts("sifre yanlis!");
10: }
Program 11.13 : Bir stringi diğerine kopyalama
1: #include <string.h>
2: main(){
2: char *str1="ahmet", str2[10];
4: /* once */
5: puts(str2);
6: strcpy(str2,str1);
7: /* sonra */
8: puts(str2);
9: }
Program 11.14 : bir stringi diğerine ekleme
1: #include <string.h>
2: main(){
3: char *a="ahmet ";
4: char *b="bingul";
5: strcat(a,b);
6: printf(a);
7: }
Program 11.15 : strinin uzunluğunu hesaplar
1: #include <string.h>
2: main(){
3: char ktr[100];
4: puts("Birseyler yazin:");
5: gets(ktr);
6: printf("%s %d karakterden oluşmuştur.",ktr,strlen(ktr));
7: }
Ders12: Disk Dosyaları (Dosyalama)
Çoğu programda, bazı verilerin disk üzerinde saklanmasına gerek duyulur. C programlama dilinde, disk dosyasına erişme (okuma ve yazma için) iki farklı yöntemle yapılır. Bunlar üst düzey ve alt düzey olarak adlandırılır. Bunlardan üst düzey G/Ç yöntemi ANSI tarafından desteklenmektedir. Alt düzey G/Ç ANSI tarafından desteklenmemektedir. Bu yüzden, burada Üst düzey G/Ç konu edilecektir.
Dosya Açma ve Kapama
Bir dosyaya okuma/yazma yapmak için onun açılması gerekir. Bunun için fopen() fonksiyonu kullanılır. Açılan dosya fclose() ile tekrar kapatılmalıdır. Genel olarak:
...
FILE *dosya;
...
dosya = fopen(dosya_adı,mod);
...
fclose(dosya);
...
mod ile açılacak olan dosyanın ne amaçla açılacağı belirlenir. Bunlar:
r (read only) yalnızca okuma için açar.
w (write only) yalnızca yazma için açar.
a (append) ekleme yapmak için açar.
r+ Okuma/yazma için açar.
w+ Okuma/yazma için açar.
a+ Okuma/yazma için açar.
deneme.txt adlı bir dosyanın, yazmak için açılıp açılmadığını test etmek için aşağıdaki kod kullanılır:
#include <stdio.h>
...
FILE *yaz; /* dosya işaretçisi */
...
yaz = fopen("deneme.txt","w");
if( yaz == NULL)
{
puts("bu dosya acilmiyor...");
exit();
}
/* açılırsa! dosya işlemleri */
...
fclose(yaz);
...
Dosya Fonksiyonları
Fonksiyon Görevi
fopen() Dosya oluşturur, açar
fclose() Dosyayı kapatır
putc() Dosyaya karakter yazar
getc() Dosyadan karakter okur
feof() Dosya sonuna gelindiğini sorgular
fprintf() Dosyaya formatlı veri yazar
fscanf() Dosyadan formatlı veri okur
fputs() Dosyaya katar yazar
fgets() Dosyadan katar okur
fwrite() Dosyaya dizi yazar
fread() Dosyadan dizi okur
ÖrneklerProgram 12.1 : Bu program klavyeden girilen iki tamsayı ve toplamını deneme.txt adlı bir dosyaya yazar.
1:/* dosya1.c */
2: #include <stdio.h>
3:
4: main()
5: {
6: FILE *yaz;
7: int x,y,z;
8:
9: yaz = fopen("deneme.txt","w");
10: if( yaz== NULL)
11: {
12: puts("Dosya acilamiyor...\a\n");
13: exit();
14: }
15:
16: printf("Toplanacak iki sayı girin : ");
17: scanf("%d %d",&x,&y);
18: z = x+y;
19:
20: fputs( "Bu dosya iki sayının toplamsını gösterir!\n",yaz );
21: fprintf(yaz,"%d + %d = %d",x,y,z);
22: fclose(yaz);
23:
24: puts("Bilgiler kaydedildi. Devam etmek için ENTER tuşuna basın.");
25: getchar();
26: }
Toplanacak iki sayı girin : 5 6
Bilgiler kaydedildi. Devam etmek için ENTER tuşuna basın.
+-----------------------------------------------
| Bu dosya iki sayının toplamsını gösterir!
| 5 + 6 = 11
|
Not: deneme.txt dosyası daha önce oluşturulmuşsa Program 12.1 önceki verileri silip yerine yeni verileri yazacaktır. Ekleme yapmak için fopen() fonksiyonunu 'a' modu ile kullanılmalıdır.
Bilgisayarın c:\deneme dizininde bulunan tipler.dat adlı bir dosyaya sahip olduğumuzu varsayalım, ve bu dosyanın içeriği aşağıdaki gibi olsun.
+-------------------------------
|Ahmet
|d
|1256
|65489878
|0.822
|
Buradaki veri tipleri sırasıyla katar, karakter, tamsayı, uzun tamsayı ve reel sayı şeklindedir. dosya2.c programı bu verilerin nasıl okunacağını göstermektedir.
Program 12.2 : Bu program bir dosyaya formatlı yazılmış olan verileri okur ve ekrana basar
1: /* dosya2.c */
2: #include <stdio.h>
3: main()
4: {
5: FILE *oku;
6: char ktr[10],kr;
7: int tam;
8: long uzun_tam;
9: float reel;
10:
11: if( (oku=fopen("c:\\deneme\\tipler.dat","r")==NULL ){
12: puts("Dosya açılmadı !\n");
13: exit();
14: }
15:
16: fscanf(oku,"%s\n%c\n%d\n%ld\n\%f",
17: ktr,&kr,&tam,&uzun_tam,&reel);
18: fclose(oku);
19:
20: puts("Dosyadan okunan veriler sırasıyla:");
21: printf(%s\n%c\n%d\n%ld\n\%f",ktr,kr,tam,uzun_tam,reel);
22:
23: }
Dosyadan okunan veriler sırasıyla:
Ahmet
d
1256
65489878
0.822
Elimizde aşağıdaki gibi bir dosya olsun. Bu dosyadan istediğimiz bir öğrencinin numarasını girerek ona ait bilgilere ulaşılmak istensin. Program 12.3 basit bir veritabanı uygulamasıdır. Bu program öğrencilere ait bilgilerin bulunduğu bir dosyadan veri okur. 16. satırda Öğrencinin numarası istenir. Eğer böyle bir numara varsa öğrenciye ait bilgiler ekrana basılır. Aksi durumda "Kayıt bulunamadı" şelinde bir ileti ekrana basılır.
+------------------------------------------------
|NO ADI SOYADI mt1 mt2 fin
|--- ------- ------ --- --- ---
|251 Ahmet Bingul 100 100 100
|597 Meltem Bingul 100 100 100
|569 Metin Celen 54 65 89
|987 Teoman Burak 45 87 65
|
Program 12.3 : Basit bir veritabanı
1: /* dosya3.c */
2: #include <stdio.h>
3:
4: main()
5: {
6: FILE *notlar;
7: int i,numara,no,mt1,mt2,final;
8: char gecici[10],ad[10],soyad[10];
9:
10: if( (notlar=fopen("notlar.js","r")==NULL ){
11: puts("Dosya açılmadı !\n");
12: exit(0);
13: }
14:
15: printf("Numara girin: ");
16: scanf("%d",&numara);
17:
18: for(i=0;i<12;i++)
18: fscanf(notlar,"%s",gecici);
19:
20: no = 0;
21:
22: while( !feof(notlar) )
23: {
24: fscanf(notlar,"%d\t%s\t%s\%d\t%d\t%d\n",
25: &no,ad,soyad,&mt1,&mt2,&final);
26: if( no==numara ) break;
27: }
28: fclose(oku);
29: if( no ){
30: puts("Öğrenci Bilgileri:");
31: printf("Numarası : %d",no);
32: printf("Adı : %s",ad);
33: printf("Soyadı : %d",soyad);
34: printf("1.Vize : %d",mt1);
35: printf("2.Vize : %d",mt2);
36: printf("2.Vize : %d",mt3);
37: }
38: else
39: puts("Kayıt bulunamadı");
40:
41: }/*main*/
Bazı uygulamalarda, daha önce bir şekilde hazırlanmış olan bir dosyanın içeriğini değiştirmek gerekebilir. Program 12.4 , eski.dat dosyasındaki verileri yeni.dat dosyasına aşağıdaki çevirir. Program kodları bir dosyadan diger bir dosyaya, bir verinin nasıl taşınacağına dair bir örnek teşkil eder.
dosya 1 dosya 2
_______________ ________________
|X-degerleri | | |
|1.0 | |X Y |
|2.0 | |1.0 0.0 |
|3.0 | |2.0 2.5 |
|4.0 | |3.0 4.9 |
|5.0 | ---> |4.0 3.2 |
|Y-degerleri | |5.0 1.8 |
|0.0 | | |
|2.5 | | |
|4.9 | | |
|3.2 | | |
|1.8 | | |
|_______________| |________________|
Program 12.4 : dosya1 in içindeki alt alta olarak yazılmış olan verileri, dosya2 ye şekildeki gibi yan yana yazar
1: /* dosya4.c */
2: #include <stdio.h>
3:
4: main()
5: {
6: FILE *oku,*yaz;
7: float x[5],y[5];
8: char dosya1[12],dosya2[12],gecici[10];
9: int i;
10:
11: printf("Verilerin okunacağı dosyanın adı");
12: scanf("%s",dosya1);
13: if( (oku==fopen(dosya1,"r"))==NULL ){
14: printf("%s dosyası acilamiyor...",dosya1);
15: exit();
16: }
17:
18: printf("Verilerin yazılacağı dosyanın adı");
19: scanf("%s",dosya2);
20: if( (yaz==fopen(dosya1,"w"))==NULL ){
21: printf("%s dosyası acilamiyor...",dosya2);
22: exit();
23: }
24:
25: /*dosya1 den verileri oku, bu verileri x[] ve y[] dizilerine sakla */
26: fscanf(oku,"%s",gecici); /* rakamlarin disindaki degerleri okumak icin */
27:
28: for(i=0;i<5;i++) fscanf(oku,"%f\n",&x[i]);
29:
30: fscanf(oku,"%s",gecici);
31:
32: for(i=0;i<5;i++) fscanf(oku,"%f\n",&y[i]);
33:
34: fclose(oku); /* verilerin bulundugu dosyayi kapat */
35:
36: /* dizileri dosya2 ye yaz */
37: fprintf(yaz,"X\tY");
38: for(i=0;i<5;i++)
39: fprintf(yaz,"%f\t%f",x[i],y[i]);
40: fclose(yaz); /* verilerin yazildigi dosyayi kapat */
41:
42: printf("%s --> %s dönüştürme işlemi gerçekleşti.",dosya1,dosya2);
43:
44: return 0;
45:}
Ders13: enum, struct, union ve typedef Yapıları
C, kullanıcının kendi veri tipini tanımlamasına müsaade eder. Bu kısımda böyle veritiplerinin nasıl oluşturulacağı anlatılacaktır.
enum
Bu tip, değişkenin alabileceği değerlerin belli(sabit) olduğu durumlarda programı daha okunabilir hale getirmek için kullanılır. enum örnekleri Program 13.1 ve Program 13.2 de gösterilmiştir. Genel yazım biçimi:
enum TipAdı{değer1,değer2,...,değerN}DeğişkenAdı;
TipAdı programcı tarafından verilen tip ismidir. DeğişkenAdı ise program içinde kullanılacak olan değişkenin adıdır. Eğer kullanılmazsa program içinde daha sonra enum ile birlikte kullanılır. Örneğin:
enum bolumler{programcilik, donanim, muhasebe, motor};
tanımı ile derleyici programcilik için 0, donanim için 1, muhasebe için 2 ve motor için 3 değerini kabul ederek atamaları buna göre yapar. Değişken adı bildirilirse daha sonra enum kullanmaya gerek kalmaz.
enum renkler{kirmizi,mavi,sari} renk;
enum gunler{pazartesi,sali,carsamba,persembe,cuma,cumartesi,pazar};
Şimdi istenirse tanımlanan bu tipler program içinde kullanılabilir.
enum bolumler bolum;
enum gunler gun;
bolum = muhasebe /* bolum = 2 anlaminda */
gun = cuma; /* gun = 4 anlaminda */
renk = kirmizi; /* renk = 0 anlaminda */
Program 13.1 : 3 sabit renk için enum kullanımı
1: /* enum1.c */
2: enum renkler{kirmizi,sari,mavi};
3:
4: main(){
5: enum renkler renk;
6: renk = sari;
7: printf("\n%d",renk);
8: }
Program 13.2 : 5 sabit bölüm için enum kullanımı
1: /* enum2.c */
2: enum bolumler{
3: programcilik, donanim, muhasebe, motor, buro
4: }bolum;
5:
6: main(){
7: bolum = donanim;
8: printf("\n%d",bolum);
9: bolum +=2; /* bolum=motor */
10: printf("\n%d",bolum);
11: }
stuctC dilinde standart tipler kullanılarak kendi tipinizi üretebilirsiniz. (struct örnekleri Program 13.3 , Program 13.4 ve Program 13.5 te gösterilmiştir). Bu yapının kullanımı:
struct TipAdı{
tip deg_ismi;
tip deg_ismi;
...
};
enum ile sabit bildirimi yapılırken struct ile değişken bildirimi yapılır. Bu yapının faydası, örneğin bir öğrenciye ait bilgileri bir çatı altında toplamak için:
struct ogrenci{
char ad[10],soyad[20];
long no;
short sinif;
};
Bu tipte bir değişken tanımlama:
struct ogrenci ogr1,ogr2;
şeklinde olmalıdır. ogr1 değişkeni ile tanımlanan 1. öğrencinin numarasına bir değer atama işlemi:
ogr1.no = 2012597;
veya
ogr1->no = 2012597;
şeklinde yapılır.Program 13.3 : Bir öğrenciye ait bilgilerin tek bir çatı altında toplanması
1: /* struct1.c */
2: #include <stdio.h>
3:
4: struct ogrenci{
5: char ad[10],soyad[20];
6: long no;
7: int sinif;
8: }
9:
10: main(){
11: struct ogrenci ogr;
12: printf("Ogrenci nosu :");
13: scanf("%ld",&ogr.no);
14: if( ogr.no == 2248 )
15: {
16: ogr.no = 2248;
17: strcpy(ogr.ad,"Ahmet");
18: strcpy(ogr.soyad,"Bingul");
19: ogr.sinif = 1;
20: }
21: printf("\nNo : %ld",ogr.no);
22: printf("\nAdı : %s ",ogr.ad);
23: printf("\nSoyadı: %s ",ogr.soyad);
24: printf("\nSınıfı: %d ",ogr.sinif);
25: }
Program 13.4 : Bir öğrenciye ait bilgilerin tek bir çatı altında toplanması
/* struct2.c */
#include <stdio.h>
struct ogrenci{
char ad[10],soyad[20];
long no;
int sinif;
}ogr;
main(){
printf("Ogrenci nosu :");
scanf("%ld",&ogr->no);
if( ogr.no == 2248 )
{
ogr.no = 2248;
strcpy(ogr.ad,"Ahmet");
strcpy(ogr.soyad,"Bingul");
ogr.sinif = 1;
}
printf("\nNo : %ld",ogr.no);
printf("\nAdı : %s ",ogr.ad);
printf("\nSoyadı: %s ",ogr.soyad);
printf("\nSınıfı: %d ",ogr.sinif);
}
Program 13.5 : bir topun x-y düzlemindeki zamana bağlı hareketi
1: /* struct3.c */
2: #include <stdio.h>
3: #include <math.h>
4:
5: struct koordinat{
6: float x,y;
7: }top;
8:
9: main(){
10: int i;
11: float t;
12:
13: for(t=0.0;t<10.0;t+=0.1){
14: top->x = 10 - 9*cos(t);
15: top->y = 5 + 2*sin(t);
16: printf("%f\t%f",top->x,top->y);
17: }
18:
19: }
tpyedefstruct ile oluşturulan yapıda typedef deyimi kullanılırsa, bu yapıdan değişken tanımlamak için tekrar struct deyiminin kullanılmasına gerek kalmaz.
typedef struct kayit{
char ad[10],soyad[20];
long no;
short sinif;
}ogr1,ogr2;
bu kullanımın diğerlerinden farkı yoktur.
Bu deyimin başka kullanımı da vardır. C dilinde program kodları bu deyimle tamamen türkçeleştirilebilir. Örneğin:
typedef int tamsayi;
şeklinde kullanılırsa programda daha sonra int tipinde bir değişken tanımlarken şu biçimde kullanılmasına izin verilir.
tamsayi x,y; /* int x,y anlaminda */
unionBir programda veya fonksiyonda değişkenlerin aynı bellek alanını paylaşması için ortaklık bildirimi union deyimi ile yapılır. Bu da belleğin daha verimli kullanılmasına imkan verir. Bu tipte bildirim yapılırken struct yerine union yazılır.
union paylas{
float f;
int i;
char kr;
};
Dikkat: Yukarıdaki bildirim yapıldığında, bellekte bir yer ayrılmaz. Değişken bildirimi:
union paylas bir,iki;
şeklinde yapılır. Üyelere erişmek aşağıdaki gibi olur:
bir.kr= 'A';
iki.f = 3.14;
bir.i = 2000;
Program 13.6 : union x ve y nin aynı bellek alanını işgal ettiğinin kanıtı
1: /* union1 */
2: #include <stdio.h>
3:
4: union paylas{
5: int x;
6: int y;
7: }z;
8:
9: main()
10: {
11: int *X,*Y;
12:
13: z.x = 10;
14: X = &z.x;
15: printf("\nTamsayı(x) : %d - bellek adresi %X",z.x,X);
16:
17: z.y = 20;
18: Y = &z.y;
20: printf("\nTamsayı(y) : %d - bellek adresi %X",z.y,Y);
21: }
Tamsayı(x) : 10 - bellek adresi DF23
Tamsayı(y) : 20 - bellek adresi DF23
Hazırlayan Ömer Zafer ÖZGÖÇER
Bu fonksiyonlar en temel trigonomertik fonksiyonlardır. Kullanımları Tablo 6.1 da gösterilmiştir. Örnek program Program 6.4 de sunulmuştur.
Tablo 6.1 : Bazı Trigonometrik fonksiyonlar
Bu fonksiyonlar kendisine parametre olarak gelen değeri radyan olarak kabul eder ve sonucu hesaplar. Eğer derece cinsinden açıların hesaplanması gerekiyorsa su dönüşüm kullanılmalıdır:
radyan = (3.141593/180.0)*derece;
Program 6.4 : 45 dercelik bir açının sinüs, kosinüs ve tanjant değerleri
1: /* sin(), cos(), and tan() funksiyonlarının kullanımı */
2: #include <stdio.h>
3: #include <math.h>
4:
5: main()
6: {
7: double x;
8:
9: x = 45.0; /* 45 derece */
10: x *= 3.141593 / 180.0; /* radyana çeveir */
11: printf("45 derecenin sinüsü : %f.\n", sin(x));
12: printf("45 derecenin kosinüsü : %f.\n", cos(x));
13: printf("45 derecenin tanjantı : %f.\n", tan(x));
14: return 0;
15: }
45 derecenin sinüsü : 0.707107
45 derecenin kosinüsü : 0.707107
45 derecenin tanjantı : 1.000000
pow() - sqrt() - log() - log10() Fonksiyonları

