Temel C Dokümanları 7 (Dosya işlemleri)
Sıra geldi hepimzin merakla bekledigi C de dosya acma, yazma, yani data kullanma olaylarına…
Şimdi yeni bir degisken daha ogrenencez. Degiskenimizin turu: FILE isminden de anlasıldıgı gibi dosyaları temsil eden bir degisken turu.bu. Ama file diye degil FILE olarak yazacaz unutmayın ki C buyuk harf kucuk harf ayrımı yapan bir dildir. Peki nasıl kullanacaz bu FILE degiskenini ? Diger degiskenler gibi soyle:
FILE *f;
Bu komutla f adında bir FILE degiskeni pointerı yaptık. Niye pointer olarak belirledik de normal bi degisken yapmadık diye merak ediyorsanız bunun sebebi dosya acma yazma ve okuma islemleri icin kullanacagımız hazır fonksiyonların input olarak pointer kabul etmeleridir. Simdi bu FILE pointerını kullanacagımız fonksiyonlara bakalım:
fopen , fclose , fprintf, fscanf , fputs, fgets adında fonksiyonları tanıyacaz ve kullanacaz. Bu fonksiyonlar stdio.h kutuphane dosyasında tanımlanmıstır. Once fopen:
FILE *fopen(char *dosyayolu, char *dosyaizni)
Seklinde tanımlanmıstır. Fonksiyonlar dersimizi hatırlarsak bu fonksiyonun nasıl kullanıldıgını anlarız hemen. Bastaki FILE * kısmından fonksiyonun cıktı olarak bir fILE pointerı verdigini goruyoruz. Parantez icindeki inputların turlerine bakarsak iki tane string aldıgını goruruz. Bunlardan ilki acacagımız dosyanın yolu, ikincisi ise dosyayı hangi iznle acacagımızdır. Yani yazmak icinmi, okumak icinmi, append etmek icinmi actıgımızı belirtecez. Bir ornekle gosterelim.
FILE *f;
Char *path=”c:\\ornek.txt”;
f=fopen(path,”w”);
bu kodlarla f adında bip FILE pointerı belirledik, sonra path adında bir string yaptık. Daha onceki string derslerimizde
char path[]=”c:\\ornek.txt”;
seklinde string olusturuyorduk. Simdi pointerları ogrendikten sonra char *path; seklinde de string belirleyebildigimizi ogrenmis olduk. Pointerlar dersinin ikinci kısmındaki pointerların arrayler le ve arraylerin de stringlerle iliksilerini incelerseniz olayı anlarsınız. Anlayamasanız sorun J . Burada diger bir dikkat edilecek nokta c:\ornek.txt yerine c:\\ornek.txt yazdık. İki tane \ kullandık. Bunun sebebi \ isaretinin stringlerde ozel bir karakter olması. \n seklinde alt satıra gecmemiz gibi. \ isaretinden sonra gelen karakterin ozel bir karakterle karıstırılmaması icin iki tane yazıyoruz.
Yukardaki kodların son satırında ise f pointerına fopen fonksiyonundan cıkan dosyayı atıyoruz. “w” iznini kullanarak. “w” yazmak icin demek. Simdi bu izinleri ve nasıl kullanıldıklarının baslıcalarını inceleyelim biraz.
r : Okumak icin acar
w: Yazmak icin acar, dosya varsa icindekiler silinir, yoksa
a: Appends; dosya zaten varsa acar yoksa olusturur, ve dosyanın sonuna yazar.
Artık elimizde bir dosya var ona istedigimizi yapabiliriz. Simdi dosyayadan nasıl okuyacagımızı ve nasıl yazacagımızı ogrenenlim. fprintf ve fscanf fonksiyonları:
Bu fonksiyonlar scanf ve printf fonksiyonlarına benzerler. Tek farkı input olarak bir de steam almalarıdır. Steam nedir ? stream bilgi alınıp verilen arabirimlerdir. Baslıca streamler stdin, stdout ve stderr dır.Bunlar sırasıyla standart input(girdi), standart output(cıktı) ve standart error(hata) anlamına gelir. Standart girdi klavyedir. Standart cıktı monitordur. Standart error ise bir program calısırken olusan hataların kaydedildigi sream dir. Scanf fonksiyonu stdin stream ini kullanır. Yani klavyeden girilen seyi okur. Printf ise stdout streamini kullanarak bilgiyi direk monitore gonderir. Bu ana steam lerden baksa srteam ler de olusturulabilir. Mesela bir FILE pointerı bilgi okunup yazılabilen bir steam olusturur. fprintf ve fscanf fonksiyonları ile steam olarak FILE pointerı gosterilir ve buradan bilgi alınıp yazılır.Simdi printf fonksiyonu ile yaptıgım seyi fprintf fonksiyon u ile kıyaslayabilecegimiz iki kod yazalım.
int x;
x=5;
printf(“x in degeri %d dir”,x);
Bu kodla ekrana su yazılır:
x in degeri 5 dir.
Simdi fprintf ornegi:
FILE *f;
İnt x;
f=fopen(“c:\\ornek.txt”,”w”);
x=5;
fpintf(f,”x in degeri %d dir”,x);
Bu kodlarla c:\ornek.txt adındaki dosya acılır. Eger boyle bir dosya yoksa olusturulur.Varsa acılırken icindeki tum bilgiler silinir. Sonra bu text dosyasına “x in degeri 5 dir” yazılır. Goruldugu gibi printf ve fprintf arasındaki tek kodlama farkı, fprintf in parantezlerinde basa steam olarak actıgımız dosyayı temsil eden FILE pointerını yazmamız. Ve boylece ekrana bir yazı yazılacagına actıgımız dosyaya yazılıyor.
fscanf de cok benmzer sekildedir.
Scanf:
Scanf(“%d”,&y)
Fscan:
fscanf(f,“%d”,&y)
fscnaf ile f dosyasınındanki ilk veri okunur ve y degiskenine atanır. Tıpkı scanf ile klavyeden gelen bilginin okunup degiskene atanması gibi.
fclose fonksiyonu ile de dosya ile olan isimiz bitince dosyamızı kapatırız.,
fclose(f)
seklinde… Simdi buraya kadar ogrendiklerimizle basit bir program yazalım. Programımız calısınca c:\radres.txt diye bir dosyanın ilk kelimesini okusun(once radres.txt diye bir dosya olusturup sonra da icine biseyler yazıp kaydetmemiz gerekiyor tabi…)sonra da c:\ornek.txt diye bir dosya olusturup o dosyaya radres.txt den okudugu kelimeyi yazsın:
#include<stdio.h>
main()
{
FILE *radres;
FILE *ornek;
char *rad;
radres= fopen("c:\\radres.txt","r"
;
if(radres==NULL)
{
printf("radres.txt bulunamadı"
;
exit(-1);
}
fscanf(radres,"%s",&rad);
ornek=fopen("c:\\ornek.txt","w"
;
fprintf(ornek,"%s",rad);
fclose(radres);
fclose(ornek);
return 0;
}
yukardaki kodlarda ki if radres.txt idye bir dosya belirtilen yerde yoksa. Yani bu durumda radres FILE pointerına dondurulen deger NULL yani bossa ekrana “radres.txt bulunamadı” yazıp programdan cıkıyor…
Simdi fgets ve fputs fonksiyonlarını inceleyelim. String dersinde de soyledigimiz gibi bu fonksiyonlar scanf ve printf den farklı olarak string okuma ve yazma icin ozellesmis gonksiyonlardır. Scanf ve fscanf le belirtilen kaynaktan bir string okuttugumuzda ilk kelimeyi okurken gets ve fgets tum satırı okur. Demekki bir dosyadan tum satırı okumak yada bir satır yazdırmak istiyorsak fgets ve fputs fonks,yonlarını kullanacaz. Once gets ve puts un kullanımını hatırlayalım.
gets(buf);
seklinde bir komutla ekrandan tum satırı okutup buf stringine cumleyi atıyorduk. fgets ise su sekilde kullanılıyor.
fgets(buf,25,f);
buradaki buf okunan stringi atayacagımız degisken. 25 maksimum kac karakter okuyacagımızı belirtiyor. f ise okunacak steam i yani dosyayı temsil eden FILE pointerının adı oluyor.
puts(buf);
buf stringini ekrana bir satır olarak yazdırır ve alt satıra gecer…
fputs(buf,strlen(buf),f);
burada, buf dosyaya yazılacak olan stirng oluyor. strlen(buf), buf stringinin kac karakterden olustugunu belirten bir fonksiyon. Bu fonksiyonu kullanabilmemiz icin programımızın basına #include<string.h> satırını dahil etmemiz lazım. Cunku strlen fonksiyonu string.h kutuphane dosyasında bulunuyor. Bu fonksşyonu kullanmak yerine bir sayı da yazabilirdik. Yazdıgımız sayı kadar karakter yazılacaktı f dosyasına.
Simdi birde feof diye bir fonksiyon var onun da ne oldugunu bilmemiz lazım. Bu fonksiyon okunan dosyanın sonuna gelip gelmedigimizi kontrol ediyor.
int feof(FILE *f);
seklinde kullanılıyor. Yani girdi olarak bir FILE pointerı alıyor ve cıktı olarak bir tam sayı donduruyor. Eger fonksiyona verilen dosyanın sonuna gelinmemisse 0 degerini donduruyor.
Mesela bir dosyanın sonuna gelip gelmedigimiz ogrenmek icin bir if yazalım:
if ( feof(f) )
{
//burada eger dosyanın sonuna gelindiyse yapılacak kodlar yazılacak mesela…
}
yukardaki kodla eger f dosyasının sonuna gelinmemisse feof(f) 0 degerini dondurecek ve 0, if tarafından yanlıs olarak algılanacak. Eger dosyanın sonuna gelinmisse feof(f) 0 dan farklı bir deger dondurecek ve if bunu dogru olarak algılyıcak…
Simdiye kadar ogrendiklerimizi kullanarak bir program yazalım. Mesela bu program bir text dosyasının hepsini okusun ve icinde belli bir kelimenin kac tane bulundugunu hesaplasın.
Bu programı yazarken string.h da bulunan bir string fonksiyonu kullanacaz. strcmp adlı bir fonksiyon. Bu fonksiyon bir iki stringi bir biri ile kıyaslıyor. Ve eger ilki buyukse 1, ikincisi buyukse -1 , iki string bir birine esitse 0 degerini donduruyor. Buyukden kastım alfabede hangisinin once geldigi anlamında. Ama yazacagımız programda bizi sadece esit olup olmadıkları ilgilendirecek. İste program:
#include<stdio.h>
#include<string.h>
main()
{
FILE *f;
char buf[255];
char dosya[255];
char kelime[255];
int sayac=0;
printf("aranacak kelimeyi girin: "
;
gets(kelime);
while(1)
{
printf("dosyanin adini yoluyla birlikte girin: "
;
gets(dosya);
if((f=fopen(dosya,"r"
)==NULL)
{
printf("dosya bulunamadı "
;
continue;
}
else
break;
}
while( !feof(f) )
{
fscanf(f,"%s",&buf);
if( strcmp(buf, kelime)==0)
sayac++;
}
fclose(f);
printf("%s dosyasında %d tane %s kelimesi bulundu\n",dosya,sayac,kelime);
return 0;
}
Bu programı inceleyin gayet basit bir yapısı var. Ödev verelim . Mesela combo listler vardır bilirsiniz. User:Password formatında alt alta user ve passwordlar vardır bu combo listlerde. Odevimiz bu sekilde yazılmıs bir combo listin userlarını alt alta bir dosyaya, passwordlerini alt alta baksa bir dosyaya yazarak ayıracak bir program yapmak. Bilgisayarınızda combo list yoksa eger. Siteye eklediğim bir combo list adresi vereyim hem bu list işinize de yarar belki:
Linklerin Görülmesine İzin Verilmiyor
Linki Görebilmek İçin Üye Ol veya Giriş Yap
Odev için ip ucu:
radres:avent
şeklindeki bir stringi radres ve avent seklinde ayırmak icin “:” karaktrinin stringin kacıncı elemanı oldugunu bulmak lazım. Bunu icin de string.h library dosyasında bulunan strstr fonksiyonunu kullanabilirsiniz.
x=strstr(buf, ”:” );
seklinde yazılırsa buf stringinin icinde kacıncı elemanın “:“ oldugunu x char pointerına atanır… aslında direk stringi ayıran daha kolay bir fonksiyon var ama solemicem biraz string antremanı yapmış olursunuz .