Ce face errno, perror și strerror
Multe funcții din biblioteca standard semnalează o eroare printr-o valoare specială (NULL, -1, EOF) și pun motivul în errno, un număr declarat în <errno.h>. Codurile au nume: ENOENT (fișierul nu există), EACCES (acces interzis), ERANGE (rezultat în afara intervalului), EDOM (argument în afara domeniului).
perror("text") scrie pe stderr textul tău, două puncte și descrierea erorii. strerror(cod) returnează descrierea ca șir, ca s-o pui unde vrei (într-un printf, într-un jurnal). Mesajele sunt în engleză și pot diferi puțin între sisteme.
Citește errno imediat după funcția care a eșuat: orice alt apel de bibliotecă îl poate schimba. Funcțiile nu pun errno pe 0 când reușesc, de aceea, la funcții ca strtol, setezi tu errno = 0 înainte de apel.
Parametri
| Parametru | Descriere |
|---|---|
s |
La perror: textul afișat înaintea mesajului (de obicei numele fișierului sau al operației). |
cod |
La strerror: un cod de eroare, de obicei errno. |
Ce returnează
strerror: un șir cu descrierea erorii (nu îl modifica). perror nu returnează nimic.
Exemple
Exemplul 1: Motivul pentru care fopen a eșuat
Fișierul nu există, deci errno devine ENOENT. strerror dă textul pe stdout, iar perror scrie pe stderr (afișat aici la final, după ieșirea normală).
#include <errno.h>
#include <stdio.h>
#include <string.h>
int main(void) {
FILE *f = fopen("comenzi-iasi.txt", "r");
if (f == NULL) {
int cod = errno;
printf("errno = %d, ENOENT? %s\n", cod, cod == ENOENT ? "da" : "nu");
printf("strerror: %s\n", strerror(cod));
perror("comenzi-iasi.txt");
return 0;
}
fclose(f);
return 0;
}
Rezultat
errno = 2, ENOENT? da
strerror: No such file or directory
comenzi-iasi.txt: No such file or directory
Exemplul 2: errno = 0 înainte de strtol
Un număr prea mare pentru long nu produce o valoare negativă specială: strtol returnează LONG_MAX și pune ERANGE în errno. Ca să știi sigur că eroarea vine de la acest apel, pui errno pe 0 înainte.
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
const char *texte[] = {"2500", "99999999999999999999999"};
for (int i = 0; i < 2; i++) {
errno = 0;
long valoare = strtol(texte[i], NULL, 10);
if (errno == ERANGE) {
printf("%s: %s (am primit %s)\n", texte[i], strerror(errno),
valoare == LONG_MAX ? "LONG_MAX" : "altă valoare");
} else {
printf("%s: ok, %ld\n", texte[i], valoare);
}
}
return 0;
}
Rezultat
2500: ok, 2500
99999999999999999999999: Result too large (am primit LONG_MAX)
Greșeli frecvente
- Verifici
errnofără ca funcția să fi raportat o eroare.errnopoate avea o valoare veche de la un apel anterior; uită-te la el doar după ce valoarea returnată arată eșecul. - Apelezi
printfîntre funcția care a eșuat și citirea luierrno.printfpoate modificaerrno; salvează-l întâi într-o variabilă. - Declari singur
int errno;.errnoeste un macro definit de bibliotecă (fiecare fir de execuție are propria valoare); include doar<errno.h>.
Comenzi înrudite
fopen și fclose: Deschide un fișier pentru citire, scriere sau adăugare și returnează un FILE *; fclose îl închide și salvează datele rămase.strtol și strtod: Transformă text în număr și îți spune unde s-a oprit citirea și dacă valoarea a depășit limitele.fprintf: Scrie text formatat într-un fișier sau în stderr, cu același șablon ca printf.exit, atexit și EXIT_SUCCESS: Oprește programul din orice funcție, cu un cod de ieșire; atexit înregistrează funcții de rulat la final.assert: Verifică în timpul rulării o condiție care trebuie să fie mereu adevărată și oprește programul cu un mesaj dacă nu este.