Ich kann perror()
oder strerror()
verwenden, um die „human readable“ Fehlermeldung zu einem errno
gehören, zu drucken, aber was ist, wenn ich auch den symbolischen Namen drucken möchten (zum Beispiel „EAGAIN
“) des errno
?Wie kann ich drucken den symbolischen Namen eines errno in C?
Jede geeignete Funktion oder ein Makro, das zu tun?
Update: den Code Anbringen ich mit dem Schreiben endete, basiert auf der Idee der akzeptierte Antwort unten und seine Kommentare:
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
int get_errno_name(char *buf, int buf_size) {
// Using the linux-only gawk instead of awk, because of the convenient
// match() functionality. For Posix portability, use a different recipe...
char cmd[] = "e= && " // errno to be inserted here (max digits = 6)
"echo '#include <errno.h>' | "
"gcc -dM -E - | " // optionally, use $CC inead of gcc
"gawk \"match(\\$0, /^#[[:space:]]*define[[:space:]]+"
"(E[[:alnum:]]+)[[:space:]]+$e($|[^[:alnum:]])/, m) "
"{ print m[1] }\"";
{
// Insert the errno as the "e" shell variable in the command above.
int errno_digit_c = snprintf(cmd + 2, 6, "%d", errno);
if (errno_digit_c < 1) {
fprintf(stderr, "Failed to stringify an errno "
"in get_errno_name().\n");
return -1;
}
// Replace the inserted terminating '\0' with whitespace
cmd[errno_digit_c + 2] = ' ';
}
FILE *f = popen(cmd, "r");
if (f == NULL) {
perror("Failed to popen() in get_errno_name()");
return -1;
}
int read_size = 0, c;
while ((c = getc(f)) != EOF) {
if (isalnum(c)) {
buf[read_size++] = c;
if (read_size + 1 > buf_size) {
fprintf(stderr, "Read errno name is larger than the character "
"buffer supplied to get_errno_name().\n");
return -1;
}
}
}
buf[read_size++] = '\0';
if (pclose(f) == -1) {
perror("Failed to pclose() in get_errno_name()");
return -1;
}
return read_size;
}
Interessanter Code. Ich würde keine Funktion bereitstellen, die einen C-Compiler in einer Produktionsumgebung ausgeführt hat - es ist sowohl langsam als auch "unzuverlässig", da einige Leute zur Laufzeit keine Compiler haben.Es gibt reichlich Gelegenheit zum Zwischenspeichern von Ergebnissen unter der Annahme, dass sich der Satz von Fehlermeldungen normalerweise nicht ändert, außer (vielleicht) wenn das Betriebssystem aktualisiert wird, und selbst dann bedeutet Abwärtskompatibilität, dass die meisten Fehlernummern unverändert bleiben. Sie könnten Ihren Code jedoch dazu verwenden, die Daten für alle Systemfehler zu sammeln und diese Ausgabe dann in einer Funktion zu verwenden, die zum Zeitpunkt der Kompilierung von den Daten gesteuert wird. –
@ JonathanLeffler Vielen Dank für Ihr Feedback. Vereinbarte auf beiden Konten. Ich hätte wahrscheinlich erwähnen sollen, dass das oben genannte definitiv nicht als solches bereitgestellt werden soll (es sei denn, Sie haben keine Probleme mit den Laufzeitabhängigkeiten von gcc und gawk ...). Und ja; Code wie dieser würde besser als Teil eines (c) make-Skripts zur Kompilierzeit ausgeführt werden. Meine Projekte sind jedoch eher klein, so dass ich mich normalerweise nicht mit solchen Skripten beschäftige. Aus diesem Grund ist der obige Code für meine persönlichen Debug-Builds am besten geeignet. – Will