GÖSTERİCİ DİZİLERİ Göstericiler de birer nesne olduguna göre gösterici dizileri de tanımlanabilmelidir. Elemanları göstericilerden oluşan dizilere “gösterici dizileri” (pointer arrays) denir. Bildirimleri aşağıdaki şekilde yapılır : <tür> *<dizi ismi [dizi_uzunluğu];> Örneğin : char *s[10]; int *sample[50]; float *kilo[10]; Gösterici dizilerinin bildirimleri normal dizi bildirimlerinden farklı olarak * operatörü ile yapılmaktadır. Örneğin: char str[100]; bildiriminde, str 100 elemanlı char türden bir diziyken char *str[100]; bildiriminde ise, str 100 elemanlı char türden bir gösterici dizisidir. Derleyici bir gösterici dizisi tanımlaması ile karşılaşınca diğer dizilerde yaptığı gibi, bellekte belirtilen sayıda gösteriyi tutabilecek kadar ardışıl yer tahsis eder. Örneğin: char *p[10]; bildirimi ile derleyici, s dizisinin 10 elemanlı ve her elemanın char türden bir gösterici olduğunu anlar. Kullanılan sistemde göstericilerin uzunluğunun 2 byte olduğunu kabul edersek, 20 byte sürekli bir bölge tahsis edecektir. Bu durumda; p[0], p[1], p[2], ...p[9] dizi elemanlarının her biri char türden bir göstericidir. Elemanlarından her biri diğerinden bağımsız olarak kullanılabilir ve her bir eleman bir nesnedir. Aşağıdaki örneği inceleyiniz : main() { char *s[10]; int k; for (k = 0; k < 10; ++k) s[k] = (char *) malloc(30); if (s[k] == NULL) { printf("cannot allocate memory!..\n"); exit(EXIT_FAILURE); } printf("ismi giriniz : "); gets(s[k]); } Bu örnekte her elemanı char türden bir gösterici olan, 10 elemanlı bir gösterici dizisi açılmış ve dizinin her elemanı için, döngü içerisinde malloc fonksiyonu ile 30 byte büyüklüğünde bir bellek bloğu tahsis edilmiştir.Tahsis edilen blokların başlangıç adresleri gösterici dizisinin elemanlarına yerleştirildikten sonra, gets fonksiyonu ile klavyeden girilen karakterlerin tahsis edilen bloklara aktarılmıştır. s isimli dizi yerel bir dizi olduğuna göre, dizi elemanları içerisinde rasgele (garbage values) değerler olduğunu belirtelim. Dolayısıyla malloc fonksiyonu ile yer ayırmadan yapılan veri aktarımları gösterici hatalarına yol açacaktır. Dinamik olarak tahsis edilen alanlar, gerektiği zaman yine bir döngü yardımıyla serbest bırakılabilir : for (k = 0; k < 10; ++k) free(s[k]); gösterici dizilerine ilk değer verilmesi Normal dizilere ilkdeğer nasıl veriliyorsa gösterici dizilerine de ilk değer aynı biçimde verilir. örneğin: int *p[] = { (int *) 0x1FC0, (int *) 0x1FC2, (int *) 0x1FC4, (int *) 0x1FC6, (int *) 0x1FC8 } Kuşkusuz ki, gösterici dizisine atanan adreslerin bir amaç doğrultusunda kullanılabilmesi için güvenli bölgeleri göstermesi gerekir. Bu nedenle uygulamada karakter gösterici dizisi dışındaki gösterici dizilerine ilk değer verilmesi durumuna pek raslanmaz. Gösterici dizilerine ilk değer verme işlemi genellikle karakter gösterici dizilerine string ifadeleriyle ilk değer verilmesi biçiminde karşımıza çıkmaktadır. char türden gösterici dizileri Uygulamalarda en sık görülen gösterici dizileri char türden olan gösterici dizilerdir. Daha önce stringler konusunda da gördüğümüz gibi, stringler C derleyicisi tarafından char türden adresler olarak ele alındığına göre, char türden bir gösterici dizisine stringler aracılığıyla ilk değer verilebilir: char *aylar[] = {“Ocak", "Şubat", "Mart", "Nisan", "Mayıs", "Haziran", "Temmuz", "Ağustos", "Eylül", "Ekim", "Kasım", "Aralık" }; aylar dizisinin her bir elemanı char türden bir göstericidir. Ve bu gösterici dizisine stringler ile ilk değer verilmiştir. Başka bir deyişle char türden bir gösterici dizisi olan aylar dizisinin her bir elemanı bir yazıyı göstermektedir. char türden gösterici dizilerinin kullanılma nedenleri 1. Program içinde sık kullanılacak yazıların her defasında yazılması yerine bir gösterici dizisinin elemanlarında saklanması. Aşağıdai örnekte err dizisinin her bir elemanında hata mesajlarına ilişkin yazılar saklanmıştır. char *err[] = {“Bellek Yetersiz!”, “Hatalı şifre”, “Dosya bulunamadı”, “Belirtilen dosya zaten var”, “ “sürücü hazır değil”, "Okunacak dosya açılamıyor", "yazılacak dosya açılamıyor!.." “Belirlenemeyen hata!”}; Artık programın herhangi bir yerinde yazılardan biri yazdırılmak istenirse, yazdırılacak olan yalnızca gösterici dizisinin herhangi bir elemanında başlangıç adresi tutulan yazıdır : if (fp == NULL) { printf("%s\n", err[5]); return 5; }. 2. Bazı yazıların bu şekilde bir algoritmaya bağlı olarak kullanılması : #include <stdio.h> int dayofweek(int day, int month, int year); char *aylar[] = {“Ocak", "Şubat", "Mart", "Nisan", "Mayıs", "Haziran", "Temmuz", "Ağustos", "Eylül", "Ekim", "Kasım", "Aralık" }; char *gunler[] = {"Pazar", "Pazartesi", "Salı", "Çarşamba", "Perşembe", "Cuma", "Cumartesi" }; void display_date(int day, int mon, int year) { printf("%02d ", day); puts(aylar[mon - 1]); printf(" %d ", year); } Bir yazının belirli bir yazıyla aynı olup olmadığını, strcmp fonksiyonuyla saptayabiliriz. Peki bir yazının bir grup yazı içinde var olup olmadığını nasıl tespit edebiliriz? Aşağıda tanımlanan getmonth fonksiyonu kendisine başlangıç adresi gönderilen bir yazının ingilizce ay isimlerinden biri olup olmadığını test etmekte, eğer böyle ise bu ayın kaçıncı ay olduğu bilgisiyle geri dönmektedir. (1 - 12) Fonksiyon, kendisine gönderilen argumanda başlangıç adresi tutulan yazı bir ay ismine karşılık gelmiyor ise 0 değeriyle geri dönmektedir. #include <stdio.h> #include <string.h> int getmonth(char *str) { char *months[] = {"Jan", Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; int k; for (k = 0; k < 12; ++k) if (!stricmp(months[k], str) return k + 1; return 0; } main() { char s[20]; int n = 20; int result; while (n-- > 0) { printf("bir ay ismi giriniz ."); gets(s); result = getmonth(s); if (result) printf("%s yılın %d. ayıdır\n", s, result); else printf("%s gecerli bir ay ismi değildir\n"); } return 0; } stricmp fonksiyonunun iki yazının karşılaştırmasını büyük harf küçük harf duyarlılığı olmadan yapması dışında, strcmp fonksiyonundan başka bir farkı bulunmadığını hatırlayalım. Gösterici dizileri de tıpkı diğer diziler gibi yerel ya da global olabilecektir. Eğer dizinin global olması durumunda dizi elemanlarının hepsinin içinde 0 değerleri olurken, yerel bir gösterici dizisinin içinde rasgele değerler olacaktır. Dizinin her bir elemanı içinde bir adres bilgisi olduğuna göre, atama yapılmamış global gösterici dizilerinin her bir elemanı içinde 0 adresi (NULL adresini) bulunurken, atama yapılmamış yerel gösterici dizilerinin elemanları içinde rasgele değerler bulunmaktadır. Bir gösterici hatasına neden olmamak için önce gösterici dizisi elemanlarına güvenli adresler yerleştirmek gerekmektedir. Stringler statik nesneler gibi ele alındıkları için bir gösterici dizisi elemanlarına stringlerle değer vermek bir gösterici hatasına enden olmayacaktır. Zira stringler, daha önce de belirtildiği gibi önce derleyici tarafından bellekte güvenli bir bölgeye yerleştirilirler, daha sonra ise yerleştirildikleri bloğun başlangıç adresi olarak ele alınırlar.
12 Ağustos 2020 Çarşamba
C programlama gösterici diziler
Kaydol:
Kayıt Yorumları (Atom)
Hiç yorum yok:
Yorum Gönder
Her yorum bilgidir. Araştırmaya devam...