Bir önceki makalemizde
printf, fprintf ve sprintf fonksiyonlarını ele almıştık. Bu fonksiyonlar, genel
anlamda bir çıkış birimine (örneğin ekrana, char * türünden bir göstericiye
ya da bir dosyaya) bilgi aktaran standart fonksiyonlardı. Bu makalemizde ise
bir giriş biriminden bilgi alıp bir nesneye aktaran fonksiyonlar olan scanf,
fscanf ve sscanf standart fonksiyonlarını ele alacağız.
* scanf Fonksiyonu
:
Programlarımızda
sıklıkla kullanıcıdan bir bilgi almaya gereksinim duyarız. İşte bu işlemi gerçekleştirmek
için scanf fonksiyonu kullanılır. Standart scanf fonksiyonu ile girdi elde edilir.
Fonksiyonun prototip bildirimi stdio.h başlık dosyasında yer alır :
int scanf
(char *format, ...); |
scanf fonksiyonu,
standart girdi biriminden girilen karakterleri okuyarak, parametre değişkeni
olarak aktarılan nesnelere yazar. Karakterleri yorumlama işlemini de format
parametresi olarak geçilen ifadeye göre gerçekleştirir. Geri dönüş değeri, başarılı
olarak aktarılan karakter sayısını ifade eder. Fonksiyonun tüm parametreleri
göstericidir. Format belirten ilk parametrenin dışındaki parametreler, alınan
bilgilerin aktarılacağı göstericilerdir. Format belirten ifadede kullanılan
dönüşüm belirteçleri ile bu göstericiler sırasıyla eşleştirilir ve her göstericiye
değerin ne şekilde yorumlanarak atanacağı belirlenir. Örneğin kullanıcının klavyeden
gireceği bir tamsayı değerini bir nesneye atamak istersek şöyle bir ifade yazmalıyız
:
int deger;
scanf("%d",°er);
//...
int a, b;
scanf("%d%d",&a,&b); |
Görüldüğü üzere,
ikinci parametre olarak "deger" isimli nesnenin adresi geçilmiştir.
Kullanıcının klavyeden gireceği tamsayı değeri, bu adrese yazılacaktır. İkinci
örnekte ise klavyeden iki bilgi alınmıştır. Bu bilgiler de biçimlendirme ifadesine
göre tamsayı olarak yorumlanır. Biçimlendirme ifadesinde özel olarak belli karakterler
kullanarak tek satırda bilgi alımını da sağlayabiliriz. Örneğin klavyeden noktalı
virgül ile ayrılmış üç tane tamsayı değeri almak istediğimizi düşünelim. Yani
kullanıcı bir satırda gireceği tüm bilgileri yazacak ve bunları birer noktalı
virgül ile ayıracak. Bu durumda scanf fonksiyonunu şu şekilde çağırmalıyız :
int a, b,
c;
scanf("%d;%d;%d",&a,&b,&c);
//...
int gun,yil; char
ay[20]; scanf("%d %s %d";&gun,ay,&yil); |
Kullanıcı "34;56;21"
şeklinde bir ifade girdiğinde bu değerler sırasıyla a, b ve c nesnelerine atanacaktır.
Biçimlendirme ifadesinde noktalı virgül kullanmazsak, bu durumda kullanıcının
bu değerleri teker teker girmesi ve her defasında "enter" tuşuna basması
gerekir. Eğer boşluklarla ayrılmış bir ifadeyi tek satırda alarak nesnelerimize
aktarmak istiyorsak biçimlendirme ifadesindeki dönüşüm karakterleri arasına
boşluk karakteri eklemeliyiz. Yukarıda ikinci örnekte klavyeden aralarına boşluklar
ile bırakılmış bir tarih bilgisinin okunmasını sağladık. Örneğin kullanıcı "1
Ocak 2005" gibi bir tarih bilgisini girip "enter" tuşuna bastığında
bu bilgiler sırasıyla gun, ay ve yil nesnelerine aktarılacaktır. (Dizi isimleri
adres belirttiği için ay dizisinin adı doğrudan yazılmıştır.) scanf fonksiyonu
girdi biriminden kaç değer okuyacağını biçimlendirme ifadesinde kullanılan dönüşüm
karakteri sayısına göre belirler. Bu sayı ile alınan değerleri saklamak üzere
fonksiyona aktardığımız adreslerin sayısının tutması önemlidir. scanf fonksiyonu
ile aldığımız bilgilerin sayısını kontrol etmek için fonksiyonun geri dönüş
değerini kullanabiliriz. Bu şekilde kullanıcının bilgileri istediğimiz şekilde
girmesini de sağlayabiliriz. Tarih bilgisi almak için yazdığımız yukarıdaki
ifadede scanf fonksiyonunun bulunduğu satırı bir if ifadesi içerisine alıp geri
dönüş değerinin 3 olup olmadığını kontrol ederiz, eğer girilen bilgi sayısı
3’e eşit değilse kullanıcıya bir bilgi mesajı vererek kullanıcıyı bilgiyi doğru
girmeye zorlayabiliriz. Biçimlendirme ifadesinde kullanılan dönüşüm karakterleri
ile ilgili olarak ayrıntılı bilgiyi printf - fprintf - sprintf fonksiyonlarını
incelediğimiz makalede bulabilirsiniz.
* fscanf
Fonksiyonu :
fprintf fonksiyonu,
bilgileri ilk parametresi olarak geçilen dosya göstericisinin gösterdiği dosyaya
yazıyordu. fscanf fonksiyonu da aynı şekilde bilgileri ilk parametresi olarak
geçilen dosya göstericisinin gösterdiği dosyadan okur ve diğer parametrelerinde
belirtilen adreslere yazar. Fonksiyonun prototip bildirimi stdio.h başlık dosyasında
yer alır :
int fscanf
(FILE *fp, char *format, ...); |
Fonksiyonun ilk
parametresi okumanın yapılacağı dosyayı işaret eden bir dosya göstericisi olmalıdır.
İkinci parametresi biçimlendirme ifadesidir. Diğer parametreler ise okunacak
bilgilerin aktarılacağı nesnelerdir. Geri dönüş değeri, belirtilen dosyadan
başarıyla okunup belirtilen alanlara yazılan değer sayısını ifade eder. printf
- fprintf - sprintf fonksiyonlarını incelediğimiz makalede yaptığımız bir örneği
ele alarak fscanf fonksiyonunu kullanalım. Söz konusu örnekte yılın aylarının
sıra numaralarını ve isimlerini bir dosyaya fprintf fonksiyonu ile yazdırmıştık.
Şimdi aynı dosyadan bu bilgileri okuyarak ekrana yazdıralım :
#include <stdio.h>
#include <stdlib.h>
#define MONTH_NUMBER
12
char *ptr[]
=
{"Ocak","Subat","Mart","Nisan","Mayis","Hazira
n",
"Temmuz","Agustos","Eylul","Ekim","Kasim","Ara
lik"};
int main
()
{
    FILE *fp;
    int i;
    char a1[10], a2[10], a3, a4[20];
    //1. Kısım
    fp = fopen("aylar.txt","w");
    if (!fp) {
        printf("aylar.txt dosyasi olusturulamadi.
Program sonlaniyor... \n");
        exit(EXIT_FAILURE);
    }
    for (i = 0; i < MONTH_NUMBER; ++i)
        fprintf(fp,"%2d. ay : %s\n",i+1,ptr[i]);
    fclose(fp);
    //2.Kısım
    fp = fopen("aylar.txt","r");
    if (!fp) {
        printf("aylar.txt dosyasi acilamadi.
Program sonlaniyor...\n");
        exit(EXIT_FAILURE);
    }
    for (i = 0; i < MONTH_NUMBER; ++i) {
        fscanf(fp,"%s %s %c %s",a1,a2,&a3,a4);
        fprintf(stdout,"%s %s %c %s \n",a1,a2,a3,a4);
    }
    fclose(fp);
    return 0;
}
|
Kodun ilk bölümünde
ptr isimli dizinin elemanları olan ay isimlerini sıra numaraları ile beraber
aylar.txt isimli bir dosyaya yazdırıyoruz. Bu kısmı fprintf fonksiyonunu ele
aldığımız makalede oluşturmuştuk. Şimdi oluşturduğumuz bu dosyadan bu bilgileri
satır satır alarak ekrana yazdıracağız. Okuma sırasında da fscanf fonksiyonunu
kullanacağız. fscanf fonksiyonu ile dosyadan bilgi okuyacaksak, bilginin dosyada
nasıl bir biçimde saklandığını bilmemiz gerekir. Örneğin bizim dosyamızda her
satırda bir ay ve o aya ilişkin sıra numarası "1. ay : Ocak" şeklinde
tutuluyor. Bu bilgiyi okurken "1.", "ay", "Ocak"
kısımlarını char türden göstericilere ":" karakterini ise char türden
bir nesneye aktarabiliriz. Ancak bu bilginin nasıl tutulduğunu bilmeseydik biçimlendirme
ifadesini oluşturamazdık. Kodun ikinci kısmında "aylar.txt" dosyasını
okuma modunda açıyoruz. Dosya açma işlemi başarıyla sonuçlanırsa satır satır
dosyayı okuduğumuz for döngüsüne geliyoruz. Burada fscanf fonksiyonunun biçimlendirme
ifadesini az önce bahsettiğimiz gibi ilk iki parametreyi ve son parametreyi
karakter katarı olarak, üçüncü parametreyi ise karakter olarak okuyacağımızı
belirtecek şekilde yazıyoruz. Bilgilerin aktarılacağı nesneleri ise sırasıyla
diğer parametre değişkenleri olarak yazıyoruz. Karakteri aktaracağımız nesnenin
adresini gönderiyoruz, dizi isimlerini ise sadece isimlerini belirterek gönderiyoruz.
Döngü içerisinde ikinci adımda, okuduğumuz bilgiyi ekrana yazdırmak için fprintf
fonksiyonunu kullandık. Ekrana yazma yapabilmek için fprintf fonksiyonunun ilk
parametresine "stdout" dosya göstericisini geçiyoruz. Hatırlayacağınız
üzere bu dosya göstericisi ve bununla beraber stdin, stderr dosya göstericileri
program başlatıldığında otomatik olarak oluşturuluyordu. stdout dosya göstericisi,
ekrana işaret ediyordu. Bu durumda fprintf fonksiyonu bilgileri ekrana aktaracaktır.
Son olarak dosyamızı kapatıyoruz ve programımız sonlanıyor. fprintf ve fscanf
fonksiyonlarını kullanarak bir dosyayı kopyalamak da mümkündür. İsterseniz buna
ilişkin bir örnek de yapalım :
#include <stdio.h>
#include <stdlib.h>
#define MONTH_NUMBER
12
char *ptr[]
=
{"Ocak","Subat","Mart","Nisan","Mayis","Hazira
n",
"Temmuz","Agustos","Eylul","Ekim","Kasim","Ara
lik"};
int main
()
{
    FILE *fp1, *fp2;
    int i;
    char a1[10], a2[10], a3, a4[20];
    fp1 = fopen("aylar.txt","r");
    if (!fp1) {
        printf("aylar.txt dosyasi acilamadi. Program
sonlaniyor... \n");
        exit(EXIT_FAILURE);
    }
    fp2 =
fopen("kopya_aylar.txt","w");
    if (!fp2) {
        printf("kopya_aylar.txt dosyasi olusturulamadi. Program
sonlaniyor...
\n");
        fclose(fp1);
        exit(EXIT_FAILURE);
    }
    for (i = 0; i < MONTH_NUMBER; ++i) {
        fscanf(fp1,"%s %s %c %s",a1,a2,&a3,a4);
        fprintf(fp2,"%s %s %c %s \n",a1,a2,a3,a4);
    }
    fclose(fp1);
    fclose(fp2);
    return 0;
}
|
Öncelikle bilgilerin
bulunduğu "aylar.txt" dosyasını okuma modunda açıyoruz. Daha sonra
kopya dosyayı "kopya_aylar.txt" isminde yazma modunda açıyoruz. Dosya
açma işlemlerinin başarıyla sonuçlanıp sonuçlanmadığını kontrol ediyoruz. Bu
işlemlerin ardından, sırasıyla ilk dosyadan okuduğumuz bilgiyi hemen kopya dosyaya
yazdırıyoruz. Bilgiyi okumak için fscanf fonksiyonunu, yazdırmak için de fprintf
fonksiyonunu kullandık. Dosya satır satır kopyalandıktan sonra her iki dosyayı
da kapatıyoruz ve programımız sonlanıyor.
* sscanf
Fonksiyonu :
Bu fonksiyon okuyacağı
bilgiyi, ilk parametresinde belirtilen karakter katarından alır. Fonksiyonun
stdio.h başlık dosyasında yer alan prototip bildirimi şu şekildedir :
int sscanf
(char *str, char *format, ...); |
sscanf fonksiyonunun
diğer scanf fonksiyonlarından tek farkı, okuma işlemini ilk parametresinde belirtilen
(char *) türündeki nesneden yapmasıdır. Biçimlendirme ifadesi, yine scanf ve
fscanf fonksiyonlarında olduğu gibi okunan bilginin nasıl yorumlanacağını belirtir.
Diğer parametreler ise bilgilerin aktarılacağı göstericilerdir.
#include <stdio.h>
int main
()
{
    char *str = "12 Aralik 1945";
    int gun, yil;
    char ay[20];
    sscanf(str,"%d %s %d",&gun,ay,&yil);
    printf("%d ",gun);
    printf("%s ",ay);
    printf("%d \n",yil);
    return 0;
}
|
Bu örnekte de (char
*) türünden bir göstericide tutulan tarih bilgisini sscanf fonksiyonu ile okuyarak
gun, yil ve ay isimli nesnelere atadık. Görüldüğü üzere kullanılan tema hep
aynıdır. Sadece okumanın yapıldığı yer değişmektedir. Böylece scanf, fscanf
ve sscanf fonksiyonlarının ortak ve farklı yönlerini kavramış olduk. Bir dahaki
yazımızda görüşmek üzere, mutlu günler dilerim..
Makale:
Standart scanf, fscanf ve sscanf Fonksiyonları C ve Sistem Programlama Çiğdem Çavdaroğlu
|