@billinkc, meine Frage ist nicht wirklich, wie man Bool-Werte am besten druckt - es geht um einen konkreten printf-Spezifizierer. Welches scheint nicht zu existieren. Ein anderer Winkel zu einer netten Antwort wäre: Vielleicht gibt es eine Möglichkeit, printf einen benutzerdefinierten Formatbezeichner hinzuzufügen, der die Bool-Konvertierung durchführt ...
maxschlepzig
Fair genug, obwohl ich anscheinend nicht in der Lage bin, den VtC freizugeben, muss ich nur warten, bis meine Stimme abläuft.
Billinkc
@maxschlepzig: Die einzige Möglichkeit, das Problem zu lösen, besteht darin, die Dokumentation zu überprüfen. Wenn Sie GNU / Linux verwenden (da Sie uns beispielsweise nichts über Ihr System erzählt haben), können Sie ein aktuelles printf-Handbuch auf [Linux-Manpages] (man7.org) lesen. Wenn Sie möchten, dass "true" / "false" -Strings gedruckt werden, können Sie sie manuell erstellen. Dies ist ziemlich einfach.
Bulat M.
Antworten:
710
Es gibt keinen Formatbezeichner für boolTypen. Da jedoch jeder Integraltyp, der kürzer intist intals bei printf()der Übergabe an die variadischen Argumente heraufgestuft, verwendet wird, können Sie Folgendes verwenden %d:
Ich würde dies +1, wenn Sie den Nicht-Single-String-Literal-Ausdruck als Format-String entfernen. Diese Art der Verwendung wird leicht zu einer unsicheren Verwendung. printf("%s", x ? "true" : "false");würde das Problem beheben.
R .. GitHub STOP HELPING ICE
2
Für den "Warum nicht" -Teil dieser Antwort würde ein Formatbezeichner für bool die Verwendung der Formatzeichenfolge wie vorgesehen ermöglichen: zum Erstellen einer Zeichenfolge mit einer Mischung aus Literalen und Werten.
Noamtm
13
Nur als Anmerkung, würde ich in Richtung streit neigen , das printf("%s", x ? "true" : "false");ist besser , dass printf(x ? "true" : "false");- Sie sind insgesamt die Kontrolle über das Format - String hier so gibt es keine Gefahr , dass sie etwas bekommen wie "%d"die Probleme verursachen würde. Die fputs, auf der anderen Seite, ist eine bessere Option.
Paxdiablo
15
Warum ist fputs"noch besser"? Ich bin immer auf der Suche nach Möglichkeiten, mein C zu verbessern. Unter welchen Umständen sollte ich fputsstatt verwenden printf?
Arc676
10
@ Arc676, für eine Zeichenfolge ohne Formatierung ist fputs schneller und einfacher als printf (die die Zeichenfolge analysieren muss, um nach Formatierungszeichen zu suchen). Durch die Verwendung von fputs (stdout) anstelle von put () (standardmäßig stdout) wird die neue Zeile entfernt, die put () an die Ausgabe anfügt.
Tschad
45
Es gibt keinen Formatbezeichner für bool. Sie können es mit einigen der vorhandenen Spezifizierer zum Drucken integraler Typen drucken oder etwas ausgefalleneres tun:
@ H2CO3 sowieso habe ich eine Lösung vorgeschlagen, die "wahr" und "falsch" als OP-Anforderungen druckt. Ich habe auch meinen Wortlaut in dem von Ihnen erwähnten Teil leicht geändert.
Ivaylo Strandjev
5
@IvayloStrandjev: Ja, es gibt einen boolTyp in C, nur nicht in der C89-Edition - er ist Teil der C99-Sprachspezifikation. Es gibt ein neues Schlüsselwort _Bool, und wenn Sie es einschließen <stdbool.h>, boolist es ein Synonym für _Bool.
Adam Rosenfield
30
ANSI C99 / C11 enthält keinen zusätzlichen printf-Konvertierungsspezifizierer für bool.
#include<stdio.h>#include<printf.h>#include<stdbool.h>staticint bool_arginfo(conststruct printf_info *info,size_t n,int*argtypes,int*size){if(n){
argtypes[0]= PA_INT;*size =sizeof(bool);}return1;}staticint bool_printf(FILE *stream,conststruct printf_info *info,constvoid*const*args){bool b =*(constbool*)(args[0]);int r = fputs(b ?"true":"false", stream);return r == EOF ?-1:(b ?4:5);}staticint setup_bool_specifier(){int r = register_printf_specifier('B', bool_printf, bool_arginfo);return r;}int main(int argc,char**argv){int r = setup_bool_specifier();if(r)return1;bool b = argc >1;
r = printf("The result is: %B\n", b);
printf("(written %d characters)\n", r);return0;}
Da es sich um eine glibc-Erweiterung handelt, warnt der GCC vor diesem benutzerdefinierten Bezeichner:
$ gcc -Wall -g main.c -o main
main.c: In der Funktion 'main':
main.c: 34: 3: Warnung: Unbekanntes Konvertierungstypzeichen 'B' im Format [-Wformat =]
r = printf ("Das Ergebnis ist:% B \ n", b);
^
main.c: 34: 3: Warnung: Zu viele Argumente für das Format [-Wformat-extra-args]
Ausgabe:
$ ./main
Das Ergebnis ist: false
(21 Zeichen geschrieben)
$ ./main 1
Das Ergebnis ist: wahr
(geschrieben 20 Zeichen)
btoaist "Binärzeichenfolge zur Basis 64 Zeichenfolge" in nicht standardmäßigem JavaScript (Gecko und WebKit), daher möchten Sie möglicherweise einen anderen Namen verwenden.
Panzi
26
@panzi: Ich bin mir nicht sicher, ob es sich für einen C-Programmierer lohnt, sich über nicht standardmäßige JavaScript-Kennungen Gedanken zu machen.
Keith Thompson
5
@KeithThompson Ich glaube, ich habe die Fragen verwirrt und irgendwie gedacht, dass es sich um JavaScript handelt, was sowieso keinen Sinn ergibt. Es war wahrscheinlich spät in der Nacht.
Panzi
9
Oder für die "true\0false"[(!x)*5]
hinterhältigeren
1
@MooingDuck: vielleicht !!x*5.
jxh
4
Sie können nicht, aber Sie können 0 oder 1 drucken
Diese Antwort ist nicht zum Thema gehörend und sollte gelöscht werden, da es sich um eine andere Sprache als die in der Frage angegebene handelt.
Lundin
2
@Lundin Ich bin nicht einverstanden, dass dies gelöscht werden sollte. Das Ziel von SO ist nicht nur, einer Person zu helfen, sondern allen Menschen mit der gleichen Frage zu helfen. Wenn ich nach sprintf print boolean als true false c ++ suche , ist dies die erste Seite, die angezeigt wird (obwohl diese Seite möglicherweise das beste Ergebnis war, wenn diese Antwort nicht vorhanden war). Da C ++ fast eine Obermenge von C ist, denke ich nicht, dass solche Antworten so einfach verworfen werden sollten. +1 von mir.
Jeff G
1
@JeffG Ja, solche Antworten sollten gelöscht werden, wir haben sehr klare Richtlinien. Lesen Sie die C- und C ++ - Tag-Wikis. Diese Frage ist für C-Programmierer nicht hilfreich, insbesondere weil die booleschen Systeme C und C ++ völlig unterschiedlich sind und die Frage mit C gekennzeichnet ist. Dass Google die beiden nachfolgenden ++ in Ihrer Suche nicht verstehen kann, ist nicht das Problem von SO.
Lundin
2
@Lundin Mein Kommentar sollte nicht als Kommentar zu den Richtlinien von SO interpretiert werden. Es war wirklich ein Kommentar darüber, ob diese Antwort die Frage konstruktiv ergänzt. Diese Antwort ist sofort nur als C ++ erkennbar. Niemand, der hierher kommt, um eine Antwort nur für C zu erhalten, würde dazu verleitet zu glauben, dass dies in C funktionieren würde, und Zeit damit verschwenden, es zu versuchen. Dies ist jedoch eine gute Antwort für C ++. Wenn Antworten nützlich sind, auch wenn sie dem OP nicht helfen, sollten sie dann nicht aufbewahrt werden? Ich denke, konstruktive Antworten, die eindeutig Vorbehalte identifiziert haben, sollten niemals gelöscht werden, unabhängig von der Politik.
Das ist völlig unverständlich. Es dauerte eine Weile, bis ich herausfand, was "false\0true"+6*xwirklich geschah. Wenn Sie in einem Projekt mit anderen Personen arbeiten oder nur in einem Projekt mit einer Codebasis, die Sie x Jahre später verstehen möchten , sollten Konstruktionen wie diese vermieden werden.
HelloGoodbye
3
Obwohl ich sehe, dass dies möglicherweise optimierter ist, da es verzweigungslos ist. Wenn Geschwindigkeit Ihr Anliegen ist, könnte dies eine Option sein. Erklären Sie die Mechanik hinter dem Trick in einem Kommentar. Eine Inline-Funktion oder ein Makro mit einem selbstdokumentierenden Namen wäre ebenfalls hilfreich (aber in diesem Fall wahrscheinlich nicht ausreichend).
HelloGoodbye
3
Neben den Bedenken hinsichtlich der Lesbarkeit ist zu beachten, dass dies
explodiert
2
@plugwash Sie können es natürlich ändern, printf("%s\n","false\0true"+6*(x?1:0));was nur ... 5% weniger lesbar ist.
HoosierEE
static inline char const *bool2str(_Bool b) { return "false\0true"+6*x; } int main(void) { printf("%s != %s", bool2str(false), bool2str(true)); return 0; } Gleich wie mit static inline char decimal2char(int d) { assert(d >= 0 && d <= 9); return '0' + d; }; Wickeln Sie es einfach in eine beschreibende benannte Funktion und sorgen Sie sich nicht um die Lesbarkeit.
Antworten:
Es gibt keinen Formatbezeichner für
bool
Typen. Da jedoch jeder Integraltyp, der kürzerint
istint
als beiprintf()
der Übergabe an die variadischen Argumente heraufgestuft, verwendet wird, können Sie Folgendes verwenden%d
:Aber warum nicht:
oder besser:
oder noch besser:
stattdessen?
quelle
printf("%s", x ? "true" : "false");
würde das Problem beheben.printf("%s", x ? "true" : "false");
ist besser , dassprintf(x ? "true" : "false");
- Sie sind insgesamt die Kontrolle über das Format - String hier so gibt es keine Gefahr , dass sie etwas bekommen wie"%d"
die Probleme verursachen würde. Diefputs
, auf der anderen Seite, ist eine bessere Option.fputs
"noch besser"? Ich bin immer auf der Suche nach Möglichkeiten, mein C zu verbessern. Unter welchen Umständen sollte ichfputs
statt verwendenprintf
?Es gibt keinen Formatbezeichner für bool. Sie können es mit einigen der vorhandenen Spezifizierer zum Drucken integraler Typen drucken oder etwas ausgefalleneres tun:
quelle
bool
Typ in C, nur nicht in der C89-Edition - er ist Teil der C99-Sprachspezifikation. Es gibt ein neues Schlüsselwort_Bool
, und wenn Sie es einschließen<stdbool.h>
,bool
ist es ein Synonym für_Bool
.ANSI C99 / C11 enthält keinen zusätzlichen printf-Konvertierungsspezifizierer für
bool
.Die GNU C-Bibliothek bietet jedoch eine API zum Hinzufügen benutzerdefinierter Spezifizierer .
Ein Beispiel:
Da es sich um eine glibc-Erweiterung handelt, warnt der GCC vor diesem benutzerdefinierten Bezeichner:
Ausgabe:
quelle
In der Tradition von
itoa()
:quelle
btoa
ist "Binärzeichenfolge zur Basis 64 Zeichenfolge" in nicht standardmäßigem JavaScript (Gecko und WebKit), daher möchten Sie möglicherweise einen anderen Namen verwenden."true\0false"[(!x)*5]
!!x*5
.Sie können nicht, aber Sie können 0 oder 1 drucken
Quelle
quelle
Wenn Sie C ++ besser mögen als C, können Sie dies versuchen:
quelle
Um nur 1 oder 0 basierend auf dem booleschen Wert zu drucken, den ich gerade verwendet habe:
Besonders nützlich bei Flags:
quelle
!!
Ich bevorzuge eine Antwort von Bester Weg, um das Ergebnis eines Bools als 'falsch' oder 'wahr' in c zu drucken. , so wie
quelle
"false\0true"+6*x
wirklich geschah. Wenn Sie in einem Projekt mit anderen Personen arbeiten oder nur in einem Projekt mit einer Codebasis, die Sie x Jahre später verstehen möchten , sollten Konstruktionen wie diese vermieden werden.printf("%s\n","false\0true"+6*(x?1:0));
was nur ... 5% weniger lesbar ist.static inline char const *bool2str(_Bool b) { return "false\0true"+6*x; } int main(void) { printf("%s != %s", bool2str(false), bool2str(true)); return 0; }
Gleich wie mitstatic inline char decimal2char(int d) { assert(d >= 0 && d <= 9); return '0' + d; }
; Wickeln Sie es einfach in eine beschreibende benannte Funktion und sorgen Sie sich nicht um die Lesbarkeit.