Apa specifier format printf untuk bool?

458

Sejak ANSI C99 ada _Boolatau boolmelalui stdbool.h. Tetapi apakah ada juga printfpenentu format untuk bool?

Maksud saya sesuatu seperti dalam kode semu itu:

bool x = true;
printf("%B\n", x);

yang akan mencetak:

true
maxschlepzig
sumber
1
Anda dapat membaca ini untuk informasi lebih lanjut cplusplus.com/reference/cstdio/printf Anda selalu dapat membuatnya!
Varvarigos Emmanouil
3
@ Billinkc, pertanyaan saya sebenarnya bukan tentang apa cara terbaik untuk mencetak nilai bool - ini tentang specifier printf beton. Yang sepertinya tidak ada. Sudut lain untuk jawaban yang bagus adalah: mungkin ada cara untuk menambahkan
penentu
Cukup adil, meskipun saya tampaknya tidak memiliki kemampuan untuk melepaskan VtC jadi saya hanya harus menunggu suara saya berakhir.
billinkc
@maxschlepzig: satu-satunya cara untuk menyelesaikan masalah adalah dengan memeriksa dokumentasi. Jika Anda menggunakan GNU / Linux (misalnya, karena Anda tidak memberi tahu kami tentang sistem Anda), Anda dapat membaca manual printf terbaru di [Linux man pages] (man7.org). Jika Anda ingin mencetak string "benar" / "salah", Anda dapat membuatnya secara manual, itu sangat mudah.
Bulat M.

Jawaban:

711

Tidak ada penentu format untuk booljenis. Namun, karena jenis integral apa pun yang lebih pendek dari intyang dipromosikan intketika diturunkan ke printf()argumen variadik, Anda dapat menggunakan %d:

bool x = true;
printf("%d\n", x); // prints 1

Namun mengapa tidak:

printf(x ? "true" : "false");

atau lebih baik:

printf("%s", x ? "true" : "false");

atau, bahkan lebih baik:

fputs(x ? "true" : "false", stdout);

sebagai gantinya?

Adrian Mole
sumber
21
Saya akan memberi ini +1 jika Anda menyingkirkan ekspresi non-string-tunggal-literal sebagai string format. Penggunaan semacam ini dengan mudah berubah menjadi penggunaan yang tidak aman. printf("%s", x ? "true" : "false");akan memperbaiki masalah ini.
R .. GitHub BERHENTI MEMBANTU ICE
2
Untuk bagian "mengapa tidak" dari jawaban ini - penentu format untuk bool akan memungkinkan string format untuk digunakan seperti yang dirancang: untuk membangun string dengan campuran literal dan nilai.
noamtm
13
Hanya sebagai catatan, saya akan cenderung ke arah yang bersengketa yang printf("%s", x ? "true" : "false");adalah lebih baik bahwa printf(x ? "true" : "false");- Anda berada dalam keseluruhan kontrol dari format string di sini sehingga tidak ada bahaya bahwa itu akan mendapatkan sesuatu seperti "%d"yang akan menyebabkan masalah. Di fputssisi lain, ini adalah pilihan yang lebih baik.
paxdiablo
15
Mengapa fputs"lebih baik"? Saya selalu mencari cara untuk meningkatkan C. Saya dalam kondisi apa yang harus saya gunakan, fputsbukan printf?
Arc676
10
@ Arc676, untuk string tanpa pemformatan, fput lebih cepat dan lebih sederhana daripada printf (yang harus mengurai string mencari chars pemformatan). Menggunakan fput (stdout) alih-alih hanya menempatkan () (yang default ke stdout) menghilangkan baris baru yang menempatkan () ditambahkan ke output.
Chad
45

Tidak ada penentu format untuk bool. Anda dapat mencetaknya menggunakan beberapa specifier yang ada untuk mencetak tipe integral atau melakukan sesuatu yang lebih mewah:

 printf("%s", x?"true":"false");
Ivaylo Strandjev
sumber
Para pemain tidak diperlukan.
@ H2CO3 lagian saya telah menyarankan solusi mencetak "benar" dan "salah" sebagai permintaan OP. Saya juga sedikit mengubah kata-kata saya pada bagian yang Anda sebutkan.
Ivaylo Strandjev
5
@IvayloStrandjev: Ya, ada adalah sebuah boolketik C, hanya saja tidak dalam edisi C89 - bagian itu dari C99 bahasa spec. Ada kata kunci baru _Bool, dan jika Anda sertakan <stdbool.h>, maka boolsinonim untuk _Bool.
Adam Rosenfield
30

ANSI C99 / C11 tidak termasuk specifier konversi printf tambahan untuk bool.

Tetapi pustaka GNU C menyediakan API untuk menambahkan penspesifikasi khusus .

Sebuah contoh:

#include <stdio.h>
#include <printf.h>
#include <stdbool.h>

static int bool_arginfo(const struct printf_info *info, size_t n,
    int *argtypes, int *size)
{
  if (n) {
    argtypes[0] = PA_INT;
    *size = sizeof(bool);
  }
  return 1;
}
static int bool_printf(FILE *stream, const struct printf_info *info,
    const void *const *args)
{
  bool b =  *(const bool*)(args[0]);
  int r = fputs(b ? "true" : "false", stream);
  return r == EOF ? -1 : (b ? 4 : 5);
}
static int 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) return 1;
  bool b = argc > 1;
  r = printf("The result is: %B\n", b);
  printf("(written %d characters)\n", r);
  return 0;
}

Karena ini merupakan ekstensi glibc, GCC memperingatkan tentang specifier khusus itu:

$ gcc -Wall -g main.c -o main
main.c: Dalam fungsi 'main':
main.c: 34: 3: peringatan: karakter tipe konversi yang tidak dikenal 'B' dalam format [-Wformat =]
   r = printf ("Hasilnya adalah:% B \ n", b);
   ^
main.c: 34: 3: peringatan: terlalu banyak argumen untuk format [-Wformat-extra-args]

Keluaran:

$ ./main
Hasilnya adalah: false
(ditulis 21 karakter)
$. / utama 1
Hasilnya adalah: benar
(ditulis 20 karakter)
maxschlepzig
sumber
12

Dalam tradisi itoa():

#define btoa(x) ((x)?"true":"false")

bool x = true;
printf("%s\n", btoa(x));
jxh
sumber
5
btoaadalah "string biner ke basis 64 string" dalam JavaScript non-standar (Gecko dan WebKit), jadi Anda mungkin ingin menggunakan nama yang berbeda.
panzi
26
@panzi: Saya tidak yakin itu sepadan dengan usaha seorang programmer C untuk khawatir tentang pengidentifikasi JavaScript non-standar.
Keith Thompson
5
@KeithThompson Saya pikir saya bingung dengan pertanyaan dan entah bagaimana berpikir ini tentang JavaScript, yang tidak masuk akal. Mungkin sudah larut malam.
panzi
9
Atau, untuk yang lebih licik di antara kita: "true\0false"[(!x)*5]:-)
paxdiablo
1
@ MoingDuck: mungkin !!x*5.
jxh
4

Anda tidak bisa, tetapi Anda dapat mencetak 0 atau 1

_Bool b = 1;
printf("%d\n", b);

sumber

Stephan
sumber
2

Jika Anda menyukai C ++ lebih baik daripada C, Anda dapat mencoba ini:

#include <ios>
#include <iostream>

bool b = IsSomethingTrue();
std::cout << std::boolalpha << b;
Arsen YM
sumber
5
Jawaban ini di luar topik dan harus dihapus, karena ini tentang bahasa lain daripada yang ada di pertanyaan.
Lundin
2
@Lundin Saya tidak setuju bahwa ini harus dihapus. Tujuan SO tidak hanya untuk membantu satu orang, tetapi untuk membantu semua orang dengan pertanyaan yang sama. Ketika saya mencari sprintf print boolean sebagai true false c ++ , ini adalah halaman pertama yang muncul (walaupun bisa dibilang halaman ini mungkin merupakan hasil teratas jika jawaban ini tidak ada). Karena C ++ hampir merupakan superset dari C, saya tidak berpikir jawaban seperti itu harus dengan mudah dibuang. +1 dari saya.
Jeff G
1
@ JeffFF Ya jawaban seperti itu harus dihapus, kami memiliki kebijakan yang sangat jelas. Baca wiki tag C dan C ++. Pertanyaan ini tidak membantu programmer C terutama karena sistem boolean C dan C ++ sama sekali berbeda dan pertanyaannya ditandai C. Bahwa Google tidak dapat memahami dua trailing ++ dalam pencarian Anda bukan masalah SO.
Lundin
2
@Lundin Komentar saya tidak dimaksudkan untuk ditafsirkan sebagai komentar pada kebijakan SO. Itu benar-benar komentar tentang apakah jawaban ini menambah pertanyaan. Jawaban ini segera dapat diidentifikasi sebagai C ++ - saja. Tidak ada yang datang ke sini untuk jawaban C-only akan tertipu untuk berpikir ini akan berhasil di C dan membuang waktu untuk mencobanya. Namun, ini adalah jawaban yang bagus untuk C ++. Jika jawaban bermanfaat, bahkan jika mereka tidak membantu OP, maka bukankah seharusnya dijaga? Saya pikir jawaban konstruktif yang telah mengidentifikasi dengan jelas peringatan tidak boleh dihapus, terlepas dari kebijakan.
Jeff G
1
@JeffG Anda dapat memunculkannya di meta.stackoverflow.com , ini bukan tempat untuk melakukan diskusi ini.
Lundin
2

Untuk hanya mencetak 1 atau 0 berdasarkan nilai boolean saya hanya menggunakan:

printf("%d\n", !!(42));

Sangat berguna dengan Bendera:

#define MY_FLAG (1 << 4)
int flags = MY_FLAG;
printf("%d\n", !!(flags & MY_FLAG));
Tarion
sumber
Berhati-hatilah bahwa !!mungkin akan dioptimalkan jauh
ragerdl
1

Saya lebih suka jawaban dari Cara terbaik untuk mencetak hasil bool sebagai 'salah' atau 'benar' dalam c? , seperti

printf("%s\n", "false\0true"+6*x);
  • x == 0, "false \ 0true" + 0 "itu berarti" false ";
  • x == 1, "false \ 0true" + 6 "itu berarti" benar ";
xjzhou
sumber
21
Ini sama sekali tidak bisa dipahami. Butuh waktu yang lama sebelum saya menemukan apa yang "false\0true"+6*xsebenarnya terjadi. Jika Anda bekerja dalam proyek dengan orang lain, atau hanya dalam proyek dengan basis kode yang ingin Anda pahami x tahun kemudian, konstruksi seperti ini harus dihindari.
HelloGoodbye,
3
Meskipun saya melihat bahwa ini mungkin lebih dioptimalkan karena kurang cabang. Jika kecepatan menjadi perhatian Anda, ini mungkin menjadi pilihan, pastikan untuk menjelaskan mekanisme di balik trik dengan baik dalam komentar. Fungsi inline atau makro dengan nama yang mendokumentasikan diri juga akan membantu (tetapi mungkin tidak cukup dalam kasus ini).
HelloGoodbye,
3
Serta kekhawatiran tentang keterbacaan diingat bahwa ini akan meledak jika seseorang memberikan nilai selain 0 atau 1.
plugwash
2
@plugwash Anda tentu saja dapat mengubahnya printf("%s\n","false\0true"+6*(x?1:0));yang hanya ... 5% lebih sedikit dapat dibaca.
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; } Sama seperti dengan static inline char decimal2char(int d) { assert(d >= 0 && d <= 9); return '0' + d; }; cukup bungkus dengan fungsi yang dinamai secara deskriptif dan jangan khawatir tentang keterbacaannya.
yyny