Obrir i tancar un fitxer
fopen() i fclose()
FILE *f;
f = fopen("notes.txt", "w");
if (f == NULL) {
printf("Error obrint el fitxer\n");
return 1;
}
// ... llegir o escriure ...
fclose(f);
FILE * és un apuntador especial que representa el fitxer obert. El segon argument de fopen és el mode: "r" (lectura; el fitxer ha d'existir), "w" (escriptura; el crea si no existeix, o el buida si ja hi era) i "a" (afegir al final, sense esborrar el que ja hi havia). Si fopen no pot obrir el fitxer, retorna NULL — per això cal comprovar-ho sempre, igual que amb malloc.
No t'oblidis mai de fclose: és el que assegura que tot el que has escrit es desa de debò al disc.
Escriptura i lectura formatada
fprintf i fscanf funcionen exactament com printf i scanf, només que el primer argument és el fitxer, no la pantalla ni el teclat.
fprintf(f, "%s %d\n", "Jordi", 16); // escriu al fitxer, no al terminal fscanf(f, "%s %d", nom, &edat); // llegeix del fitxer, no del teclat
Llegir línia a línia
Per processar un fitxer sencer sense saber per endavant quantes línies té, es llegeix amb fgets dins d'un bucle fins que no en quedin més.
char linia[50];
while (fgets(linia, 50, f) != NULL) {
printf("%s", linia);
}
fgets ja la coneixies del teclat (stdin); aquí l'únic que canvia és llegir d'un FILE * en lloc de stdin. Quan ja no hi ha més línies per llegir, fgets retorna NULL, i el bucle s'atura tot sol.
Taula de referència
| Funció | Fa |
|---|---|
fopen(nom, mode) | obre el fitxer; retorna NULL si falla |
fclose(f) | el tanca i desa els canvis |
fputc(c, f) / fgetc(f) | escriu / llegeix un sol caràcter |
fputs(s, f) / fgets(s, mida, f) | escriu / llegeix una línia |
fprintf(f, ...) / fscanf(f, ...) | escriptura / lectura formatada |
fread(...) / fwrite(...) | llegeixen / escriuen blocs de bytes en cru (registres sencers, no text) |
ferror(f) | cert si hi ha hagut algun error amb aquest fitxer |
Mira el fitxer omplir-se i buidar-se pas a pas
Fixa't que fprintf i fscanf no toquen mai el terminal: el panell "Fitxer" és on passa l'acció.
Escriptura i lectura
Línia a línia
Codi
Variables
| Nom | Valor |
|---|
Fitxer
Terminal
Problemes per resoldre
Sense solució ni comprovació automàtica: escriu el programa, compila'l (gcc programa.c -o programa) i prova'l. Les pistes són plegades perquè les obris només si les necessites.
1. Desar i sumar
Escriu un programa que desi els números 3, 7, 1, 9 i 5 en un fitxer numeros.txt (un per línia). Després, torna'l a obrir, llegeix-los i mostra'n la suma.
Suma: 25
Pistes
Primer un bloc que obre el fitxer en mode "w" i hi escriu els 5 números amb fprintf(f, "%d\n", num);, i fclose.
Després, un altre bloc que l'obre en mode "r" i llegeix amb fscanf(f, "%d", &num) dins d'un bucle, acumulant la suma — fscanf retorna el nombre de valors llegits correctament (1 si n'hi havia, o un valor diferent quan ja no en queden).
2. Comptar línies
Reaprofitant el numeros.txt de l'exercici anterior, escriu un programa que compti quantes línies té.
El fitxer té 5 línies
Pistes
El mateix patró while (fgets(linia, 50, f) != NULL) de la teoria, però en lloc d'imprimir cada línia, incrementa un comptador.
3. Copiar un fitxer
Escriu un programa que copiï el contingut de numeros.txt a un fitxer nou, copia.txt, caràcter a caràcter (amb fgetc i fputc, no amb línies senceres).
Copiat correctament
Pistes
Obre'n dos alhora: un en mode "r" (l'origen) i un altre en mode "w" (el destí).
int c; while ((c = fgetc(origen)) != EOF) { fputc(c, desti); } — fgetc retorna EOF (no NULL, perquè treballa amb un sol caràcter) quan el fitxer s'acaba.
Exercicis d'autoavaluació
Aquests es generen amb valors nous a l'atzar i tenen solució comprovable.
Quina serà la sortida per terminal d'aquest programa?