@billinkc, moje pytanie tak naprawdę nie dotyczy tego, jak najlepiej wydrukować wartości bool - chodzi o konkretny specyfikator printf. Który wydaje się nie istnieć. Innym kątem do ładnej odpowiedzi byłoby: być może istnieje sposób, aby dodać specyfikator formatu niestandardowego do printf, który dokonuje konwersji bool ...
maxschlepzig
W porządku, chociaż wydaje mi się, że nie jestem w stanie wyemitować VtC, więc będę musiał poczekać na wygaśnięcie mojego głosu.
billinkc
@maxschlepzig: jedynym sposobem rozwiązania problemu jest sprawdzenie dokumentacji. Jeśli używasz GNU / Linux (jako przykład, ponieważ nie powiedziałeś nam o swoim systemie), możesz przeczytać aktualną instrukcję printf na [stronach Linuxa] (man7.org). Jeśli chcesz wydrukować ciągi „prawda” / „fałsz”, możesz je zbudować ręcznie, jest to dość łatwe.
Bulat M.
Odpowiedzi:
709
Nie ma specyfikatora formatu dla booltypów. Ponieważ jednak dowolny typ całkowy krótszy niż intpromowany, intgdy jest przekazywany do printf()argumentów variadic, możesz użyć %d:
Dałbym +1, jeśli pozbyłbyś się wyrażenia nie będącego jednym ciągiem literalnym jako ciągu formatu. Ten rodzaj użytkowania łatwo przekształca się w niebezpieczne użycie. printf("%s", x ? "true" : "false");rozwiązałoby problem.
R .. GitHub PRZESTAŃ POMÓC LODOWI
2
W części „dlaczego nie” tej odpowiedzi - specyfikator formatu dla bool pozwoliłby na użycie łańcucha formatu zgodnie z przeznaczeniem: do konstruowania łańcucha z mieszanką literałów i wartości.
noamtm
13
Podobnie jak notatki, to bym raczej ku kwestionując, że printf("%s", x ? "true" : "false");jest lepiej , że printf(x ? "true" : "false");- jesteś w całkowitej kontroli ciągu formatu tutaj więc nie ma żadnego niebezpieczeństwa, że będzie to coś jak "%d"które mogłyby powodować problemy. Z fputsdrugiej strony jest lepszym rozwiązaniem.
paxdiablo
15
Dlaczego fputs„jeszcze lepiej”? Zawsze szukam sposobów na poprawę mojego C. W jakich okolicznościach powinienem stosować fputszamiast printf?
Arc676,
10
@ Arc676, dla łańcucha bez formatowania, fputs jest szybszy i prostszy niż printf (który musi parsować ciąg szukając znaków formatujących). Użycie fputs (stdout) zamiast po prostu puts () (domyślnie stdout) eliminuje nowy wiersz, który puts () dołącza do wyniku.
Czad
45
Nie ma specyfikatora formatu dla bool. Możesz wydrukować go za pomocą niektórych istniejących specyfikatorów do drukowania typów całkowitych lub zrobić coś bardziej wymyślnego:
@ H2CO3 w każdym razie zasugerowałem rozwiązanie drukujące „prawda” i „fałsz” jako żądania OP. Zmieniłem też nieznacznie moje sformułowanie w części, o której wspomniałeś.
Ivaylo Strandjev
5
@IvayloStrandjev: Tak, tam jestbool typ w C, nie tylko w wersji C89 - to część języka specyfikacji C99. Pojawiło się nowe słowo kluczowe _Bool, a jeśli je podasz <stdbool.h>, boolto synonim _Bool.
Adam Rosenfield,
30
ANSI C99 / C11 nie zawierają dodatkowego specyfikatora konwersji printf dla 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;}
Ponieważ jest to rozszerzenie glibc, GCC ostrzega przed tym niestandardowym specyfikatorem:
$ gcc -Wall -g main.c -o main
main.c: W funkcji „main”:
main.c: 34: 3: ostrzeżenie: nieznany typ konwersji znak „B” w formacie [-Wformat =]
r = printf („Wynikiem jest:% B \ n”, b);
^
main.c: 34: 3: ostrzeżenie: zbyt wiele argumentów dla formatu [-Wformat-extra-args]
Wynik:
$ ./main
Wynik jest następujący: false
(napisane 21 znaków)
$ ./main 1
Wynik jest następujący: prawda
(napisano 20 znaków)
Ta odpowiedź jest nie na temat i powinna zostać usunięta, ponieważ dotyczy innego języka niż ten w pytaniu.
Lundin
2
@Lundin Nie zgadzam się, że należy to usunąć. Celem SO jest nie tylko pomoc jednej osobie, ale także pomoc wszystkim ludziom z tym samym pytaniem. Kiedy szukam booleanu sprintf print jako true false C ++ , pojawia się pierwsza strona (choć zapewne ta strona może być najlepszym wynikiem, jeśli ta odpowiedź nie istnieje). Ponieważ C ++ jest prawie nadzbiorem C, nie sądzę, że takie odpowiedzi powinny być tak łatwo odrzucane. +1 ode mnie
Jeff G
1
@JeffG Tak, takie odpowiedzi należy usunąć, mamy bardzo jasne zasady. Przeczytaj strony wiki z tagami C i C ++. To pytanie nie jest pomocne dla programistów C, szczególnie dlatego, że systemy logiczne C i C ++ są zupełnie inne, a pytanie jest oznaczone jako C. To, że Google nie jest w stanie zrozumieć dwóch końcowych ++ w twoim wyszukiwaniu, nie jest problemem SO.
Lundin,
2
@Lundin Mój komentarz nie miał być interpretowany jako komentarz do zasad SO. To był naprawdę komentarz, czy ta odpowiedź konstruktywnie dodaje pytanie. Ta odpowiedź jest natychmiast identyfikowalna jako tylko C ++. Nikt nie przychodzi tutaj po odpowiedź tylko w języku C, aby pomyśleć, że zadziała to w C i zmarnuje czas na próby. Jest to jednak świetna odpowiedź dla C ++. Jeśli odpowiedzi są przydatne, nawet jeśli nie pomagają OP, to czy nie powinny być przechowywane? Myślę, że konstruktywne odpowiedzi, które jasno wskazują zastrzeżenia, nigdy nie powinny być usuwane, niezależnie od zasad.
To jest całkowicie niezrozumiałe. Zajęło mi "false\0true"+6*xsporo czasu, zanim zorientowałem się, co naprawdę zrobiłem. Jeśli pracujesz w projekcie z innymi ludźmi lub po prostu w projekcie z bazą kodu, którą chcesz zrozumieć x lata później, należy unikać takich konstrukcji.
HelloGoodbye
3
Chociaż widzę, że może to być bardziej zoptymalizowane, ponieważ nie ma gałęzi. Jeśli zależy Ci na prędkości, może to być opcja, po prostu dobrze wyjaśnij mechanikę sztuczki w komentarzu. Przydałaby się również funkcja wbudowana lub makro z nazwą samodokumentującą (ale prawdopodobnie w tym przypadku niewystarczające).
HelloGoodbye
3
Oprócz obaw związanych z czytelnością należy pamiętać, że
wybuchnie,
2
@plugwash Możesz oczywiście zmienić na, printf("%s\n","false\0true"+6*(x?1:0));który jest tylko ... 5% mniej czytelny.
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; } Taki sam jak z static inline char decimal2char(int d) { assert(d >= 0 && d <= 9); return '0' + d; }; po prostu zawiń ją w funkcję o nazwie opisowej i nie martw się o jej czytelność.
Odpowiedzi:
Nie ma specyfikatora formatu dla
bool
typów. Ponieważ jednak dowolny typ całkowy krótszy niżint
promowany,int
gdy jest przekazywany doprintf()
argumentów variadic, możesz użyć%d
:Ale dlaczego nie:
albo lepiej:
lub nawet lepiej:
zamiast?
źródło
printf("%s", x ? "true" : "false");
rozwiązałoby problem.printf("%s", x ? "true" : "false");
jest lepiej , żeprintf(x ? "true" : "false");
- jesteś w całkowitej kontroli ciągu formatu tutaj więc nie ma żadnego niebezpieczeństwa, że będzie to coś jak"%d"
które mogłyby powodować problemy. Zfputs
drugiej strony jest lepszym rozwiązaniem.fputs
„jeszcze lepiej”? Zawsze szukam sposobów na poprawę mojego C. W jakich okolicznościach powinienem stosowaćfputs
zamiastprintf
?Nie ma specyfikatora formatu dla bool. Możesz wydrukować go za pomocą niektórych istniejących specyfikatorów do drukowania typów całkowitych lub zrobić coś bardziej wymyślnego:
źródło
bool
typ w C, nie tylko w wersji C89 - to część języka specyfikacji C99. Pojawiło się nowe słowo kluczowe_Bool
, a jeśli je podasz<stdbool.h>
,bool
to synonim_Bool
.ANSI C99 / C11 nie zawierają dodatkowego specyfikatora konwersji printf dla
bool
.Ale biblioteka GNU C zapewnia interfejs API do dodawania niestandardowych specyfikatorów .
Przykład:
Ponieważ jest to rozszerzenie glibc, GCC ostrzega przed tym niestandardowym specyfikatorem:
Wynik:
źródło
W tradycji
itoa()
:źródło
btoa
to „ciąg binarny do podstawowego ciągu 64” w niestandardowym JavaScript (Gecko i WebKit), więc możesz chcieć użyć innej nazwy."true\0false"[(!x)*5]
:-)!!x*5
.Nie możesz, ale możesz wydrukować 0 lub 1
źródło
źródło
Jeśli podoba Ci się C ++ lepiej niż C, możesz spróbować:
źródło
Aby po prostu wydrukować 1 lub 0 na podstawie właśnie użytej wartości logicznej:
Szczególnie przydatne z flagami:
źródło
!!
może zostać zoptymalizowanyWolę odpowiedź od najlepszego sposobu, aby wydrukować wynik bool jako „fałsz” lub „prawda” w c? , tak jak
źródło
"false\0true"+6*x
sporo czasu, zanim zorientowałem się, co naprawdę zrobiłem. Jeśli pracujesz w projekcie z innymi ludźmi lub po prostu w projekcie z bazą kodu, którą chcesz zrozumieć x lata później, należy unikać takich konstrukcji.printf("%s\n","false\0true"+6*(x?1:0));
który jest tylko ... 5% mniej czytelny.static inline char const *bool2str(_Bool b) { return "false\0true"+6*x; } int main(void) { printf("%s != %s", bool2str(false), bool2str(true)); return 0; }
Taki sam jak zstatic inline char decimal2char(int d) { assert(d >= 0 && d <= 9); return '0' + d; }
; po prostu zawiń ją w funkcję o nazwie opisowej i nie martw się o jej czytelność.