• Metin dosyalarıyla çalışma işlevleri. C dilinde dosyalarla çalışma

    C++'da metin dosyalarıyla çalışma.

    İki ana dosya türü vardır: metin ve ikili. Dosyalar, kullanıcının büyük miktarda veriyi klavyeden girmeye gerek kalmadan doğrudan diskten okumasına olanak tanır.

      Metin herhangi bir karakterden oluşan dosyalar çağrılır. Her biri satır sonu karakteriyle biten satırlar halinde düzenlenirler. Dosyanın sonu "dosyanın sonu" sembolüyle gösterilir. Herhangi bir metin düzenleyici kullanılarak görüntülenebilen bir metin dosyasına bilgi yazarken, tüm veriler bir karakter türüne dönüştürülür ve karakter biçiminde saklanır.

      İÇİNDE ikili Dosyalarda bilgiler, her tür ve yapıdaki verilerin saklanabileceği belirli büyüklükteki bloklar biçiminde okunur ve yazılır.

    Dosyalarla çalışmak için özel veri tipleri, isminde Canlı Yayınlar. Akış ifstream okuma modunda dosyalarla çalışmak için kullanılır ve akış kayıt modunda. Dosyalarla hem yazma hem de okuma modunda çalışmak için bir akış kullanılır f akışı.

    C++ programlarında metin dosyalarıyla çalışırken iostream ve fstream kitaplıklarını dahil etmeniz gerekir.

    İçin yaz verileri bir metin dosyasına aktarmak için şunlara ihtiyacınız vardır:

      akış tipinde bir değişkeni tanımlayın.

      bilgileri bir dosyaya aktarır.

      dosyayı kapattığınızdan emin olun.

    İçin okuma Bir metin dosyasındaki veriler için şunlara ihtiyacınız vardır:

      ifstream türünde bir değişkeni tanımlar.

      open fonksiyonunu kullanarak bir dosyayı açın.

      dosyayı kapatın.

    Kayıt bilgileri bir metin dosyasına

      Daha önce de belirtildiği gibi, bir metin dosyasıyla çalışmaya başlamak için ofstream türünde bir değişken tanımlamanız gerekir. Örneğin şöyle:

      Dosyaya bilgi yazmak için bir F değişkeni oluşturulacaktır.

      Bir sonraki aşamada dosyanın yazılmaya açılması gerekmektedir. Genel olarak akış açma operatörü şöyle görünecektir:

    F.open("dosya", mod);

    Burada F akış olarak tanımlanan bir değişkendir,

    dosya - diskteki dosyanın tam adı,

    mod - açılan dosyayla çalışma modu.

    Tam dosya adını belirtirken çift eğik çizgi kullanmanız gerektiğini lütfen unutmayın. Örneğin, D: sürücüsündeki oyun klasöründe bulunan noobs.txt dosyasının tam adının şu şekilde yazılması gerekecektir:

    D:\\oyun\\noobs.txt.

    Dosya aşağıdaki modlardan birinde açılabilir:

    ios::in - dosyayı veri okuma modunda açar, bu mod ifstream'ler için varsayılan moddur;

    ios::out - bir dosyayı veri yazma modunda açar (bu durumda mevcut dosya hakkındaki bilgiler yok edilir), bu mod ofstreams için varsayılan moddur;

    ios::app - dosyayı, dosyanın sonuna veri yazma modunda açın;

    ios::ate - zaten açık olan bir dosyanın sonuna git;

    ios::trunc - dosyayı temizleyin, bu aynı zamanda ios::out modunda da olur;

    ios::nocreate - mevcut olmayan bir dosyayı açmayın;

    ios::noreplace - mevcut bir dosyayı açma.

    Mode parametresi eksik olabilir, bu durumda dosya bu akış için varsayılan modda açılır.

    Dosyanın başarılı bir şekilde açılmasından sonra (herhangi bir modda), F değişkeni true'yu, aksi takdirde false'u saklar. Bu, dosya açma işleminin doğruluğunu kontrol etmenizi sağlayacaktır.

    Bir dosyayı (örnek olarak D:\\game\\noobs.txt dosyasını ele alalım) kayıt modunda aşağıdaki yollardan biriyle açabilirsiniz:

    // Birinci yol

    akış F;

    F.open("D:\\oyun\\noobs.txt", ios::out);

    //ikinci yöntem, ios::out modu varsayılan moddur

    // İçin akışakış

    akış F;

    //üçüncü yöntem değişkenin tanımını ve akış tipini birleştirir

    //ve dosyayı tek bir ifadeyle açıyoruz

    akış F("D:\\oyun\\noobs.txt", ios::out);

    Dosyayı yazma modunda açtıktan sonra içine bilgi yazabileceğiniz boş bir dosya oluşturulacaktır.

    Mevcut bir dosyayı ilk yazma modunda açmak istiyorsanız mod olarak ios::app kullanmalısınız.

    Bir dosyayı kayıt modunda açtıktan sonra, standart çıkış aygıtı yerine ekrana yazdığınız gibi dosyaya yazabilirsiniz.coutaçık dosyanın adını belirtmelisiniz.

    Örneğin, a değişkenini F akışına yazmak için çıktı ifadesi şöyle görünecektir:

    b, c, d değişkenlerinin G akışına sıralı çıkışı için, çıkış operatörü şu şekilde olacaktır:

    G<

    Bir akışın kapatılması operatör kullanılarak yapılır:

    ÖRNEK:

    D:\\game\\noobs.txt metin dosyasını oluşturun ve içine n adet gerçek sayı yazın.

    #include "stdafx.h"

    #katmak

    #katmak

    #katmak

    ad alanı std'sini kullanma;

    int ana()

    setlocale(LC_ALL, "RUS");

    int i, n;

    çift ​​a;

    //bir dosyaya veri yazmak için bir akışı tanımlar

    akış F;

    //dosyayı yazma modunda açıyoruz,

    //modios:: dışarıvarsayılan olarak yüklü

    f.open("D:\\oyun\\noobs.txt", ios::out);

    //gerçek sayıların sayısını girin

    cout<<" N="; cin>> N;

    //gerçek sayıları girmek için döngü

    //ve bunları bir dosyaya yazıyoruz

    için (i=0; ben

    cout<<"a=";

    //bir sayı girin

    cin>>a;

    F<

    // akışı kapatıyoruz

    f.close();

    sistem("duraklat");

    0 değerini döndür;

    _______________________________________________________________

    Bir metin dosyasından bilgi okumak için aşağıdaki gibi bir değişken tanımlamanız gerekir: ifstream. Bundan sonra dosyayı okumak için operatörü kullanarak açmanız gerekir. açık. Değişken F olarak adlandırılırsa ilk iki ifade şu şekilde olacaktır:

    F.open("D:\\oyun\\noobs.txt", ios::in);

    Bir dosyayı okuma modunda açtıktan sonra, içindeki bilgileri klavyede olduğu gibi okuyabilirsiniz.cinverilerin okunacağı akışın adını belirtin.

    Örneğin, F akışından a değişkenine okumak için giriş ifadesi şu şekilde görünecektir:

    Bir metin düzenleyicide iki sayı, aralarında boşluk, sekme, satır sonu gibi karakterlerden en az biri varsa ayrılmış sayılır. Programcının metin dosyasında kaç tane ve hangi değerlerin saklanacağını önceden bilmesi iyidir. Ancak çoğu zaman dosyada saklanan değerlerin türü basitçe bilinir, ancak sayıları değişebilir. Bu sorunu çözmek için dosyadaki değerleri birer birer okumanız ve her okumadan önce dosyanın sonuna gelinip gelinmediğini kontrol etmeniz gerekir. Bunun için bir fonksiyon var F. eof().

    Burada F iş parçacığının adıdır; işlev bir Boolean değeri döndürür: dosyanın sonuna ulaşılıp ulaşılmadığına bağlı olarak doğru veya yanlış. Bu nedenle, tüm dosyanın içeriğini okumak için bir döngü şu şekilde yazılabilir:

    //bir dosyadan değerleri okumak için düzenleme, yürütme

    //dosyanın sonuna geldiğimizde döngü bozulacak,

    //bu durumda F.eof() true değerini döndürecektir

    while (!F.eof())

    ÖRNEK:

    D:\\game\\noobs.txt metin dosyası gerçek sayıları saklar, ekranda görüntüler ve sayılarını hesaplar.

    #include "stdafx.h"

    #katmak

    #katmak

    #katmak

    #katmak

    ad alanı std'sini kullanma;

    int ana()

    setlocale(LC_ALL, "RUS");

    int n=0;

    şamandıra a;

    f akışı F;

    //dosyayı okuma modunda aç

    F.open("D:\\oyun\\noobs.txt");

    //eğer dosya doğru açıldıysa

    //bir dosyadan değerleri okumak için döngü; döngü yürütme kesintiye uğrayacak,

    //dosyanın sonuna geldiğimizde bu durumda F.eof() true değerini döndürecektir.

    while (!F.eof())

    //F akışından a değişkenine bir sonraki değer okunuyor

    F>>a;

    //a değişkeninin değerini ekrana aktarıyoruz

    cout<

    //okunan sayı sayısını arttır

    // akışı kapatıyoruz

    F.close();

    //okunan sayıların sayısını ekrana yazıyoruz

    cout<<"n="<

    //dosya açılışı hatalıysa çıktı

    //böyle bir dosyanın yokluğuna ilişkin mesajlar

    başka türlü<<" Файл не существует"<

    sistem("duraklat");

    0 değerini döndür;

    C++. İkili dosya işleme

    Bir ikili dosyaya bilgi yazarken karakterler ve sayılar bayt dizisi halinde yazılır.

    İçin yaz verileri bir ikili dosyaya dönüştürmek için şunlara ihtiyacınız vardır:

      FAIL * türünde bir dosya değişkenini FILE *filename; operatörünü kullanarak tanımlayın. Burada dosya adı, dosya işaretçisinin saklanacağı değişkenin adıdır.

      fwrite işlevini kullanarak bir dosyaya bilgi yazın

    İçin saymak b ikili dosyadan veri almak için şunlara ihtiyacınız vardır:

      FILE * türünde bir değişkeni tanımlayın

      fopen işlevini kullanarak bir dosyayı açın

      fclose işlevini kullanarak bir dosyayı kapatın

    İkili dosyalarla çalışmak için gereken temel işlevler.

    İçin keşifler Dosya fopen işlevi için tasarlanmıştır.

    DOSYA *fopen(const *dosya adı, const char *mode)

    Burada dosya adı, açılan dosyanın tam adını saklayan bir dizedir; mod, dosyayla çalışma modunu belirleyen bir dizedir; aşağıdaki değerler mümkündür:

    “rb” - ikili dosyayı okuma modunda açın;

    “wb” - kayıt için bir ikili dosya oluşturun; varsa içeriği temizlenir;

    “ab” - dosyanın sonuna eklenecek bir ikili dosya oluşturun veya açın;

    “rb+” - mevcut bir ikili dosyayı okuma-yazma modunda açar;

    “wb+” - ikili dosyayı okuma-yazma modunda açar, mevcut dosya temizlenir;

    "ab+" - mevcut bilgileri düzeltmek ve dosyanın sonuna yeni bilgiler eklemek için bir ikili dosya açılır veya oluşturulur.

    Dosya başarısız bir şekilde açılırsa işlev, f dosya değişkeninde NULL değerini döndürür. Bir dosyayı açtıktan sonra, 0'ıncı baytı mevcuttur, dosya işaretçisi 0'dır; bunun değeri, okundukça veya yazıldıkça, okunan (yazılan) bayt sayısına göre kaydırılır. Dosya işaretçisinin geçerli değeri, okuma veya yazma işleminin gerçekleşeceği bayt numarasıdır.

    İçin kapanış dosya fclose işlevi için tasarlanmıştır

    int fclose(DOSYA *dosyaadı);

    Dosya başarıyla kapatılmışsa 0, aksi takdirde NULL döner.

    Kaldırma işlevi şunun içindir: kaldırma Dosyalar.

    int kaldır(const char *dosyaadı);

    Bu işlev, filenema adlı dosyayı diskten siler. Silinecek dosyanın kapatılması gerekmektedir. Dosya silinemezse işlev sıfırdan farklı bir değer döndürür.

    İçin yeniden adlandırma dosyalar için yeniden adlandırma işlevi amaçlanmaktadır:

    int rename(const char *eskidosyaadı, const char *yenidosyaadı);

    İlk parametre eski dosya adı, ikincisi ise yenisidir. Program başarıyla sonlandırılırsa 0 değerini döndürür.

    Okuma ikili dosyadan alma fread işlevi kullanılarak yapılır:

    fread(void *ptr, boyut, n, FILE *dosyaadı);

    Fread işlevi, dosya dosya adından boyut boyutunda n öğeyi bir ptr dizisine okur. İşlev, okunan öğelerin sayısını döndürür. Bir dosyadan okuduktan sonra işaretçisi n*boyutta bayt kaydırılır.

    Kayıt ikili dosyaya dönüştürme işlemi fwrite işlevi kullanılarak yapılır:

    fwrite(const void *ptr, boyut, n, FILE *dosyaadı);

    fwrite işlevi, boyut boyutunda n öğeden oluşan bir ptr dizisinden dosya adını yazar. İşlev, yazılan öğelerin sayısını döndürür. Dosyaya bilgi yazıldıktan sonra işaretçi n*boyutta bayt kaydırılır.

    İçin dosya sonu kontrolü feof'un bir işlevi var:

    int feof(DOSYA *dosyaadı);

    Dosyanın sonuna ulaşıldığında sıfırdan farklı bir değer döndürür.

    ÖRNEK:

    D:\\game\\noobs.dat ikili dosyası oluşturun ve içine n tam sayı ve n gerçek sayı yazın.

    #include "stdafx.h"

    #katmak

    ad alanı std'sini kullanma;

    int ana()

    setlocale(LC_ALL, "RUS");

    int n, ben;

    çift ​​a;

    // yazma modunda bir ikili dosya oluşturun

    f=fopen("D:\\oyun\\noobs.dat", "wb");

    // giriş sayılarN

    cout<<"n="; cin>>n;

    fwrite(&n, sizeof(int), 1, f);

    //n tane reel sayı girmek için döngü

    için (i=0; ben

    //sonraki gerçek sayıyı girin

    cout<<"a=";

    cin>>a;

    //gerçel sayının ikili dosyaya yazılması

    fwrite(&a, sizeof(double), 1, f);

    // kapalı dosya

    fclose(f);

    sistem("duraklat");

    0 değerini döndür;

    ÖRNEK:

    Önceki görevde oluşturulan D:\\game\\noobs.dat ikili dosyasının içeriğini görüntüleyin

    #include "stdafx.h"

    #katmak

    ad alanı std'sini kullanma;

    int ana()

    setlocale(LC_ALL, "RUS");

    int n, ben;

    çift ​​a;

    DOSYA *f; //dosya değişkenini tanımlıyoruz

    //mevcut ikili dosyayı okuma modunda aç

    //dosyadan bir tamsayıyı n değişkenine oku

    //n'nin ekrana çıktısı

    cout<<"n="<

    //n sayıdan oluşan bir dizi için bellek tahsis ediliyor

    a=yeni çift[n];

    //dosyadan a dizisine n gerçek sayıyı oku

    //diziyi ekrana aktarıyoruz

    için (i=0; ben

    cout<

    cout<

    // kapalı dosya

    fclose(f);

    sistem("duraklat");

    0 değerini döndür;

    İkili dosya- sıralı veri yapısı, bir dosyayı açtıktan sonra içinde saklanan ilk bayt kullanılabilir. Bir dosyaya sırayla veri yazabilir veya okuyabilirsiniz. Diyelim ki on beşinci sayıyı ve ardından birinciyi saymanız gerekiyor. Sıralı erişim kullanılarak bu şu şekilde yapılabilir:

    int n, ben;

    çift ​​a;

    DOSYA *f;

    f=fopen("D:\\oyun\\noobs.dat", "rb");

    için (i=0; ben<15; i++)

    fclose(f);

    f=fopen("D:\\oyun\\noobs.dat", "rb");

    fread(&a, sizeof(double), 1, f);

    fclose(f);

    Gördüğünüz gibi bir dosyadaki sayıları okumak ve ardından dosyayı tekrar açmak en uygun yol değildir. Dosya işaretçisini belirli bir bayta taşımak için fseek işlevini kullanmak çok daha uygun olacaktır.

    int fseek(DOSYA *dosya adı, long int ofset, int başlangıç);

    Fonksiyon, geçerli dosya konumu işaretçisini F, orijin ve ofset değerlerine göre ayarlar. Ofset parametresi, dosya işaretçisinin, Origin parametresi tarafından belirtilen orijine göre kaydırılacağı bayt sayısına eşittir. Origin parametresinin değeri, stdio.h başlığında tanımlanan aşağıdaki ofset değerlerinden biri olmalıdır:

    SEEK_SET - dosyanın başından itibaren;

    SEEK_CUR - mevcut konumdan;

    SEEK_END - dosyanın sonundan itibaren.

    İşlev, işlem başarılı olursa sıfır değeri, ofset başarısız olursa sıfır olmayan bir değer döndürür.

    fseek işlevi aslında bir dosyadaki herhangi bir değere doğrudan erişim sağlar. Dosyadaki değerin yalnızca konumunu (bayt sayısını) bilmeniz gerekir. Örnek olarak aşağıdaki sorunu kullanarak ikili dosyalarda doğrudan erişimin kullanımına bakalım.

    ÖRNEK

    Daha önce oluşturulan D:\\game\\noobs.dat ikili dosyasında en büyük ve en küçük gerçek sayıların yerini değiştirin.

    Sorunu çözmek için kullanılan algoritma aşağıdaki aşamalardan oluşur:

      bir dosyadan gerçek değerlerin diziye okunması a.

      a dizisinde maksimum (max) ve minimum (min) değerleri ve bunların sayılarını (imax, imin) arayın.

      dosya işaretçisini maksimum değere hareket ettirerek min.

      dosya işaretçisini minimum değere hareket ettirip maksimum yazma.

    Sorunun yorumlarla çözülmesine yönelik programın metni aşağıdadır.

    #include "stdafx.h"

    #katmak

    ad alanı std'sini kullanma;

    int ana()

    setlocale(LC_ALL, "RUS");

    int n, i, imax, imin;

    çift ​​*a, maksimum, minimum;

    DOSYA *f;

    //bir dosyayı okuma-yazma modunda açıyoruz

    f=fopen("D:\\oyun\\noobs.dat", "rb+");

    //dosyadaki sayıyı n değişkenine oku

    //dosyadaki gerçek sayılar

    fread(&n, sizeof(int), 1, f);

    cout<<"n="<

    //gerçek sayıları saklamak için hafıza ayırıyoruz,

    //a dizisinde saklanacak olan

    a=yeni çift[n];

    //dosyadan diziye ve gerçek sayılara oku

    fread(a, sizeof(double), n, f);

    //maksimum ve minimum elemanları ara

    // a dizisinde ve indekslerinde

    for (imax=imin=0, max=min=a, i=1; i

    eğer (a[i]>max)

    maksimum=a[i];

    eğer (a[i]

    min=a[i];

    // hareketli Işaretçi İle maksimum eleman

    fseek(f, sizeof(int)+imax*sizeof(double), SEEK_SET);

    //maksimum dosya elemanı yerine min yaz

    fwrite(&min, sizeof(double), 1, f);

    // hareketli Işaretçi İle minimum eleman

    fseek(f, sizeof(int)+imin*sizeof(double), SEEK_SET);

    //minimum dosya öğesi yerine maksimumu kaydet

    fwrite(&max, sizeof(double), 1, f);

    //dosyayı kapatıyoruz

    fclose(f);

    //belleği serbest bırakıyorum

    silmek [ ]A;

    sistem("duraklat");

    Programcıya göre açık bir dosya, okunan veya yazılan bir veri dizisi olarak temsil edilir. Bir dosya açıldığında, onunla ilişkilendirilir. G/Ç akışı . Çıkış bilgileri akışa yazılır, giriş bilgileri akıştan okunur.

    G/Ç için bir akış açıldığında stdio.h'de tanımlanan standart bir FILE yapısıyla ilişkilendirilir. FILE yapısı dosya hakkında gerekli bilgileri içerir.

    Bir dosyanın açılması, dosya üzerinde daha sonraki işlemler için kullanılabilecek FILE tipindeki yapıya bir işaretçi döndüren fopen() işlevi kullanılarak yapılır.

    DOSYA *fopen(isim, tür);

    name – açılacak dosyanın adı (yol dahil),
    type - dosyaya nasıl erişildiğini tanımlayan bir karakter dizisinin işaretçisi:

    · "r" - dosyayı okumak için açın (dosya mevcut olmalıdır);

    · "w" - yazmak için boş bir dosya açın; dosya mevcutsa içeriği kaybolur;

    · "a" - dosyayı sonuna kadar yazmak üzere açın (eklemek için); dosya mevcut değilse oluşturulur;

    · "r+" - dosyayı okumak ve yazmak için açın (dosya mevcut olmalıdır);

    · "w+" - okumak ve yazmak için boş bir dosya açın; dosya mevcutsa içeriği kaybolur;

    · "a+" - dosyayı okumak ve eklemek için açın; dosya mevcut değilse oluşturulur.

    Dönüş değeri açık akışın bir işaretçisidir. Bir hata tespit edilirse NULL döndürülür.

    fclose() işlevi, fopen() işlevi kullanılarak açılan dosyalarla ilişkili akışı veya akışları kapatır. Kapatılacak akış fclose() fonksiyonunun argümanı tarafından belirlenir.

    Dönüş değeri: akış başarıyla kapatılmışsa 0 değeri; Bir hata meydana gelirse sabit EOF.

    #katmak
    int ana()

    karakter adı = "my.txt";

    if(fp = fopen(isim, "r")!=NULL)

    // dosyayı açmak mümkün müydü?
    ... // veriler üzerinde gerekli işlemler

    else printf("Dosya açılamadı");

    Dosyadan karakter okuma:

    char fgetc(akış);

    İşlev bağımsız değişkeni, FILE türündeki bir akışın işaretçisidir. Fonksiyon okunan karakterin kodunu döndürür. Dosyanın sonuna gelindiğinde veya bir hata meydana geldiğinde EOF sabiti döndürülür.
    Bir dosyaya sembol yazma:

    fputc(karakter, akış);

    Fonksiyonun argümanları bir karakter ve FILE tipindeki bir akışı gösteren bir işaretçidir. Fonksiyon okunan karakterin kodunu döndürür.

    fscanf() ve fprintf() işlevleri, scanf() ve printf() işlevlerine benzer, ancak veri dosyalarıyla çalışır ve ilk argümanları olarak dosyaya yönelik bir işaretçiye sahiptir.

    fscanf(akış, "Giriş Formatı", argümanlar);
    fprintf(akış, "Çıktı Formatı", argümanlar);

    fgets() ve fputs() işlevleri dize girişi/çıkışı için tasarlanmıştır; dosyalarla çalışmak için kullanılan gets() ve puts() işlevlerine benzerler.

    fgets(Çizgi İşaretçisi, Karakter Sayısı, akış);

    Dizenin içerdiği yeni satır karakteri "\n" okununcaya veya akış EOF bitene veya maksimum sayıda karakter okunana kadar akıştan karakterler okunur. Sonuç bir dize işaretçisine yerleştirilir ve "\0" boş karakteriyle biter. Fonksiyon dizenin adresini döndürür.

    fputs(Dize İşaretçisi, akış);

    Geçerli konumdan akışa bir dize kopyalar. Sonlandırıcı boş karakter kopyalanmaz.
    Örnek Numarayı girin ve s1.txt dosyasına kaydedin. Sayıyı s1.txt dosyasından okuyun, 3 artırın ve s2.txt dosyasına kaydedin.

    fopen() işlevi, kullanım için bir akışı açar, bir dosyayı bu akışla ilişkilendirir ve ardından bu akışa bir FILE işaretçisi döndürür. Çoğu zaman dosya bir disk dosyası olarak değerlendirilir. fopen() işlevi aşağıdaki prototipe sahiptir:

    DOSYA *fopen(const char *dosya adı, const char *mode);

    Modun, dosyayı açmak için istenen modu içeren bir dizeye işaret ettiği yer. Borland C++'da mod için geçerli değerler tabloda gösterilmektedir. dosya adı, işletim sistemine geçerli bir dosya adı sağlayan bir karakter dizisi olmalıdır ve bir yol adı içerebilir.

    fopen() işlevi, FILE temel türüne bir işaretçi döndürür. Bu işaretçi dosyayı tanımlar ve çoğu dosya sistemi işlevi tarafından kullanılır. Asla kendiniz değiştirmemelisiniz. Dosya açılamıyorsa işlev bir boş gösterici döndürür.

    Tabloda görüldüğü gibi dosya metin veya ikili modda açılabilir. Metin modunda, siz yazarken satırbaşları ve satır besleme sırası yeni satır karakterine çevrilir. Çıktıda ise bunun tersi doğrudur: yeni satır karakteri satır başı ve satır beslemeye çevrilir. Bu çeviri ikili dosyalarda oluşmaz. Mode argümanında ne t ne de b belirtilmediğinde, dosyanın metin/ikili durumu Borland C++'da tanımlanan _fmode global değişkeninin değeri tarafından belirlenir. Varsayılan olarak fmode O_TEXT olarak ayarlanmıştır, yani metin modu ayarlanmıştır. _fmode'u O_BINARY olarak ayarlarsanız dosyalar ikili modda açılacaktır. (Bu makrolar fcntl.h'de tanımlanmıştır.) Doğal olarak, açık bir t veya b kullanılması, _fmode değişkeniyle ilişkili etkileri ortadan kaldırır. Ayrıca _fmode yalnızca Borland ürünlerine özeldir. ANSI C I/O sisteminde tanımlanmamıştır.

    Yazmak için test adlı bir dosyayı açmanız gerekiyorsa şunu yazmalısınız:

    Fp = fopen("test", "w");

    Burada fp, FILE * türünde bir değişkendir. Ancak aşağıdakileri görmek yaygındır:

    If((fp = fopen("test", "w"))==NULL) (
    puts("Dosya açılamıyor.");
    çıkış(1);
    }

    Bu yöntem, bir dosyayı açarken, örneğin yazma korumasının varlığı veya diskte boş alan olmaması gibi hataları tespit etmenizi sağlar.

    Bir dosyayı yazmak üzere açmak için fopen() kullanılırsa, belirtilen adda önceden var olan herhangi bir dosya silinecektir. Belirtilen isimde bir dosya mevcut değilse oluşturulacaktır.

    Dosyanın sonuna bilgi eklemeniz gerekiyorsa a (ekleme) modunu kullanmalısınız. Dosya mevcut değilse oluşturulacaktır.

    Bir dosyayı okumak için açmak, dosyanın varlığını gerektirir. Dosya mevcut değilse bir hata döndürülür. Bir dosya okuma/yazma işlemi için açılırsa, varsa silinmez, yoksa oluşturulur.

    Tablo: İzin verilen mod değerleri

    Anlam

    Okumak için bir dosya açar. (Varsayılan olarak metin dosyası olarak açılır.)

    Yazılacak bir dosya oluşturur. (Varsayılan olarak metin dosyası olarak açılır.)

    Bir dosyaya eklenir. (Varsayılan olarak metin dosyası olarak açılır.)

    Okumak için bir ikili dosyayı açar.

    Yazmak için bir ikili dosyayı açar.

    Bir ikili dosyaya eklenir.

    Okumak/yazmak için bir dosya açar. (Varsayılan olarak metin dosyası olarak açılır.)

    Bir okuma/yazma dosyası oluşturur. (Varsayılan olarak metin dosyası olarak açılır.)

    Bir okuma/yazma dosyası ekler veya oluşturur. (Varsayılan olarak metin dosyası olarak açılır.)

    Okuma/yazma için bir ikili dosya açar.

    Okuma/yazma ikili dosyası oluşturur.

    Okuma/yazma ikili dosyasını ekler veya oluşturur.

    Yazmak için bir metin dosyası oluşturur.

    Bir metin dosyasına eklenir.

    Okumak için bir metin dosyasını açar.

    Okuma/yazma için bir metin dosyası oluşturur.

    Okumak/yazmak için bir metin dosyası açar veya oluşturur.

    Daha önce, veri girerken ve çıkarırken standart akışlarla (klavye ve monitör) çalışıyorduk. Şimdi C dilinin dosyalardan veri almayı ve oraya yazmayı nasıl uyguladığına bakalım. Bu işlemleri gerçekleştirmeden önce dosyayı açmanız ve ona erişmeniz gerekir.

    C programlama dilinde, bir dosyaya yönelik işaretçi FILE türündedir ve bildirimi şu şekilde görünür:
    DOSYA *dosyam;

    Öte yandan, fopen() işlevi okuma ("r"), yazma ("w") veya ekleme ("a") modunda ilk argümanı olarak belirtilen adresteki bir dosyayı açar ve ona bir işaretçi döndürür programa. Bu nedenle, bir dosyayı açma ve onu programa bağlama işlemi şuna benzer:
    dosyam = fopen("merhaba.txt", "r");

    Bir dosyaya veri okurken veya dosyaya veri yazarken, ona bir dosya işaretçisi (bu durumda dosyam) aracılığıyla erişilir.

    Herhangi bir nedenden dolayı (belirtilen adreste dosya yoksa, ona erişim reddedildiyse), fopen() işlevi dosyayı açamıyorsa NULL değerini döndürür. Gerçek programlarda, neredeyse her zaman if dalındaki dosya açma hatasını ele alırlar, ancak biz bunu daha fazla atlayacağız.

    Fopen() işlev bildirimi stdio.h başlık dosyasında bulunur, dolayısıyla dahil edilmesi gerekir. Ayrıca stdio.h'de FILE yapı tipi bildirildi.

    Bir dosyayla çalışma bittikten sonra, arabelleği verilerden kurtarmak için ve diğer nedenlerden dolayı dosyayı kapatmak gelenekseldir. Bu, özellikle programın dosyayla çalıştıktan sonra çalışmaya devam etmesi durumunda önemlidir. Harici bir dosya ile ona programdan gelen bir işaretçi arasındaki bağlantıyı kesmek, fclose() işlevi kullanılarak yapılır. Dosyaya bir işaretçi parametre olarak iletilir:
    fclose(dosyam);

    Programda birden fazla dosya açılabilmektedir. Bu durumda her dosyanın kendi dosya işaretçisiyle ilişkilendirilmesi gerekir. Ancak program önce bir dosyayla çalışıp ardından onu kapatırsa işaretçi ikinci bir dosyayı açmak için kullanılabilir.

    Bir metin dosyasından okuma ve metin dosyasına yazma

    fscanf()

    fscanf() işlevi, anlam olarak scanf() işlevine benzer, ancak ondan farklı olarak, standart girdi yerine bir dosyadan biçimlendirilmiş girdi sağlar. fscanf() işlevi parametreleri alır: dosya işaretçisi, biçim dizesi, veri yazmak için bellek alanlarının adresleri:
    fscanf(dosyam, "%s%d", str, &a);

    Başarıyla okunan veri veya EOF sayısını döndürür. Boşluklar ve yeni satır karakterleri veri sınırlayıcı olarak sayılır.

    Diyelim ki nesnelerin aşağıdaki tanımını içeren bir dosyamız var:

    Elma 10 23,4 Muz 5 25,0 Ekmek 1 10,3

    #katmak main () ( FILE * file; struct food ( karakter adı[ 20 ] ; unsigned adet; float fiyat; ) ; struct food shop[ 10 ] ; char i= 0 ; file = fopen ( "fscanf.txt" , "r" ) ; while (fscanf (file, "%s%u%f" , shop[ i].name , & (shop[ i].qty ) , & (shop[ i].price ) ) != EOF) ( printf ("%s %u %.2f \N", mağaza[i].adı, mağaza[i].adet, mağaza[i].fiyat) ; i++; ))

    Bu durumda bir yapı ve bir dizi yapı bildirilir. Dosyadaki her satır dizinin bir öğesine karşılık gelir; dizi öğesi, bir dize ve iki sayısal alan içeren bir yapıdır. Döngü yineleme başına bir satır okur. Dosya sonuyla karşılaşıldığında fscanf(), EOF değerini döndürür ve döngü sona erer.

    fgets()

    fgets() işlevi, get() işlevine benzer ve bir dosyadan satır satır giriş gerçekleştirir. fgets()'a yapılan bir çağrı bir satır okuyacaktır. Bu durumda satırın tamamını okuyamazsınız, yalnızca bir kısmını baştan okuyabilirsiniz. fgets() parametreleri şuna benzer:
    fgets (karakter_dizisi, okunan_karakterlerin_sayısı, dosyaya_işaretçi)

    Örneğin:
    fgets(str, 50, dosyam)

    Bu işlev çağrısı, dosyam işaretçisiyle ilişkili dosyadan, işlevin aynı zamanda bir dizide depolayacağı "\n" karakteri de dahil olmak üzere uzunluğu 50 karakterden azsa bir tam satırlık metin okuyacaktır. str dizisinin son (50.) elemanı fgets() tarafından eklenen "\0" karakteri olacaktır. Eğer string daha uzunsa fonksiyon 49 karakter okuyacak ve sonuna "\0" yazacaktır. Bu durumda okuma satırında "\n" bulunmayacak.

    #katmak #define N 80 main () ( FILE * file; char arr[ N] ; file = fopen ("fscanf.txt" , "r" ) ; while (fgets (dizi, N, dosya) != NULL) printf (" %s", arr) ; printf (" \N") ); fclose(dosya); )

    Bu programda öncekinden farklı olarak veriler arr dizisine satır satır okunur. Bir sonraki satır okunduğunda önceki satır kaybolur. fgets() işlevi, sonraki satırı okuyamazsa NULL değerini döndürür.

    getc() veya fgetc()

    getc() veya fgetc() işlevi (her ikisi de çalışır), bir dosyadan sonraki tek karakteri almanızı sağlar.

    while ((dizi[ i] = fgetc (dosya) ) != EOF) ( if (dizi[ i] == " \N") (dizi[i] = " \0 " ; printf("%s \N", arr); ben = 0; ) aksi halde i++; )arr[i] = " \0 " ; printf("%s \N", arr);

    Örnek kod, ekranda bir dosyadaki verileri görüntüler.

    Bir metin dosyasına yazma

    Tıpkı girdi gibi, bir dosyanın çıktısı da farklı olabilir.

    • Biçimlendirilmiş çıktı. fprintf işlevi (dosya_index, biçim_dizgesi, değişkenler) .
    • Satır bazında çıktı. İşlev fputs(string, file_pointer) .
    • Karakter karakter çıktısı. fputc() veya putc(symbol, file_pointer) işlevi.

    Aşağıda, bir dosyaya veri çıkışı sağlamak için üç yöntem kullanan kod örnekleri verilmiştir.

    Dosyanın her satırına bir yapıya ait alanların yazılması:

    dosya = fopen ("fprintf.txt", "w"); while (scanf ("%s%u%f" , shop[ i].name , & (shop[ i].qty ) , & (shop[ i].price ) ) != EOF) ( fprintf (file, " %s %u %.2f \N", mağaza[i].adı, mağaza[i].adet, mağaza[i].fiyat) ; i++; )

    Bir dosyaya satır satır çıktı (fputs(), puts()'un kendisinden farklı olarak satırın sonuna “\n” yerleştirmez):

    while (gets (arr) != NULL) ( fputs (dizi, dosya); fputs (" \N", dosya); )

    Karakter karakter çıktı örneği:

    while ((i = getchar () ) != EOF) putc (i, dosya) ;

    İkili dosyadan okuma ve ikili dosyaya yazma

    Bir dosyayla karakter dizisi olarak değil, bayt dizisi olarak çalışabilirsiniz. Prensip olarak metin olmayan dosyalarla başka şekilde çalışmak mümkün değildir. Ancak metin dosyalarını bu şekilde okuyabilir ve yazabilirsiniz. Bir dosyaya erişmenin bu yönteminin avantajı okuma-yazma hızıdır: tek erişimde önemli miktarda bilgi bloğu okunabilir/yazılabilir.

    Bir dosyayı ikili erişim için açarken fopen()'ın ikinci parametresi "rb" veya "wb" dizisidir.

    İkili dosyalarla çalışma konusu oldukça karmaşıktır ve onu incelemek ayrı bir ders gerektirir. Burada sadece bayt akışı olarak kabul edilen bir dosyaya okuma ve yazma fonksiyonlarının özellikleri not edilecektir.

    fread() ve fwrite() işlevleri parametre olarak alır:

    1. Verinin yazıldığı veya okunduğu hafıza alanının adresi,
    2. herhangi bir türün boyutu,
    3. Belirtilen boyutta okunan veri miktarı,
    4. dosya indeksi.

    Bu işlevler başarıyla okunan veya yazılan veri sayısını döndürür. Onlar. 50 veri öğesinin okunmasını “sipariş edebilirsiniz” ancak yalnızca 10 tanesini alabilirsiniz. Hiçbir hata olmayacaktır.

    fread() ve fwrite() işlevlerinin kullanımına bir örnek:

    #katmak #katmak main () ( FILE * file; char raf1[ 50 ], raf2[ 100 ] ; int n, m; dosya = fopen ("shelf1.txt" , "rb" ) ; n= fread (shelf1, sizeof (char ) , 50 , dosya) ; fclose (dosya) ; dosya = fopen ("shelf2.txt", "rb" ) ; m= fread (shelf2, sizeof (char) , 50, dosya) ; fclose (dosya) ; raf1[ n] = " \0 " ; raf2[m] = " \N"; raf2[ m+ 1 ] = " \0 " ; dosya = fopen ("shop.txt", "wb") ; fwrite (strcat (shelf2, raf1) , sizeof (char ) , n+ m, dosya) ; fclose(dosya); )

    Burada ilk dosyadan 50 karakter okunmaya çalışılıyor. n gerçekte okunan karakter sayısını saklar. N'nin değeri 50 veya daha az olabilir. Veriler bir sıraya yerleştirilir. İkinci dosyada da aynı şey oluyor. Daha sonra ilk satır ikinciye eklenir ve veriler üçüncü dosyaya aktarılır.

    Problem çözme

    1. Kullanıcıdan bir metin dosyasının adını (adresini) soran, ardından dosyayı açan ve içindeki karakter ve satır sayısını sayan bir program yazın.
    2. Başka bir dosyadan alınan ve yazmadan önce bir şekilde değiştirilen verileri bir dosyaya yazan bir program yazın. Bir dosyadan elde edilen her veri satırının bir yapıya uyması gerekir.

    Etiketler: Metin dosyaları, fopen, fclose, feof, setbuf, setvbuf, fflush, fgetc, fprintf, fscanf, fgets, arabelleğe alınmış akış, arabelleğe alınmamış akış.

    Metin dosyalarıyla çalışma

    Bir metin dosyasıyla çalışmak konsolla çalışmaya benzer: biçimlendirilmiş giriş işlevlerini kullanarak verileri bir dosyaya kaydederiz, biçimlendirilmiş çıktı işlevlerini kullanarak bir dosyadan verileri okuruz. Daha sonra bakacağımız birçok nüans var. Yapılması gereken başlıca işlemler şunlardır

    • 1. Erişilebilmesi için dosyayı açın. Buna göre okuma, yazma, okuma ve yazma, yeniden yazma veya dosyanın sonuna kadar yazma vb. için açabilirsiniz. Bir dosyayı açtığınızda birçok hata da meydana gelebilir; dosya mevcut olmayabilir, yanlış dosya türü olabilir, dosyayla çalışma izniniz olmayabilir, vb. Bütün bunlar dikkate alınmalıdır.
    • 2. Doğrudan dosyayla çalışma - yazma ve okuma. Burada ayrıca rastgele erişim belleğiyle değil, kendi özelliklerini ekleyen arabelleğe alınmış bir akışla çalıştığımızı hatırlamamız gerekir.
    • 3. Dosyayı kapatın. Dosya programın dışında bir kaynak olduğundan kapatılmadığı takdirde muhtemelen program kapatıldıktan sonra bile bellekte takılmaya devam edecektir (örneğin, açık bir dosyayı silmek veya değişiklik yapmak mümkün olmayacaktır), vesaire.). Ek olarak, bazen erişim modunu değiştirmek için dosyayı kapatmak değil, "yeniden açmak" gerekir.

    Ek olarak, dosyanın içeriğine erişmemize gerek olmadığında bir dizi görev vardır: yeniden adlandırma, taşıma, kopyalama vb. Ne yazık ki C standardı bu ihtiyaçlara yönelik işlevlerin bir tanımını içermemektedir. Bunlar elbette derleyici uygulamalarının her biri için mevcuttur. Bir dizinin (klasör, dizin) içeriğini okumak aynı zamanda bir dosyaya erişmektir, çünkü klasörün kendisi meta bilgi içeren bir dosyadır.

    Bazen bazı yardımcı işlemlerin yapılması gerekebilir: dosyada istenen konuma gidin, geçerli konumu hatırlayın, dosyanın uzunluğunu belirleyin, vb.

    Bir dosyayla çalışmak için bir FILE nesnesine ihtiyacınız vardır. Bu nesne, arabelleğe yönelik bir işaretçi, bir dosya konumu göstergesi ve durum göstergeleri dahil olmak üzere, dosya akışının tanımlayıcısını ve onu yönetmek için gereken bilgileri saklar.

    FILE nesnesinin kendisi bir yapıdır ancak alanlarına erişilmemelidir. Taşınabilir programın dosyayı, dosya akışına erişime izin veren soyut bir nesne olarak ele alması gerekir.

    FILE türündeki bir nesne için belleğin oluşturulması ve tahsis edilmesi, fopen veya tmpfile işlevi kullanılarak gerçekleştirilir (başkaları da vardır, ancak yalnızca bunlara odaklanacağız).

    Fopen işlevi bir dosyayı açar. İki argüman alır; dosya adresini içeren bir dize ve dosya erişim modunu içeren bir dize. Dosya adı mutlak veya göreceli olabilir. fopen, dosyaya daha fazla erişmek için kullanılabilecek bir FILE nesnesine bir işaretçi döndürür.

    DOSYA* fopen(const char* dosya adı, const char* modu);

    Örnek olarak bir dosya açalım ve içine Merhaba Dünya yazalım.

    #katmak #katmak #katmak void main() ( //Dosya değişkenini kullanarak dosyaya erişeceğiz FILE *file; //Yazma izinlerine sahip bir metin dosyası açın file = fopen("C:/c/test.txt", "w+t") ; //Dosyaya yaz fprintf(dosya, "Merhaba, Dünya!"); //Dosyayı kapat fclose(dosya); getch(); )

    Fopen işlevinin kendisi nesne için bellek ayırır; temizleme işlemi fclose işlevi tarafından gerçekleştirilir. Dosyayı kapatmak gerekiyor, kendi kendine kapanmayacaktır.

    Fopen işlevi bir dosyayı metin veya ikili modda açabilir. Varsayılan metindir. Erişim modu aşağıdaki gibi olabilir

    Dosya erişim seçenekleri.
    Tip Tanım
    R Okuma. Dosya mevcut olmalıdır.
    w Yeni bir dosya yazın. Aynı adda bir dosya zaten mevcutsa içeriği kaybolur.
    A Dosyanın sonuna yazın. Konumlandırma işlemleri (fseek, fsetpos, frewind) göz ardı edilir. Dosya mevcut değilse oluşturulur.
    r+ Okumak ve güncellemek. Hem okuyabilir hem de yazabilirsiniz. Dosya mevcut olmalıdır.
    w+ Kaydetme ve güncelleme. Yeni bir dosya oluşturulur. Aynı adda bir dosya zaten mevcutsa içeriği kaybolur. Hem yazabilir hem de okuyabilirsiniz.
    a+ Gönderiyi sonlandırın ve güncelleyin. Konumlandırma işlemleri salt okunurdur ve yazma işlemleri için göz ardı edilir. Dosya mevcut değilse yeni bir tane oluşturulacaktır.

    Dosyayı ikili modda açmak gerekiyorsa satırın sonuna b harfi eklenir, örneğin “rb”, “wb”, “ab” veya karma mod için “ab+”, “ wb+”, “ab+”. B yerine t harfini ekleyebilirsiniz, ardından dosya metin modunda açılacaktır. Uygulamaya bağlıdır. Yeni C standardında (2011), x harfi, dosya zaten mevcutsa fopen'in başarısız olması gerektiği anlamına gelir. Eski programımıza ek yapalım: dosyayı yeniden açın ve orada yazdıklarımızı düşünün.

    #katmak #katmak #katmak void main() ( FILE *file; char buffer; file = fopen("C:/c/test.txt", "w"); fprintf(file, "Merhaba, Dünya!"); fclose(file); file = fopen("C:/c/test.txt", "r"); fgets(tampon, 127, dosya); printf("%s", arabellek); fclose(dosya); getch(); )

    fgets işlevi yerine fscanf kullanabilirsiniz, ancak bunun yalnızca ilk boşluğa kadar olan satırı okuyabildiğini unutmamanız gerekir.
    fscanf(dosya, "%127s", arabellek);

    Ayrıca, bir dosyayı açıp kapatmak yerine, dosyayı yeni erişim haklarıyla "yeniden açan" freopen işlevini kullanabilirsiniz.

    #katmak #katmak #katmak void main() ( FILE *file; char buffer; file = fopen("C:/c/test.txt", "w"); fprintf(file, "Merhaba, Dünya!"); freopen("C:/ c/test.txt", "r", dosya); fgets(tampon, 127, dosya); printf("%s", arabellek); fclose(dosya); getch(); )

    fprintf ve fscanf işlevleri, çıktı alacakları veya veri okuyacakları DOSYA'ya yönelik bir işaretçiyi ilk argüman olarak almaları bakımından printf ve scanf işlevlerinden farklıdır. Printf ve scanf işlevlerinin kolayca fprintf ve fscanf işlevleriyle değiştirilebileceğini hemen eklemeye değer. İşletim sisteminde (en yaygın ve yeterli işletim sistemlerini düşünüyoruz) üç standart akış vardır: standart çıkış akışı stdout, standart giriş akışı stdin ve standart hata çıkış akışı stderr. Uygulama başlatıldığında otomatik olarak açılırlar ve konsolla ilişkilendirilirler. Örnek

    #katmak #katmak #katmak void main() ( int a, b; fprintf(stdout, "İki sayı girin\n"); fscanf(stdin, "%d", &a); fscanf(stdin, "%d", &b); if (b == 0) ( fprintf(stderr, "Hata: sıfıra bölme"); ) else ( fprintf(stdout, "%.3f", (float) a / (float) b); ) getch(); )

    Dosya açılırken hata oluştu

    Fopen işlev çağrısı başarısız olursa NULL değerini döndürür. Dosyalarla çalışırken hatalar oldukça sık meydana gelir, bu nedenle bir dosyayı her açtığımızda işin sonucunu kontrol etmemiz gerekir.

    #katmak #katmak #katmak #define HATA_AÇIK_DOSYA -3 void main() ( FILE *file; char buffer; file = fopen("C:/c/test.txt", "w"); if (file == NULL) ( printf("Açılışta hata oluştu) dosya"); getch(); çıkış(ERROR_OPEN_FILE); ) fprintf(dosya, "Merhaba, Dünya!"); freopen("C:/c/test.txt", "r", dosya); if (dosya = = NULL) ( printf("Dosya açılırken hata"); getch(); çıkış(ERROR_OPEN_FILE); ) fgets(buffer, 127, file); printf("%s", buffer); fclose(file); getch() ;)

    Sorun aynı anda birden fazla dosya açıldığında ortaya çıkıyor: eğer bunlardan biri açılamıyorsa geri kalanının da kapatılması gerekiyor

    DOSYA *girişDosyası, *çıkışDosyası; imzasız m, n; imzasız i, j; inputFile = fopen(INPUT_FILE, READ_ONLY); if (inputFile == NULL) ( printf("%s dosyası açılırken hata oluştu", INPUT_FILE); getch(); çıkış(3); ) çıktıFile = fopen(OUTPUT_FILE, WRITE_ONLY); if (outputFile == NULL) ( printf("%s dosyası açılırken hata oluştu", OUTPUT_FILE); getch(); if (inputFile != NULL) ( fclose(inputFile); ) çıkış(4); ) ...

    Basit durumlarda, önceki kod parçasında olduğu gibi doğrudan hareket edebilirsiniz. Daha karmaşık durumlarda, RAII'yi C++'tan değiştiren yöntemler kullanılır: sarmalayıcılar veya derleyici özellikleri (GCC'de temizleme), vb.

    Veri Arabelleğe Alma

    Daha önce de belirttiğimiz gibi, verinin çıktısını aldığımızda, bu veri ilk olarak bir ara belleğe yerleştirilir. Tampon temizlendi

    • 1) Doluysa
    • 2) Akış kapalıysa
    • 3) Tamponun temizlenmesi gerektiğini açıkça belirtirsek (burada da istisnalar vardır :)).
    • 4) Programın başarıyla tamamlanması durumunda da işaret kaldırılır. Aynı zamanda tüm dosyalar kapatılır. Bir çalışma zamanı hatası durumunda bu gerçekleşmeyebilir.

    fflush(File *) işlevini çağırarak ara belleğin boşaltılmasını zorlayabilirsiniz. İki örneğe bakalım - temizlemeli ve temizlemesiz.

    #katmak #katmak #katmak void main() ( FILE *file; char c; file = fopen("C:/c/test.txt", "w"); do ( c = getch(); fprintf(file, "%c", c) ); fprintf(stdout, "%c", c); //fflush(dosya); ) while(c != "q"); fclose(dosya); getch(); )

    Fflush çağrısının açıklamasını kaldırın. Çalışma zamanında metin dosyasını açın ve davranışa bakın.

    Kendi boyutunuzu ayarlayarak kendinize bir dosya arabelleği atayabilirsiniz. Bu fonksiyon kullanılarak yapılır

    Void setbuf(DOSYA * akışı, karakter * arabellek);

    bu zaten açık olan bir DOSYA'yı ve yeni bir ara belleğe işaret eden bir işaretçiyi alır. Yeni arabelleğin boyutu BUFSIZ'den az olmamalıdır (örneğin, geçerli iş istasyonunda BUFSIZ 512 bayttır). NULL'u arabellek olarak iletirseniz akış arabelleğe alınmaz hale gelir. Fonksiyonu da kullanabilirsiniz

    Int setvbuf(DOSYA * akış, karakter * arabellek, int modu, size_t boyut);

    bu, isteğe bağlı boyuttaki bir arabelleği kabul eder. Mod aşağıdaki değerleri alabilir

    • _IOFBF- tam tamponlama. Dosya dolduğunda veri yazılır. Okuma sırasında, bir giriş işlemi istendiğinde arabellek dolu kabul edilir ve arabellek boştur.
    • _IOLBF- doğrusal tamponlama. Dosya dolduğunda veya yeni satır karakteriyle karşılaşıldığında veri yazılır. Okuma sırasında, bir giriş işlemi istendiğinde arabellek yeni satır karakterine kadar doldurulur ve arabellek boştur.
    • _IONBF– ara belleğe alma yok. Bu durumda boyut ve arabellek parametreleri dikkate alınmaz.
    Başarılı olursa işlev 0 değerini döndürür.

    Örnek: Kendi tamponumuzu ayarlayalım ve bir dosyadan okumanın nasıl yapıldığını görelim. Dosyanın kısa olmasına izin verin (Merhaba Dünya!) Gibi bir şey olsun ve onu karakter karakter okuyalım.

    #katmak #katmak #katmak void main() ( FILE *input = NULL; char c; char buffer = (0); input = fopen("D:/c/text.txt", "rt"); setbuf(input, buffer); while ( !feof(giriş)) ( c = fgetc(giriş); printf("%c\n", c); printf("%s\n", tampon); _getch(); ) fclose(giriş); )

    Verilerin zaten arabellekte olduğu görülebilir. Karakter karakter okuma arabellekten yapılır.

    feof

    int feof(DOSYA * akışı); dosyanın sonuna ulaşılırsa true değerini döndürür. İşlev, dosyanın tamamını baştan sona gözden geçirmeniz gerektiğinde kullanışlıdır. Metin içeriği text.txt olan bir dosya olsun. Dosyayı karakter karakter okuyup ekranda gösteriyoruz.

    #katmak #katmak #katmak void main() ( FILE *input = NULL; char c; input = fopen("D:/c/text.txt", "rt"); if (input == NULL) ( printf("Dosya açılırken hata") ; _getch(); çıkış(0); ) while (!feof(giriş)) ( c = fgetc(giriş); fprintf(stdout, "%c", c); ) fclose(giriş); _getch(); )

    Her şey yoluna girecek ama feof fonksiyonu doğru çalışmıyor... Bunun nedeni “dosya sonu” kavramının tanımlanmamış olmasıdır. Feof kullanırken sıklıkla oluşan bir hata, okunan son verinin iki kez yazdırılmasıdır. Bunun nedeni, verinin giriş arabelleğine yazılması, son okumanın hatalı gerçekleşmesi ve fonksiyonun eski okunan değeri döndürmesidir.

    #katmak #katmak #katmak void main() ( FILE *input = NULL; char c; input = fopen("D:/c/text.txt", "rt"); if (input == NULL) ( printf("Dosya açılırken hata") ; _getch(); çıkış(0); ) while (!feof(giriş)) ( fscanf(giriş, "%c", &c); fprintf(stdout, "%c", c); ) fclose(giriş); _getch(); )

    Bu örnek başarısız olacak (büyük olasılıkla) ve dosyanın son karakterini iki kez yazdıracaktır.

    Çözüm feof kullanmamaktır. Örneğin, toplam kayıt sayısını saklayın veya fscanf vb. fonksiyonların genellikle doğru okunan ve eşleşen değerlerin sayısını döndürdüğü gerçeğini kullanın.

    #katmak #katmak #katmak void main() ( FILE *input = NULL; char c; input = fopen("D:/c/text.txt", "rt"); if (input == NULL) ( printf("Dosya açılırken hata") ; _getch(); çıkış(0); ) while (fscanf(giriş, "%c", &c) == 1) ( fprintf(stdout, "%c", c); ) fclose(giriş); _getch() ;)

    Örnekler

    1. Bir dosya iki sayı içerir - dizinin boyutları. İkinci dosyayı bir dizi rastgele sayıyla dolduralım.

    #katmak #katmak #katmak #katmak //Dosya adları ve izinler #define INPUT_FILE "D:/c/input.txt" #define OUTPUT_FILE "D:/c/output.txt" #define READ_ONLY "r" #define WRITE_ONLY "w" //Dizi için maksimum değer boyut #define MAX_DIMENSION 100 //Dosyayı açarken hata #define ERROR_OPEN_FILE -3 void main() ( FILE *inputFile, *outputFile; unsigned m, n; unsigned i, j; inputFile = fopen(INPUT_FILE, READ_ONLY); if ( inputFile == NULL) ( printf("%s dosyası açılırken hata oluştu", INPUT_FILE); getch(); çıkış(ERROR_OPEN_FILE); ) OutputFile = fopen(OUTPUT_FILE, WRITE_ONLY); if (outputFile == NULL) ( printf("Hata %s dosyası açılıyor", OUTPUT_FILE); getch(); //Eğer dosya okumak için açılabiliyorsa, o zaman kapatılması gerekir if (inputFile != NULL) ( fclose(inputFile); ) çıkış(ERROR_OPEN_FILE); ) fscanf (inputFile, "%ud %ud", &m, &n); if (m > MAX_DIMENSION) ( m = MAX_DIMENSION; ) if (n > MAX_DIMENSION) ( n = MAX_DIMENSION; ) srand(time(NULL)); for (i = 0; ben< n; i++) { for (j = 0; j < m; j++) { fprintf(outputFile, "%8d ", rand()); } fprintf(outputFile, "\n"); } //Закрываем файлы fclose(inputFile); fclose(outputFile); }

    2. Kullanıcı dosyayı kopyalar ve önce çalışma modunu seçer: dosya konsola çıkarılabilir veya yeni bir dosyaya kopyalanabilir.

    #katmak #katmak #katmak #define ERROR_FILE_OPEN -3 void main() ( FILE *origin = NULL; FILE *output = NULL; char dosya adı; int mode; printf("Dosya adını girin: "); scanf("%1023s", dosya adı); Origin = fopen (dosya adı, "r"); if (origin == NULL) ( printf("%s dosyası açılırken hata oluştu", dosya adı); getch(); çıkış(ERROR_FILE_OPEN); ) printf("modu girin: "); scanf( "%d", &mode); if (mode == 1) ( printf("Dosya adını girin: "); scanf("%1023s", dosya adı); çıktı = fopen(dosya adı, "w"); if (çıkış = = NULL) ( printf("%s dosyası açılırken hata oluştu", dosya adı); getch(); fclose(origin); çıkış(ERROR_FILE_OPEN); ) ) else ( çıktı = stdout; ) while (!feof(origin)) ( fprintf (çıkış, "%c", fgetc(origin)); ) fclose(origin); fclose(output); getch(); )

    3. Kullanıcı konsoldan veri girer ve esc tuşuna basılana kadar bir dosyaya yazılır. Programı inceleyin ve görün. geri tuşuna bastığınızda nasıl davranır: dosyaya ne çıktı ve konsola ne çıktı.

    #katmak #katmak #katmak #define ERROR_FILE_OPEN -3 void main() ( FILE *output = NULL; char c; çıktı = fopen("D:/c/test_output.txt", "w+t"); if (output == NULL) ( printf ("Dosya açılırken hata"); _getch(); çıkış(ERROR_FILE_OPEN); ) for (;;) ( c = _getch(); if (c == 27) ( break; ) fputc(c, çıktı); fputc( c, stdout); ) fclose(çıkış); )

    4. Dosya tamsayılar içeriyor. Bunların maksimumunu bulun. Fscanf fonksiyonunun doğru okunan ve eşleşen nesnelerin sayısını döndürmesinin avantajından yararlanalım. Her seferinde 1 rakamı döndürülmelidir.

    #katmak #katmak #katmak #define ERROR_FILE_OPEN -3 void main() ( FILE *input = NULL; int num, maxn, hasRead; input = fopen("D:/c/input.txt", "r"); if (input == NULL) ( printf("Dosya açılırken hata"); _getch(); çıkış(ERROR_FILE_OPEN); ) maxn = INT_MIN; hasRead = 1; while (hasRead == 1) ( hasRead = fscanf(input, "%d", &num); if (hasRead != 1) ( devam et; ) if (num >

    Diğer bir çözüm ise dosyanın sonuna ulaşana kadar sayıları okumaktır.

    #katmak #katmak #katmak #katmak #define ERROR_FILE_OPEN -3 void main() ( FILE *input = NULL; int num, maxn, hasRead; input = fopen("D:/c/input.txt", "r"); if (input == NULL) ( printf("Dosya açılırken hata"); _getch(); çıkış(ERROR_FILE_OPEN); ) maxn = INT_MIN; while (!feof(input)) ( fscanf(input, "%d", &num); if (num > maxn) ) ( maxn = sayı; ) ) printf("max sayı = %d", maxn); fclose(input); _getch(); )

    5. Dosya şu kelimeleri içerir: Birkaç satır halinde Rusça kelime, tablolama, İngilizce kelime. Kullanıcı İngilizce bir kelime girer, Rusça olanı çıkarmak gerekir.

    Çeviri dosyası şuna benzer

    Güneş Güneş
    kurşun kalem tükenmez kalem
    tükenmez kalem kalem
    kapı kapısı
    Windows penceresi
    sandalye sandalye
    koltuk

    ve cp866 kodlamasıyla (OEM 866) kaydedildi. Önemli: Son kelime çifti de satır beslemeyle bitiyor.

    Algoritma şu şekildedir: bir dosyadan bir satır okuruz, satırda bir sekme karakteri buluruz, sekme karakterini sıfırla değiştiririz, arabellekten bir Rusça kelimeyi kopyalarız, arabellekten bir İngilizce kelimeyi kopyalarız, eşitliği kontrol ederiz.

    #katmak #katmak #katmak #katmak #define ERROR_FILE_OPEN -3 void main() ( FILE *input = NULL; char buffer; char enWord; char ruWord; char usrWord; unsigned index; int uzunluk; int wasFound; input = fopen("D:/c/input.txt) ", "r"); if (input == NULL) ( printf("Dosya açılırken hata"); _getch(); çıkış(ERROR_FILE_OPEN); ) printf("sözcüğü girin: "); fgets(usrWord, 127, stdin ); wasFound = 0; while (!feof(input)) ( fgets(buffer, 511, input); uzunluk = strlen(buffer); for (index = 0; indeks< length; index++) { if (buffer == "\t") { buffer = "\0"; break; } } strcpy(ruWord, buffer); strcpy(enWord, &buffer); if (!strcmp(enWord, usrWord)) { wasFound = 1; break; } } if (wasFound) { printf("%s", ruWord); } else { printf("Word not found"); } fclose(input); _getch(); }

    6. Dosyadaki satır sayısını sayın. EOF karakteriyle karşılaşıncaya kadar "\n" karakter sayısını sayarak dosyayı karakter karakter okuyacağız. EOF, girişin tamamlandığını ve okunacak veri kalmadığını belirten özel bir karakterdir. Hata durumunda fonksiyon negatif bir değer döndürür.
    NOT: EOF int türündedir, dolayısıyla karakterleri okumak için int kullanmanız gerekir. Ayrıca EOF değeri standart tarafından tanımlanmamıştır.

    #define _CRT_SECURE_NO_WARNINGS #include #katmak #katmak int cntLines(const char *dosyaadı) ( intlines = 0; int herhangi biri; //herhangi biri int türündedir çünkü EOF int türündedir! FILE *f = fopen(dosyaadı, "r"); if (f == NULL ) ( return -1; ) do ( any = fgetc(f); //printf("%c", herhangi biri);//debug if (any == "\n") ( satırlar++; ) ) while(any ! = EOF); ​​fclose(f); dönüş satırları; ) void main() ( printf("%d\n", cntLines("C:/c/file.txt")); _getch(); )

    Ru-Cyrl 18-öğretici Sypachev S.S. 1989-04-14 [e-posta korumalı] Stepan Sypaçevöğrenciler

    Hala net değil mi? – posta kutusuna sorular yazın