İçeriğe geç
Educora
İleri22 dk8 / 8

Dosyalar ve proje: öğrenci kayıtları

fopen, fprintf, fgets ve fclose ile dosyaya yaz ve dosyadan oku, ardından yapıları, dinamik belleği ve dosyaları bir öğrenci kayıtları programında birleştir.

Kendini test et
Bu derste öğreneceklerin
  • fopen ile bir dosyayı doğru kipte açmak, NULL kontrolü yapmak ve fclose ile kapatmak
  • fprintf ile dosyaya yazmak ve fgets ile satır satır okumak
  • Okunan bir satırdan sscanf ile 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.

KipAnlamıDosya yoksa
"r"okumafopen NULL döndürür
"w"yazma; eski içerik siliniryeni bir dosya oluşturulur
"a"sona eklemeyeni 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.

C
#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;
}
Beklenen çıktı
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.

  1. 1
    Türü ve kaydetmeyi hazırla

    Student yapısını tanımla ve diziyi fprintf ile dosyaya yazan save fonksiyonunu yaz.

  2. 2
    Dosyayı yükle

    load önce satırları sayar, malloc ile tam gerektiği kadar yer ayırır, rewind ile dosyanın başına döner ve her satırı sscanf ile ayrıştırır.

  3. 3
    Raporu yazdır ve belleği geri ver

    main öğrencileri kaydeder, geri yükler, ortalamayı ve en iyi sonucu bulur ve sonunda free'yi çağırır.

C
#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;
}
1. bölüm: tür ve save fonksiyonu. Başarıda 1, hatada 0 döndürür.
Text
Aysel 92
Murad 78
Leyla 85
Elvin 64
save'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.

C
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;
}
2. bölüm: 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.

C
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;
}
Beklenen çıktı
Aysel   92
Murad   78
Leyla   85
Elvin   64
Students: 4
Average: 79.75
Best: Aysel
3. bölüm. Üç bölümü sırayla tek bir 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ç NULL ise dosya açılmamıştır; iş bitince fclose(f).
  • "r" okur, "w" eski içeriği silip yazar, "a" sona ekler.
  • fprintf dosyaya biçimli metin yazar; fgets bir satırı güvenle okur ve dosya sonunda NULL döndürür.
  • sscanf okunan satırdan değerleri çıkarır; %19s gibi 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 bir free ile bitir.

Kendini test et

10 soru. Her doğru cevap XP kazandırır.

1 / 10
Dosya açılamadığında fopen ne döndürür?