fopenile bir dosyayı doğru kipte açmak,NULLkontrolü yapmak vefcloseile kapatmakfprintfile dosyaya yazmak vefgetsile satır satır okumak- Okunan bir satırdan
sscanfile veri çıkarmak - Yapıları, dinamik belleği ve dosyaları tek bir programda birleştirmek
Şimdiye kadar yazdığın programların hepsinin ortak bir eksiği var: program biter bitmez tüm veriler kaybolur. Not defterindeki notlar, bir oyunun rekoru, ayarlar... Yarın yeniden gerekecek her şey bir dosyaya yazılmalıdır. Bu derste C'de dosyalarla çalışmayı öğrenecek, ardından kursun ana konularını, yani yapıları, işaretçileri, dinamik belleği ve dosyaları tek bir projede birleştireceksin.
Dosya açmak ve kapatmak
C'de bir dosya FILE * türünde bir işaretçiyle yönetilir. fopen(ad, kip) dosyayı açar ve bu işaretçiyi döndürür; dosya açılamazsa (örneğin dosya yoksa ya da klasöre yazma izni yoksa) NULL döndürür. İş bitince fclose dosyayı kapatır: bellekte bekleyen verileri diske yazar ve kaynağı sisteme geri verir.
| Kip | Anlamı | Dosya yoksa |
|---|---|---|
"r" | okuma | fopen NULL döndürür |
"w" | yazma; eski içerik silinir | yeni bir dosya oluşturulur |
"a" | sona ekleme | yeni bir dosya oluşturulur |
fprintf, printf gibi çalışır; yalnızca ilk argüman olarak dosyayı alır. fgets(satır, boyut, dosya) dosyadan bir satır okur: en fazla boyut − 1 karakter okur, sona '\0' koyar ve '\n''i satırın içinde bırakır. Dosyanın sonunda NULL döndürür; bu yüzden while döngüsünde rahatça kullanılır.
#include <stdio.h>
int main(void) {
FILE *f = fopen("notes.txt", "w");
if (f == NULL) {
printf("Cannot open file\n");
return 1;
}
fprintf(f, "C was created in %d\n", 1972);
fprintf(f, "Files keep data\n");
fclose(f);
char line[100];
f = fopen("notes.txt", "r");
if (f == NULL) {
return 1;
}
while (fgets(line, sizeof line, f) != NULL) {
printf("Read: %s", line);
}
fclose(f);
return 0;
}Read: C was created in 1972 Read: Files keep data
printf("Read: %s", line) içinde \n yok; çünkü fgets onu satırın içinde bıraktı.Proje: öğrenci kayıtları
Bir öğretmen sınav sonuçlarını saklamak istiyor. Programımız öğrencileri bir dosyaya yazacak, sonra dosyayı okuyup öğrenci sayısını önceden bilmeden onları dinamik bir diziye yükleyecek ve bir rapor yazdıracak. Dosya basit bir metin biçimindedir: her satırda bir ad ve bir puan.
- 1Türü ve kaydetmeyi hazırla
Studentyapısını tanımla ve diziyifprintfile dosyaya yazansavefonksiyonunu yaz. - 2Dosyayı yükle
loadönce satırları sayar,mallocile tam gerektiği kadar yer ayırır,rewindile dosyanın başına döner ve her satırısscanfile ayrıştırır. - 3Raporu yazdır ve belleği geri ver
mainöğrencileri kaydeder, geri yükler, ortalamayı ve en iyi sonucu bulur ve sonundafree'yi çağırır.
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char name[20];
int score;
} Student;
int save(const char *path, const Student *list, int n) {
FILE *f = fopen(path, "w");
if (f == NULL) {
return 0;
}
for (int i = 0; i < n; i++) {
fprintf(f, "%s %d\n", list[i].name, list[i].score);
}
fclose(f);
return 1;
}save fonksiyonu. Başarıda 1, hatada 0 döndürür.Aysel 92
Murad 78
Leyla 85
Elvin 64save'den sonra students.txt dosyasının içeriği.sscanf, scanf gibi çalışır ama klavyeden değil, bir karakter dizisinden okur ve başarıyla okuduğu değerlerin sayısını döndürür. %19s en fazla 19 karakter okur; '\0' ile birlikte bu, 20 baytlık name dizisine tam sığar. Biçimi bozuk bir satır basitçe atlanır.
Student *load(const char *path, int *count) {
FILE *f = fopen(path, "r");
if (f == NULL) {
return NULL;
}
char line[64];
int n = 0;
while (fgets(line, sizeof line, f) != NULL) {
n++;
}
Student *list = malloc(n * sizeof *list);
if (list == NULL) {
fclose(f);
return NULL;
}
rewind(f);
int i = 0;
while (i < n && fgets(line, sizeof line, f) != NULL) {
if (sscanf(line, "%19s %d", list[i].name, &list[i].score) == 2) {
i++;
}
}
fclose(f);
*count = i;
return list;
}load yeni dizinin işaretçisini döndürür, eleman sayısını ise count işaretçisi üzerinden yazar.Raporun sütunlarını hizalamak için bir genişlik veririz: %-6s adı 6 karakterlik bir alanda sola, %3d ise sayıyı 3 karakterlik bir alanda sağa hizalar.
int main(void) {
Student group[] = {{"Aysel", 92}, {"Murad", 78}, {"Leyla", 85}, {"Elvin", 64}};
if (!save("students.txt", group, 4)) {
printf("Cannot save\n");
return 1;
}
int n = 0;
Student *list = load("students.txt", &n);
if (list == NULL) {
printf("Cannot load\n");
return 1;
}
int sum = 0, best = 0;
for (int i = 0; i < n; i++) {
printf("%-6s %3d\n", list[i].name, list[i].score);
sum += list[i].score;
if (list[i].score > list[best].score) best = i;
}
printf("Students: %d\n", n);
printf("Average: %.2f\n", (double) sum / n);
printf("Best: %s\n", list[best].name);
free(list);
return 0;
}Aysel 92 Murad 78 Leyla 85 Elvin 64 Students: 4 Average: 79.75 Best: Aysel
records.c dosyasına koy ve derle; çıktı böyle olur. (92 + 78 + 85 + 64) / 4 = 79,75.Önemli noktalar
FILE *f = fopen(ad, kip);— sonuçNULLise dosya açılmamıştır; iş bitincefclose(f)."r"okur,"w"eski içeriği silip yazar,"a"sona ekler.fprintfdosyaya biçimli metin yazar;fgetsbir satırı güvenle okur ve dosya sonundaNULLdöndürür.sscanfokunan satırdan değerleri çıkarır;%19sgibi bir genişlik sınırı taşmayı önler.- Gerçek programlar yapıları, dinamik belleği ve dosyaları birlikte kullanır; her
malloc'u birfreeile bitir.
Kendini test et
10 soru. Her doğru cevap XP kazandırır.
fopen ne döndürür?