ตัวระบุรูปแบบ printf สำหรับ bool คืออะไร


458

ตั้งแต่ ANSI C99 มี_Boolหรือผ่านทางbool stdbool.hแต่จะมีตัวprintfระบุรูปแบบสำหรับบูลด้วยหรือไม่

ฉันหมายถึงบางอย่างเช่นในรหัสหลอกว่า:

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

ซึ่งจะพิมพ์:

true

1
คุณสามารถอ่านได้สำหรับข้อมูลเพิ่มเติมcplusplus.com/reference/cstdio/printfคุณสามารถทำมันได้ตลอดเวลา!
Varvarigos Emmanouil


3
@ บิลลิงคคำถามของฉันไม่ได้เกี่ยวกับสิ่งที่ดีที่สุดในการพิมพ์ค่าบูล - มันเป็นเรื่องเกี่ยวกับ specifier printf ที่เป็นรูปธรรม ซึ่งดูเหมือนจะไม่มีอยู่จริง อีกมุมหนึ่งของคำตอบที่ดีอาจจะมีวิธีการเพิ่มตัวระบุรูปแบบที่กำหนดเองเพื่อ printf ที่ทำการแปลงแบบบูล ...
maxschlepzig

ยุติธรรมพอถึงแม้ว่าฉันดูเหมือนจะไม่มีความสามารถในการถ่ายทอด VtC ดังนั้นฉันจะต้องรอให้การลงคะแนนของฉันหมดอายุ
billinkc

@maxschlepzig: วิธีเดียวในการแก้ไขปัญหาคือตรวจสอบเอกสาร หากคุณใช้ GNU / Linux (ตัวอย่างเช่นเนื่องจากคุณไม่ได้บอกเราเกี่ยวกับระบบของคุณ) คุณสามารถอ่านคู่มือการพิมพ์ที่ทันสมัยบน [Linux man pages] (man7.org) หากคุณต้องการพิมพ์สตริง "true" / "false" คุณสามารถสร้างมันเองได้มันค่อนข้างง่าย
Bulat M.

คำตอบ:


711

ไม่มีตัวระบุรูปแบบสำหรับboolประเภท อย่างไรก็ตามเนื่องจากประเภทอินทิกรัลใดที่สั้นกว่าที่intได้รับการโปรโมตintเมื่อผ่านไปยังprintf()อาร์กิวเมนต์ของตัวแปรคุณสามารถใช้%d:

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

แต่ทำไมไม่:

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

หรือดีกว่า:

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

หรือดียิ่งขึ้น:

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

แทน?


21
ฉันจะ +1 สิ่งนี้ถ้าคุณกำจัดนิพจน์ที่ไม่ใช่สายเดี่ยวตัวอักษรเป็นสตริงรูปแบบ การใช้งานประเภทนี้จะเปลี่ยนเป็นการใช้งานที่ไม่ปลอดภัยได้อย่างง่ายดาย printf("%s", x ? "true" : "false");จะแก้ไขปัญหา
. GitHub หยุดช่วยเหลือน้ำแข็ง

2
สำหรับส่วน "ทำไมไม่" ของคำตอบนี้ - ตัวระบุรูปแบบสำหรับบูลจะอนุญาตให้ใช้สตริงรูปแบบตามที่ออกแบบมา: สำหรับการสร้างสตริงด้วยส่วนผสมของตัวอักษรและค่า
noamtm

13
เช่นเดียวกับโน้ตให้ฉันมีแนวโน้มไปโต้แย้งว่าprintf("%s", x ? "true" : "false");เป็นดีกว่าว่าprintf(x ? "true" : "false");- คุณอยู่ในรวมการควบคุมของสตริงรูปแบบที่นี่จึงมีไม่มีอันตรายว่ามันจะได้รับสิ่งที่ต้องการ"%d"ที่จะทำให้เกิดปัญหา fputsบนมืออื่น ๆ ที่เป็นตัวเลือกที่ดี
paxdiablo

15
ทำไมfputs"ดียิ่งขึ้น"? ฉันมักจะมองหาวิธีการปรับปรุงซีภายใต้สถานการณ์ของฉันสิ่งที่ฉันควรใช้fputsแทนprintf?
Arc676

10
@ Arc676 สำหรับสตริงที่ไม่มีการจัดรูปแบบ fputs นั้นเร็วและง่ายกว่า printf (ซึ่งต้องแยกสตริงเพื่อค้นหาการจัดรูปแบบตัวอักษร) การใช้ fputs (stdout) แทนที่จะเพียงแค่วาง () (ซึ่งเป็นค่าเริ่มต้นไปที่ stdout) จะกำจัด newline ที่ทำให้ () ต่อท้ายเอาต์พุต
ชาด

45

ไม่มีตัวระบุรูปแบบสำหรับบูล คุณสามารถพิมพ์โดยใช้ specifiers ที่มีอยู่บางตัวเพื่อพิมพ์ integral type หรือทำสิ่งที่แฟนซีมากขึ้น:

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

ไม่จำเป็นต้องร่าย

@ H2CO3 ยังไงก็ตามฉันได้แนะนำวิธีการแก้ปัญหาการพิมพ์ "จริง" และ "เท็จ" เป็นคำขอ OP ฉันยังเปลี่ยนถ้อยคำของฉันเล็กน้อยในส่วนที่คุณพูดถึง
Ivaylo Strandjev

5
@IvayloStrandjev: ใช่มีเป็นboolประเภทใน C เพียงแค่ไม่ได้อยู่ในรุ่น C89 - การเป็นส่วนหนึ่งของมันของสเปคภาษา C99 มีคำหลักใหม่เป็น_Boolและถ้าคุณรวม<stdbool.h>แล้วเป็นคำพ้องสำหรับbool _Bool
Adam Rosenfield

30

ANSI C99 / C11 ไม่ได้มีระบุ printf boolแปลงพิเศษสำหรับ

แต่ห้องสมุด GNU C มี API สำหรับการเพิ่ม specifiers

ตัวอย่าง:

#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;
}

เนื่องจากเป็นส่วนขยาย glibc GCC จึงเตือนเกี่ยวกับตัวระบุที่กำหนดเอง:

$ gcc -Wall -g main.c -o main
main.c: ในฟังก์ชั่น 'main':
main.c: 34: 3: คำเตือน: ไม่รู้จักอักขระประเภทการแปลง 'B' ในรูปแบบ [- รูปแบบ =]
   r = printf ("ผลลัพธ์คือ:% B \ n", b);
   ^
main.c: 34: 3: คำเตือน: มีอาร์กิวเมนต์มากเกินไปสำหรับรูปแบบ [- รูปแบบ - ส่วนเสริมพิเศษ]

เอาท์พุท:

$ ./main
ผลลัพธ์คือ: false
(เขียน 21 ตัวอักษร)
$ ./main 1
ผลลัพธ์คือ: จริง
(เขียน 20 ตัวอักษร)

12

ในประเพณีของitoa():

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

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

5
btoaคือ "สตริงไบนารีถึงเบส 64 สตริง" ใน JavaScript ที่ไม่ได้มาตรฐาน (Gecko และ WebKit) ดังนั้นคุณอาจต้องการใช้ชื่ออื่น
panzi

26
@panzi: ฉันไม่แน่ใจว่ามันคุ้มค่ากับความพยายามที่โปรแกรมเมอร์ C ต้องกังวลเกี่ยวกับตัวระบุ JavaScript ที่ไม่ได้มาตรฐาน
Keith Thompson

5
@ KeithThompson ฉันคิดว่าฉันสับสนคำถามและคิดว่านี่เป็นเรื่องเกี่ยวกับ JavaScript ซึ่งไม่สมเหตุสมผลเลย มันอาจจะเป็นตอนดึก
panzi

9
หรือสำหรับผู้ที่มีความคิดมากยิ่งขึ้นในหมู่พวกเรา: "true\0false"[(!x)*5]:-)
paxdiablo

1
@MooingDuck: !!x*5maybe
jxh


2

ถ้าคุณชอบ C ++ ดีกว่า C คุณสามารถลอง:

#include <ios>
#include <iostream>

bool b = IsSomethingTrue();
std::cout << std::boolalpha << b;

5
คำตอบนี้อยู่นอกหัวข้อและควรถูกลบเนื่องจากเป็นเรื่องเกี่ยวกับภาษาอื่นมากกว่าคำตอบ
Lundin

2
@Lundin ฉันไม่เห็นด้วยว่าควรลบ เป้าหมายของ SO นั้นไม่เพียง แต่ช่วยคนเดียวเท่านั้น แต่ยังช่วยคนทุกคนด้วยคำถามเดียวกัน เมื่อฉันค้นหาsprintf print boolean เป็นจริงเท็จ c ++นี่คือหน้าแรกที่ปรากฏขึ้น (แม้ว่าเนื้อหาหน้านี้อาจเป็นผลลัพธ์อันดับต้น ๆ หากไม่มีคำตอบนี้) เนื่องจาก C ++ นั้นเกือบจะเป็นชุดของ C ดังนั้นฉันจึงไม่คิดว่าคำตอบดังกล่าวควรถูกยกเลิกได้ง่ายนัก +1 จากฉัน
Jeff G

1
@JeffG ใช่คำตอบดังกล่าวควรถูกลบออกเรามีนโยบายที่ชัดเจนมาก อ่านแท็ก C และ C ++ คำถามนี้ไม่เป็นประโยชน์สำหรับโปรแกรมเมอร์ C โดยเฉพาะอย่างยิ่งเนื่องจากระบบบูลีน C และ C ++ นั้นแตกต่างกันอย่างสิ้นเชิงและคำถามถูกติดแท็ก C. Google ไม่สามารถเข้าใจสอง trailing ++ ในการค้นหาของคุณไม่ใช่ปัญหาของ SO
Lundin

2
@Lundin ความคิดเห็นของฉันไม่ได้ถูกตีความว่าเป็นความคิดเห็นเกี่ยวกับนโยบายของ SO มันเป็นความคิดเห็นจริงๆเกี่ยวกับว่าคำตอบนี้จะเพิ่มคำถามอย่างสร้างสรรค์หรือไม่ คำตอบนี้สามารถระบุได้ทันทีว่าเป็น C ++ - เท่านั้น ไม่มีใครมาที่นี่เพื่อรับคำตอบแบบ C เท่านั้นจะถูกหลอกให้คิดว่านี่จะทำงานใน C และเสียเวลาลองเลย อย่างไรก็ตามนี่เป็นคำตอบที่ดีสำหรับ C ++ หากคำตอบนั้นมีประโยชน์แม้ว่าพวกเขาจะไม่ได้ช่วย OP ก็ควรจะเก็บไว้หรือไม่? ฉันคิดว่าคำตอบที่สร้างสรรค์ที่ระบุชัดเจน caveats ไม่ควรถูกลบโดยไม่คำนึงถึงนโยบาย
Jeff G

1
@JeffG คุณสามารถนำมันมาใช้บนmeta.stackoverflow.comนี่ไม่ใช่สถานที่สำหรับการอภิปรายนี้
Lundin

2

หากต้องการพิมพ์ 1 หรือ 0 ตามค่าบูลีนที่ฉันเพิ่งใช้:

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

มีประโยชน์อย่างยิ่งกับ Flags:

#define MY_FLAG (1 << 4)
int flags = MY_FLAG;
printf("%d\n", !!(flags & MY_FLAG));

ระวังว่า!!อาจจะได้รับการเพิ่มประสิทธิภาพออกไป
ragerdl

1

ฉันต้องการคำตอบจากวิธีที่ดีที่สุดในการพิมพ์ผลลัพธ์ของบูลว่า 'เท็จ' หรือ 'จริง' ใน c? , เหมือนกับ

printf("%s\n", "false\0true"+6*x);
  • x == 0, "false \ 0true" + 0 "หมายถึง" false ";
  • x == 1, "false \ 0true" + 6 "หมายถึง" จริง ";

21
สิ่งนี้ไม่สามารถเข้าใจได้ทั้งหมด ฉันใช้เวลาสักพักก่อนที่ฉันจะค้นพบสิ่งที่"false\0true"+6*xทำจริงๆ หากคุณทำงานในโครงการกับคนอื่น ๆ หรือเพียงแค่ในรหัสโครงการที่คุณต้องการเข้าใจxปีต่อมาการก่อสร้างเช่นนี้จะต้องหลีกเลี่ยง
HelloGoodbye

3
แม้ว่าฉันจะเห็นว่าสิ่งนี้อาจได้รับการปรับให้เหมาะสมยิ่งขึ้นเนื่องจากเป็นแบบไร้สาขา หากความเร็วเป็นสิ่งที่คุณกังวลนี่อาจเป็นตัวเลือกเพียงให้แน่ใจว่าได้อธิบายกลไกหลังเคล็ดลับได้ดีในการแสดงความคิดเห็น ฟังก์ชั่นแบบอินไลน์หรือแมโครที่มีชื่อเอกสารด้วยตนเองก็จะเป็นประโยชน์ (แต่อาจไม่เพียงพอในกรณีนี้)
HelloGoodbye

3
เช่นเดียวกับความกังวลเกี่ยวกับการอ่านโปรดจำไว้ว่าสิ่งนี้จะระเบิดขึ้นถ้ามีคนผ่านค่าอื่นที่ไม่ใช่ 0 หรือ 1
plugwash

2
@plugwash คุณสามารถเปลี่ยนได้อย่างแน่นอนprintf("%s\n","false\0true"+6*(x?1:0));ซึ่งเป็นเพียง ... 5% อ่านน้อยกว่า
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; } เช่นเดียวกับstatic inline char decimal2char(int d) { assert(d >= 0 && d <= 9); return '0' + d; }; เพียงห่อไว้ในฟังก์ชั่นที่มีชื่ออธิบายและไม่ต้องกังวลกับความสามารถในการอ่าน
yyny
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.