C-keele fprintf funktsioon: täielik juhend koos näidete ja parimate praktikatega

目次

1. Mis on fprintf funktsioon

fprintfi põhialused

fprintf funktsioon on üks standardseid sisend-/väljundfunktsioone, mida kasutatakse C-keeles. Selle funktsiooni peamine roll on „väljastada vormindatud stringe”. fprintf abil saab andmeid määratud vormingu järgi kujundada ja kirjutada määratud väljundisse.

Tavaliselt kasutatakse fprintf-i järgmistes olukordades:

  • Logifailide loomine: Programmi käivitamisajaloo või veateabe salvestamine.
  • Vormindatud andmete salvestamine: Täisarvude või stringide salvestamine kindlas formaadis faili.
  • Silumisinfo väljastamine: Arenduse ajal programmi töö jälgimiseks mõeldud andmete väljastamine.

fprintfi põhisüntaks

int fprintf(FILE *stream, const char *format, ...);

Süntaksi osad

  • FILE *stream: Määrab väljundi sihtkoha. Näiteks standardväljund (stdout) või fail (fopen-iga avatud fail).
  • const char *format: Vormingustring, mis määrab, kuidas andmeid kuvatakse. Sama vorming nagu printf-funktsioonis.
  • ...: Muutuv arv argumente, mis määravad väljundandmed.

Tagastusväärtus on edukalt kirjutatud märkide arv (positiivne täisarv). Kui ilmneb viga, tagastatakse -1.

Võrdlus teiste funktsioonidega

fprintf on sarnane funktsioonidega printf ja sprintf. Siin on nende erinevused:

Erinevus printfist

printf väljastab andmed standardväljundisse (tavaliselt konsooli). fprintf võimaldab määrata väljundi sihtkoha, pakkudes suuremat paindlikkust.

Näide: printf kasutamine

printf("Hello, World!\n");

Tulemus kuvatakse alati konsoolis.

Näide: fprintf kasutamine

FILE *file = fopen("output.txt", "w");
fprintf(file, "Hello, World!\n");
fclose(file);

Selles näites kirjutatakse väljund määratud faili (output.txt).

Erinevus sprintfist

sprintf erineb selle poolest, et väljundiks on „string” ehk mälus asuv puhver.

Näide: sprintf kasutamine

char buffer[50];
sprintf(buffer, "The result is %d", 42);

Selles näites kirjutatakse string "The result is 42" muutujasse buffer.

Kokkuvõte

  • fprintf on kasulik funktsioon, mis võimaldab määrata väljundi sihtkoha (fail, standardväljund jne).
  • Kombineerides erinevaid funktsioone (printf, sprintf) saab tõsta programmi efektiivsust ja loetavust.

2. fprintfi põhiline kasutamine

Süntaks ja põhiargumentide selgitus

fprintf funktsioon on paindlik tööriist vormindatud andmete väljastamiseks. Selle põhisüntaks on järgmine:

int fprintf(FILE *stream, const char *format, ...);

Allpool on toodud argumentide üksikasjad.

  1. FILE *stream
  • Määrab väljundi sihtkoha.
  • Tüüpilised valikud:
    • Standardväljund (stdout)
    • Standardne veaväljund (stderr)
    • Fail (fopen-iga avatud fail)
  1. const char *format
  • Määrab väljundi vormingu.
  • Vorminguspetsiifereid saab kasutada stringide, täisarvude, ujukoma arvude jne jaoks (nt %s, %d, %f).
  1. Muutuva pikkusega argumendid (…)
  • Annab andmed, mis vastavad vorminguspetsiiferitele.
  • Näide: kui vorming on "Name: %s, Age: %d", tuleb edasi anda vastavad väärtused nime ja vanuse jaoks.

Tagastusväärtus on edukalt kirjutatud märkide arv (positiivne täisarv). Kui ilmneb viga, tagastatakse -1.

Põhilised koodinäited

Järgmised näited näitavad, kuidas fprintf-i kasutada.

Väljund standardväljundisse

Kirjutab stringi vormindatult standardväljundisse (stdout).

#include <stdio.h>

int main() {
    fprintf(stdout, "Hello, %s! You have %d new messages.\n", "Alice", 5);
    return 0;
}

Väljund:

Hello, Alice! You have 5 new messages.

Selles näites on stdout selgesõnaliselt määratud väljundiks.

Väljund faili

fprintf abil saab kirjutada andmeid faili.

#include <stdio.h>

int main() {
    FILE *file = fopen("output.txt", "w"); // Avab faili kirjutamisrežiimis
    if (file == NULL) {
        fprintf(stderr, "Error opening file.\n");
        return 1;
    }

    fprintf(file, "Name: %s, Age: %d\n", "Bob", 30);
    fclose(file); // Sulgeb faili
    return 0;
}

output.txt sisu:

Name: Bob, Age: 30

Põhilised vorminguspetsiiferid

fprintf võimaldab kontrollida väljundi kuju vorminguspetsiiferite abil. Allpool on toodud mõned põhilised näited.

SpetsiiferSelgitusNäide
%dKümnendsüsteemi täisarv42
%fUjukoma arv3.141593
%sString"Hello"
%cÜksik märk'A'
%xKuueteistkümnendsüsteemi arv (väiketähed)0x2a
%oKaheksandsüsteemi arv052

Näide:

fprintf(stdout, "Integer: %d, Float: %.2f, String: %s\n", 10, 3.14, "Test");

Väljund:

Integer: 10, Float: 3.14, String: Test

3. fprintfi vormingu kasutamine

Laius (Minimum Width)

Kui määrata välja laiuse, täidetakse vasakpoolne ruum tühikutega, kui väljastatava stringi pikkus jääb alla määratud laiuse.

Näide:

fprintf(stdout, "|%10s|\n", "Hello");
fprintf(stdout, "|%10d|\n", 123);

Väljund:

|     Hello|
|       123|

Siin on laiuseks määratud 10. Kui sümbolite arv on väiksem, lisatakse vasakule poole tühikud.


Täpsus (Precision)

Täpsusel on erinev tähendus sõltuvalt kasutusviisist:

  • Stringid (%s): maksimaalne väljastatavate märkide arv.
  • Ujukoma arvud (%f, %e, %g): komakohtade arv pärast koma.

Näide:

fprintf(stdout, "%.3f\n", 3.141592); // Ujukoma täpsus
fprintf(stdout, "%.5s\n", "Hello, World!"); // Stringi maksimaalne pikkus

Väljund:

3.142
Hello

Lipud (Flags)

Lippude abil saab kontrollida andmete paigutust ja vormingut.

LippSelgitusNäide
-Joondamine vasakule (vaikimisi paremale)|%-10s||Hello |
+Märgi kuvamine alati (ka positiivse arvu korral)%+d+42
0Täidab tühikud nullidega (kasutatakse laiuse määramisel)%05d00042
#Lisa eri vorming (16-nd või 8-nd süsteem)%#x0x2a
Lisab positiivse arvu ette tühiku% d 42

Näide:

fprintf(stdout, "|%-10s|%+05d|%#x|\n", "Left", 42, 42);

Väljund:

|Left      |+0042|0x2a|

Praktilised näited

Kombineerides laiust, täpsust ja lippe, saab fprintf-i abil luua hästi vormindatud tabeli kujulisi andmeid.

Tabelina väljastamine

Järgmises näites väljastatakse õpilaste hinded tabelina:

#include <stdio.h>

int main() {
    fprintf(stdout, "|%-10s|%5s|%5s|%5s|\n", "Name", "Math", "Eng", "Sci");
    fprintf(stdout, "|%-10s|%5d|%5d|%5d|\n", "Alice", 95, 88, 92);
    fprintf(stdout, "|%-10s|%5d|%5d|%5d|\n", "Bob", 82, 79, 85);
    return 0;
}

Väljund:

|Name      | Math|  Eng|  Sci|
|Alice     |   95|   88|   92|
|Bob       |   82|   79|   85|

Arvude vormindamine

Kindla formaadiga arvude väljastamine ühtse välimuse saavutamiseks.

Näide:

fprintf(stdout, "Price: $%8.2f\n", 1234.5);
fprintf(stdout, "Discount: %06d%%\n", 25);

Väljund:

Price: $ 1234.50
Discount: 000025%

Olulised märkused

  1. Vale vorminguspetsiifer
  • Kui vorminguspetsiifer ei sobi andmetüübi juurde, võib tekkida ootamatu väljund või viga.
  • Näide: stringi edastamine %d jaoks võib põhjustada määramata käitumise.
  1. Laiuse ja täpsuse liigne määramine
  • Kui määrata liiga suur laius, võib väljund muutuda liiga pikaks ja raisata ressursse.

Kokkuvõte

  • Laiuse, täpsuse ja lippude abil saab fprintf-i väljundit täpselt kontrollida.
  • Tabeliandmete ja arvude vormindamine muudab väljundi loetavamaks.
  • Oluline on tagada, et vorminguspetsiiferid ja andmetüübid vastaksid, et vältida vigu.

4. Failihaldus ja fprintf

Faili avamine (fopen)

Selleks, et fprintf abil faili kirjutada, tuleb fail esmalt avada. C-keeles kasutatakse selleks fopen funktsiooni.

fopeni põhisüntaks

FILE *fopen(const char *filename, const char *mode);
Argumentide selgitus
  • filename: avatava faili nimi või tee.
  • mode: määrab, kuidas faili avatakse.
  • "r": ainult lugemiseks
  • "w": ainult kirjutamiseks (olemasolev fail kirjutatakse üle)
  • "a": lisamine (kirjutatakse faili lõppu)
  • "rb"/"wb"/"ab": sama, kuid binaarrežiimis

Tagastusväärtus

  • Kui avamine õnnestub, tagastatakse FILE tüüpi pointer.
  • Kui avamine ebaõnnestub, tagastatakse NULL.

fopeni näide

#include <stdio.h>

int main() {
    FILE *file = fopen("example.txt", "w");
    if (file == NULL) {
        fprintf(stderr, "Error: Could not open file.\n");
        return 1;
    }

    fprintf(file, "Hello, World!\n");
    fclose(file);
    return 0;
}

See programm avab faili example.txt, kirjutab sinna teksti ja sulgeb faili.

Faili kirjutamine fprintf abil

fprintf võimaldab kirjutada vormindatud andmeid faili. Siin on mõned näited.

Põhiline faili kirjutamine

#include <stdio.h>

int main() {
    FILE *file = fopen("data.txt", "w");
    if (file == NULL) {
        fprintf(stderr, "Error: Could not open file.\n");
        return 1;
    }

    fprintf(file, "Name: %s, Age: %d\n", "Alice", 25);
    fprintf(file, "Name: %s, Age: %d\n", "Bob", 30);

    fclose(file);
    return 0;
}

data.txt sisu:

Name: Alice, Age: 25
Name: Bob, Age: 30

CSV-faili loomine

Näide CSV-andmete salvestamisest:

#include <stdio.h>

int main() {
    FILE *file = fopen("students.csv", "w");
    if (file == NULL) {
        fprintf(stderr, "Error: Could not open file.\n");
        return 1;
    }

    // Päis
    fprintf(file, "Name,Math,English,Science\n");

    // Andmed
    fprintf(file, "Alice,95,88,92\n");
    fprintf(file, "Bob,82,79,85\n");

    fclose(file);
    return 0;
}

students.csv sisu:

Name,Math,English,Science
Alice,95,88,92
Bob,82,79,85

Faili sulgemine (fclose)

Pärast faili kasutamist tuleb see sulgeda fclose funktsiooni abil. Kui faili ei suleta, võivad tekkida probleemid:

  • Andmeid ei pruugita täielikult salvestada.
  • Süsteemi ressursse kulutatakse asjatult.

fclose põhisüntaks

int fclose(FILE *stream);

Tagastusväärtus

  • Edu korral 0.
  • Tõrke korral EOF (faili lõpu märgis).

fclose näide

FILE *file = fopen("example.txt", "w");
if (file != NULL) {
    fprintf(file, "This is a test.\n");
    fclose(file);
}

Turvalise failihalduse soovitused

  1. Kontrolli faili pointerit
  • Kontrolli alati, kas fopen tagastas NULL.
  1. Ära unusta faili sulgeda
  • Iga avatud fail tuleb sulgeda fclose abil.
  1. Veaohje
  • Tuvasta ja käsitle vigu failitoimingute käigus.
  • Näiteks: kettaruumi puudus või õiguste probleemid.

Kokkuvõte

  • Fail tuleb avada fopen-iga ja sulgeda fclose-iga.
  • Õige režiimi ja vigade kontroll tagavad turvalise failihalduse.
  • fprintf abil saab salvestada CSV-formaadis või logisid.

5. Vigade käsitlemine

fprintfi tagastusväärtuse kasutamine vigade kontrolliks

Kontrollides fprintf funktsiooni tagastusväärtust saab tuvastada, kas kirjutamine õnnestus või mitte.

Tagastusväärtuse spetsifikatsioon

  • Eduka kirjutamise korral: tagastatakse kirjutatud märkide arv (positiivne täisarv).
  • Vea korral: tagastatakse -1.

Põhiline vea kontrolli näide

#include <stdio.h>

int main() {
    FILE *file = fopen("output.txt", "w");
    if (file == NULL) {
        fprintf(stderr, "Error: Could not open file.\n");
        return 1;
    }

    int result = fprintf(file, "Hello, World!\n");
    if (result < 0) {
        fprintf(stderr, "Error: Failed to write to file.\n");
    }

    fclose(file);
    return 0;
}

Selles programmis kontrollitakse fprintf tagastusväärtust ning vea korral väljastatakse teade.

Standardne veaväljund (stderr)

stderr on standardne voog, mida kasutatakse vigade ja hoiatuste väljastamiseks. Väljastades veateated stderr-i kaudu, saab need eristada tavalisest väljundist (stdout).

Näide: stderr kasutamine

#include <stdio.h>

int main() {
    FILE *file = fopen("nonexistent_dir/output.txt", "w");
    if (file == NULL) {
        fprintf(stderr, "Error: Unable to open file. Check the directory path.\n");
        return 1;
    }

    fclose(file);
    return 0;
}

Väljund (vea korral):

Error: Unable to open file. Check the directory path.

Kasutades stderr-i, saab veateated eraldada tavalisest väljundist.

Praktiline veakäsitluse näide

Allpool on toodud failikirjutamise tüüpiline veakäsitluse kood.

Näide: kirjutamise ja sulgemise veakontroll

#include <stdio.h>

int main() {
    FILE *file = fopen("output.txt", "w");
    if (file == NULL) {
        fprintf(stderr, "Error: Could not open file.\n");
        return 1;
    }

    // Kirjutamise kontroll
    if (fprintf(file, "Logging data: %d\n", 42) < 0) {
        fprintf(stderr, "Error: Failed to write to file.\n");
        fclose(file);
        return 1;
    }

    // Faili sulgemise kontroll
    if (fclose(file) != 0) {
        fprintf(stderr, "Error: Failed to close the file.\n");
        return 1;
    }

    printf("File operation completed successfully.\n");
    return 0;
}

Põhipunktid:

  1. Kontrollitakse igat sammu: avamine, kirjutamine ja sulgemine.
  2. Vea korral väljastatakse sobiv teade ja programm lõpetatakse.

Levinud vead ja lahendused

1. Faili ei saa avada

Põhjused:

  • Faili pole olemas.
  • Kataloogitee on vale.
  • Õigused puuduvad.

Lahendused:

  • Kontrolli failiteed.
  • Paranda faililubasid.
  • Kontrolli fopen tagastusväärtust.

2. Kirjutamine ebaõnnestub

Põhjused:

  • Kettaruumi puudus.
  • Fail avati ainult lugemiseks.

Lahendused:

  • Kontrolli avamisrežiimi ("w", "a").
  • Kontrolli kettaruumi.

3. Faili sulgemise viga

Põhjused:

  • Süsteemi ressursipuudus.
  • Riistvaraprobleem.

Lahendused:

  • Kontrolli sulgemisel tagastusväärtust.
  • Kasuta minimaalselt vajalikke ressursse.

Kokkuvõte

  • Kontrollides fprintf tagastusväärtust saab tuvastada kirjutamisvead.
  • Kasutades stderr-i saab veateated selgelt eristada tavalisest väljundist.
  • Põhjalik vigade käsitlus failitoimingute igas etapis parandab programmi töökindlust.

6. Rakendusnäited

Logifailide automaatne loomine

Logifaile kasutatakse programmi töö oleku ja vigade salvestamiseks. Allpool on näide logimisest koos kuupäeva ja kellaajaga.

Näide: ajatempli lisamine logisse

#include <stdio.h>
#include <time.h>

int main() {
    FILE *logFile = fopen("log.txt", "a"); // Avamine lisamisrežiimis
    if (logFile == NULL) {
        fprintf(stderr, "Error: Could not open log file.\n");
        return 1;
    }

    time_t now = time(NULL);
    struct tm *localTime = localtime(&now);

    fprintf(logFile, "[%04d-%02d-%02d %02d:%02d:%02d] Program started\n",
            localTime->tm_year + 1900, localTime->tm_mon + 1, localTime->tm_mday,
            localTime->tm_hour, localTime->tm_min, localTime->tm_sec);

    fclose(logFile);
    return 0;
}

log.txt sisu:

[2025-01-19 15:45:30] Program started

Põhipunktid

  • Kasutatakse time.h teegi funktsioone, et saada praegune aeg.
  • Avamisrežiim "a" tagab, et andmed lisatakse faili lõppu.

Tabeli kujul andmete kirjutamine

Andmete väljastamine tabelina on kasulik näiteks raportite või aruannete jaoks.

Näide: õpilaste hinded

#include <stdio.h>

int main() {
    FILE *file = fopen("report.txt", "w");
    if (file == NULL) {
        fprintf(stderr, "Error: Could not open file.\n");
        return 1;
    }

    fprintf(file, "|%-10s|%6s|%6s|%6s|\n", "Name", "Math", "Eng", "Sci");
    fprintf(file, "|%-10s|%6d|%6d|%6d|\n", "Alice", 90, 85, 88);
    fprintf(file, "|%-10s|%6d|%6d|%6d|\n", "Bob", 78, 82, 80);

    fclose(file);
    return 0;
}

report.txt sisu:

|Name      |  Math|   Eng|   Sci|
|Alice     |    90|    85|    88|
|Bob       |    78|    82|    80|

Põhipunktid

  • Vasak- ja parempoolne joondus (%-10s, %6d) teevad väljundi loetavaks.

Andmete salvestamine CSV-vormingus

CSV (Comma-Separated Values) on kasulik andmete vahetamiseks teiste rakendustega.

Näide: CSV faili kirjutamine

#include <stdio.h>

int main() {
    FILE *file = fopen("data.csv", "w");
    if (file == NULL) {
        fprintf(stderr, "Error: Could not open file.\n");
        return 1;
    }

    // Päis
    fprintf(file, "Name,Math,English,Science\n");

    // Andmeread
    fprintf(file, "Alice,90,85,88\n");
    fprintf(file, "Bob,78,82,80\n");

    fclose(file);
    return 0;
}

data.csv sisu:

Name,Math,English,Science
Alice,90,85,88
Bob,78,82,80

Põhipunktid

  • Väljade eraldamiseks kasutatakse koma (,), mis sobib Exceli või Pythoniga töötlemiseks.

Silumisinfo salvestamine

Silumislogid võimaldavad jälgida programmi tööseisundit.

Näide: muutuja logimine

#include <stdio.h>

int main() {
    FILE *debugFile = fopen("debug.log", "w");
    if (debugFile == NULL) {
        fprintf(stderr, "Error: Could not open debug log file.\n");
        return 1;
    }

    int x = 42;
    fprintf(debugFile, "Debug: Variable x = %d\n", x);

    fclose(debugFile);
    return 0;
}

debug.log sisu:

Debug: Variable x = 42

Põhipunktid

  • Silumisinfo failis aitab vigu kiiremini tuvastada.

Kokkuvõte

  • fprintf sobib logide, tabeliandmete ja CSV-de loomiseks.
  • Tööpraktikas on eriti kasulikud kuupäevaga logid ja CSV-formaadis failid.
  • Rakendusnäited aitavad paremini mõista fprintf-i praktilist kasutust.

7. Korduma kippuvad küsimused (KKK)

1. Mis vahe on fprintfil ja printfil?

Vastus

  • printf:
  • Väljastab andmed standardväljundisse (tavaliselt konsooli).
  • Väljundkohta muuta ei saa.
  • fprintf:
  • Võimaldab valida väljundi sihtkoha (nt fail, standardväljund, veaväljund).
  • Paindlikum andmete väljastamiseks.

Näide

#include <stdio.h>

int main() {
    printf("This is printed to the console.\n"); // alati konsooli

    FILE *file = fopen("output.txt", "w");
    if (file != NULL) {
        fprintf(file, "This is written to a file.\n"); // faili kirjutamine
        fclose(file);
    }
    return 0;
}

2. Kuidas fprintf abil õigesti jaapani keelt (või teisi UTF-8 märke) väljastada?

Vastus

  • Õigete märkide väljastamiseks tuleb tähelepanu pöörata järgmistele punktidele:
  1. Kooditabel:
    • Kasuta keskkonnale sobivat kodeeringut (nt UTF-8, Shift-JIS).
  2. Faili kodeering:
    • Kirjutatav fail peab kasutama sama kodeeringut, mis keskkond.

Näide: UTF-8 kasutamine

#include <stdio.h>
#include <locale.h>

int main() {
    setlocale(LC_ALL, ""); // seadista lokaadid

    FILE *file = fopen("japanese.txt", "w");
    if (file == NULL) {
        fprintf(stderr, "Error: Could not open file.\n");
        return 1;
    }

    fprintf(file, "こんにちは、世界!\n");
    fclose(file);
    return 0;
}

Märkus:

  • Mõnes keskkonnas tuleb vältida tähemärkide moondumist, määrates kodeering selgesõnaliselt.

3. Mis põhjustab fprintfi tõrkeid?

Vastus

  • Levinumad põhjused on järgmised:
  1. Faili ei saa avada:
    • Vale failitee.
    • Puuduvad õigused.
  2. Kettaruumi puudus:
    • Kirjutamise ajal pole piisavalt ruumi.
  3. Vale vorminguspetsiifer:
    • Andmetüüp ei ühti vorminguspetsiiferiga.

Näide: vorminguspetsiiferi sobimatus

#include <stdio.h>

int main() {
    FILE *file = fopen("error.txt", "w");
    if (file == NULL) {
        fprintf(stderr, "Error: Could not open file.\n");
        return 1;
    }

    // Siin kasutatakse %s, kuid antakse täisarv → määramata käitumine
    fprintf(file, "%s", 42);
    fclose(file);
    return 0;
}

Lahendus:

  • Kontrolli, et vorming ja andmetüüp kattuvad (nt %d täisarvude jaoks, %s stringide jaoks).

4. Mis mõju on puhverdamisel (buffering)?

Vastus

  • Puhverdamine:
    • Andmed kirjutatakse esmalt puhvrisse ja alles seejärel faili.
  • Probleem:
    • Kui programm katkeb ootamatult, võivad puhvrisse jäänud andmed kaduma minna.

Lahendus

  1. Kasutada fflush:
    • Puhvri tühjendamiseks ja andmete koheseks kirjutamiseks.

Näide: fflush kasutamine

#include <stdio.h>

int main() {
    FILE *file = fopen("buffered_output.txt", "w");
    if (file == NULL) {
        fprintf(stderr, "Error: Could not open file.\n");
        return 1;
    }

    fprintf(file, "Buffered data.\n");
    fflush(file); // sunnib kohe kirjutama

    fclose(file);
    return 0;
}

5. Mida teha, kui faili väljund katkeb pooleli?

Vastus

  • Põhjused võivad olla järgmised:
  1. Faili ei suleta:
    • Puhvrit ei tühjendata ja osa andmeid kaob.
  2. Kettaruumi puudus:
    • Kirjutamine katkeb, kui kettaruumi napib.

Näide: faili sulgemine

#include <stdio.h>

int main() {
    FILE *file = fopen("partial_output.txt", "w");
    if (file == NULL) {
        fprintf(stderr, "Error: Could not open file.\n");
        return 1;
    }

    fprintf(file, "This is complete data.\n");

    // Ära unusta faili sulgeda
    fclose(file);
    return 0;
}

Lahendus:

  • Kasuta alati fclose, et lõpetada kirjutamine korrektselt.
  • Kontrolli tagastusväärtusi võimalike vigade tuvastamiseks.

Kokkuvõte

  • fprintf on paindlik funktsioon, kuid korrektne veakäsitlus ja kodeering on hädavajalikud.
  • KKK annab ülevaate sagedastest probleemidest ja nende lahendustest.

8. Mitmesse faili samaaegne kirjutamine

Kasutades fprintf-i, on võimalik kirjutada andmeid korraga mitmesse faili. Selles osas vaatleme praktilisi meetodeid samaaegseks faili väljundiks.

Mitme faili haldamise põhiidee

C keeles saab avada mitu FILE pointerit ja hallata neid eraldi. Oluline on igale failile rakendada fopen, fprintf ja fclose.

Näide: kahe faili samaaegne kirjutamine

#include <stdio.h>

int main() {
    // Ava kaks faili
    FILE *file1 = fopen("output1.txt", "w");
    FILE *file2 = fopen("output2.txt", "w");

    if (file1 == NULL || file2 == NULL) {
        fprintf(stderr, "Error: Could not open one of the files.\n");
        if (file1) fclose(file1);
        if (file2) fclose(file2);
        return 1;
    }

    // Kirjuta faili 1
    fprintf(file1, "This is the first file.\n");

    // Kirjuta faili 2
    fprintf(file2, "This is the second file.\n");

    // Sulge failid
    fclose(file1);
    fclose(file2);

    printf("Data written to both files successfully.\n");
    return 0;
}

output1.txt sisu:

This is the first file.

output2.txt sisu:

This is the second file.

Põhipunktid

  1. Vea kontroll: kontrolli alati, kas fopen õnnestus.
  2. Ressursside vabastamine: sulge alati kõik avatud failid fclose-iga.

Dünaamiline failihaldus

Dünaamiliselt failinimesid genereerides saab korraga kirjutada mitmesse faili tsüklis.

Näide: dünaamilised failinimed

#include <stdio.h>

int main() {
    char filename[20];
    for (int i = 1; i <= 3; i++) {
        sprintf(filename, "file%d.txt", i);

        FILE *file = fopen(filename, "w");
        if (file == NULL) {
            fprintf(stderr, "Error: Could not open %s\n", filename);
            continue;
        }

        fprintf(file, "This is file number %d\n", i);
        fclose(file);
    }

    printf("Data written to files successfully.\n");
    return 0;
}

Loodud failid:

  • file1.txt: This is file number 1
  • file2.txt: This is file number 2
  • file3.txt: This is file number 3

Põhipunktid

  • Kasutatakse sprintf-i failinime loomiseks tsüklis.
  • Kui fail ei avane, liigutakse järgmise juurde.

Paralleelne kirjutamine

Suuremahulise samaaegse kirjutamise jaoks võib kasutada lõime (threads).

Näide: POSIX pthread abil paralleelne kirjutamine

#include <stdio.h>
#include <pthread.h>

void *write_to_file(void *arg) {
    char *filename = (char *)arg;
    FILE *file = fopen(filename, "w");
    if (file == NULL) {
        fprintf(stderr, "Error: Could not open %s\n", filename);
        return NULL;
    }

    fprintf(file, "Data written to %s\n", filename);
    fclose(file);
    return NULL;
}

int main() {
    pthread_t threads[3];
    char *filenames[] = {"thread1.txt", "thread2.txt", "thread3.txt"};

    for (int i = 0; i < 3; i++) {
        pthread_create(&threads[i], NULL, write_to_file, filenames[i]);
    }

    for (int i = 0; i < 3; i++) {
        pthread_join(threads[i], NULL);
    }

    printf("Data written to all files in parallel.\n");
    return 0;
}

Loodud failid:

  • thread1.txt: Data written to thread1.txt
  • thread2.txt: Data written to thread2.txt
  • thread3.txt: Data written to thread3.txt

Põhipunktid

  • Lõimede abil saab kirjutada paralleelselt mitmesse faili.
  • Oluline on kasutada pthread_join-i, et oodata lõimede lõppemist.

Kokkuvõte

  • fprintf abil saab samaaegselt kirjutada mitmesse faili.
  • Dünaamilised failinimed ja paralleelne töötlus suurendavad paindlikkust ja jõudlust.
  • Oluline on vabastada ressursid (fclose) ja käsitleda vigu.

9. Viitelinkid