Trình xác định định dạng printf cho bool là gì?


458

Vì ANSI C99 có _Boolhoặc boolthông qua stdbool.h. Nhưng cũng có một printfđịnh dạng định dạng cho bool?

Tôi có nghĩa là một cái gì đó giống như trong mã giả:

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

sẽ in:

true

1
Bạn có thể đọc thông tin này để biết thêm thông tin cplusplus.com/reference/cstdio/printf Bạn luôn có thể thực hiện điều đó!
Varvarigos Emmanouil


3
@billinkc, câu hỏi của tôi không thực sự về cách tốt nhất để in các giá trị bool - đó là về một công cụ xác định printf cụ thể. Mà dường như không tồn tại. Một góc khác cho một câu trả lời hay sẽ là: có lẽ có một cách để thêm một công cụ xác định định dạng tùy chỉnh vào printf thực hiện chuyển đổi bool ...
maxschlepzig

Đủ công bằng, mặc dù tôi dường như không có khả năng giải phóng VtC nên tôi sẽ phải chờ phiếu bầu của mình hết hạn.
billinkc

@maxschlepzig: cách duy nhất để giải quyết vấn đề là kiểm tra tài liệu. Nếu bạn sử dụng GNU / Linux (ví dụ: vì bạn không cho chúng tôi biết về hệ thống của bạn), bạn có thể đọc hướng dẫn sử dụng printf cập nhật trên [trang man Linux] (man7.org). Nếu bạn muốn in chuỗi "true" / "false", bạn có thể xây dựng chúng theo cách thủ công, điều này khá dễ dàng.
Bulat M.

Câu trả lời:


711

Không có định dạng định dạng cho boolcác loại. Tuy nhiên, vì bất kỳ loại tích phân nào ngắn hơn intđược quảng cáo intkhi được truyền cho printf()các đối số biến đổi, bạn có thể sử dụng %d:

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

Nhưng tại sao không:

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

hoặc tốt hơn:

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

hoặc, thậm chí tốt hơn:

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

thay thế?


21
Tôi sẽ +1 cái này nếu bạn thoát khỏi biểu thức không phải chuỗi đơn là chuỗi định dạng. Loại sử dụng này dễ dàng biến thành sử dụng không an toàn. printf("%s", x ? "true" : "false");sẽ khắc phục vấn đề.
R .. GitHub DỪNG GIÚP ICE

2
Đối với phần "tại sao không" của câu trả lời này - một công cụ xác định định dạng cho bool sẽ cho phép chuỗi định dạng được sử dụng như được thiết kế: để xây dựng một chuỗi có hỗn hợp các chữ và giá trị.
noamtm

13
Cũng giống như một lưu ý, tôi muốn có xu hướng tranh chấp đó printf("%s", x ? "true" : "false");tốt hơnprintf(x ? "true" : "false");- bạn đang ở trong tổng số kiểm soát của chuỗi định dạng ở đây do đó không nguy hiểm mà nó sẽ nhận được một cái gì đó như "%d"đó sẽ gây ra vấn đề. Mặt fputskhác, một lựa chọn tốt hơn.
paxdiablo

15
Tại sao fputs"thậm chí tốt hơn"? Tôi luôn tìm cách cải thiện C. Trong những trường hợp nào tôi nên sử dụng fputsthay vì printf?
Arc676

10
@ Arc676, đối với một chuỗi không có định dạng, fputs nhanh hơn và đơn giản hơn printf (phải phân tích chuỗi tìm kiếm ký tự định dạng). Sử dụng fputs (stdout) thay vì chỉ đặt () (mặc định cho stdout) sẽ loại bỏ dòng mới đặt () nối vào đầu ra.
Chad

45

Không có định dạng định dạng cho bool. Bạn có thể in nó bằng cách sử dụng một số chỉ định hiện có để in các loại tích phân hoặc làm một cái gì đó lạ mắt hơn:

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

Các diễn viên không cần thiết.

@ H2CO3 dù sao tôi đã đề xuất một giải pháp in "đúng" và "sai" theo yêu cầu của OP. Tôi cũng đã thay đổi một chút từ ngữ của tôi về phần bạn đề cập.
Ivaylo Strandjev

5
@IvayloStrandjev: Có, có một boolloại trong C, chỉ cần không có trong phiên bản C89 - đó là một phần của ngôn ngữ đặc tả C99. Có một từ khóa mới _Boolvà nếu bạn bao gồm <stdbool.h>, thì đó boollà một từ đồng nghĩa với _Bool.
Adam Rosenfield

30

ANSI C99 / C11 không bao gồm một công cụ xác định chuyển đổi printf bổ sung cho bool.

Nhưng thư viện GNU C cung cấp API để thêm các chỉ định tùy chỉnh .

Một ví dụ:

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

Vì nó là một phần mở rộng glibc, GCC cảnh báo về trình xác định tùy chỉnh đó:

$ gcc -Wall -g main.c -o chính
main.c: Trong chức năng 'chính':
main.c: 34: 3: cảnh báo: ký tự loại chuyển đổi không xác định 'B' ở định dạng [-Wformat =]
   r = printf ("Kết quả là:% B \ n", b);
   ^
main.c: 34: 3: cảnh báo: quá nhiều đối số cho định dạng [-Wformat-Extra-args]

Đầu ra:

$ ./ chính
Kết quả là: sai
(viết 21 ký tự)
$ ./ chính là 1
Kết quả là: đúng
(viết 20 ký tự)

12

Theo truyền thống của itoa():

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

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

5
btoalà "chuỗi nhị phân thành chuỗi 64 cơ sở" trong JavaScript không chuẩn (Gecko và WebKit), vì vậy bạn có thể muốn sử dụng một tên khác.
panzi

26
@panzi: Tôi không chắc rằng nó đáng để các lập trình viên C lo lắng về các định danh JavaScript không chuẩn.
Keith Thompson

5
@KeithThndry Tôi nghĩ rằng tôi đã nhầm lẫn các câu hỏi và bằng cách nào đó nghĩ rằng đây là về JavaScript, điều này không có ý nghĩa gì. Có lẽ đã khuya rồi.
panzi

9
Hoặc, đối với các ranh ma hơn giữa chúng ta: "true\0false"[(!x)*5]:-)
paxdiablo

1
@MooingDuck: có thể !!x*5.
jxh

4

Bạn không thể, nhưng bạn có thể in 0 hoặc 1

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

nguồn


2

Nếu bạn thích C ++ tốt hơn C, bạn có thể thử điều này:

#include <ios>
#include <iostream>

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

5
Câu trả lời này không có chủ đề và nên được xóa, vì đó là về một ngôn ngữ khác ngoài ngôn ngữ trong câu hỏi.
Lundin

2
@Lundin Tôi không đồng ý rằng điều này nên được xóa. Mục tiêu của SO không chỉ là giúp một người, mà là giúp tất cả những người có cùng câu hỏi. Khi tôi tìm kiếm sprintf in boolean là true false c ++ , đây là trang đầu tiên xuất hiện (mặc dù có thể cho rằng trang này có thể là kết quả hàng đầu nếu câu trả lời này không tồn tại). Vì C ++ gần như là một superset của C, tôi không nghĩ những câu trả lời như vậy nên dễ dàng bị loại bỏ. +1 từ tôi.
Jeff G

1
@JeffG Có câu trả lời như vậy nên được xóa, chúng tôi có chính sách rất rõ ràng. Đọc các wiki thẻ C và C ++. Câu hỏi này không hữu ích cho các lập trình viên C đặc biệt vì các hệ thống boolean C và C ++ hoàn toàn khác nhau và câu hỏi được gắn thẻ C. Rằng Google không thể hiểu hai dấu vết ++ trong tìm kiếm của bạn không phải là vấn đề của SO.
Lundin

2
@Lundin Nhận xét của tôi không có ý định được hiểu là nhận xét về chính sách của SO. Đó thực sự là một nhận xét về việc câu trả lời này có bổ sung cho câu hỏi hay không. Câu trả lời này ngay lập tức được xác định là C ++ - chỉ. Không ai đến đây vì câu trả lời chỉ có C sẽ bị lừa khi nghĩ rằng nó sẽ hoạt động trong C và lãng phí thời gian để thử nó. Tuy nhiên, đây là một câu trả lời tuyệt vời cho C ++. Nếu câu trả lời là hữu ích, ngay cả khi chúng không giúp OP, thì chúng có nên được giữ lại không? Tôi nghĩ rằng các câu trả lời mang tính xây dựng đã được xác định rõ ràng không bao giờ nên bị xóa, bất kể chính sách.
Jeff G

1
@JeffG Bạn có thể đưa nó lên meta.stackoverflow.com , đây không phải là nơi để có cuộc thảo luận này.
Lundin

2

Để chỉ in 1 hoặc 0 dựa trên giá trị boolean tôi vừa sử dụng:

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

Đặc biệt hữu ích với Cờ:

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

Coi chừng rằng !!có thể được tối ưu hóa đi
ragerdl

1

Tôi thích một câu trả lời từ Cách tốt nhất để in kết quả của một bool là 'false' hoặc 'true' trong c? , giống như

printf("%s\n", "false\0true"+6*x);
  • x == 0, "false \ 0true" + 0 "có nghĩa là" sai ";
  • x == 1, "false \ 0true" + 6 "có nghĩa là" đúng ";

21
Điều này là hoàn toàn không thể hiểu được. Nó đã cho tôi một thời gian tốt trước khi tôi tìm ra những gì "false\0true"+6*xthực sự đã làm. Nếu bạn làm việc trong một dự án với những người khác, hoặc chỉ trong một dự án với một cơ sở mã bạn muốn hiểu x năm sau, thì những công trình như thế này là điều nên tránh.
HelloGoodbye

3
Mặc dù tôi thấy rằng điều này có thể được tối ưu hóa hơn vì nó không có chi nhánh. Nếu tốc độ là mối quan tâm của bạn, đây có thể là một lựa chọn, chỉ cần đảm bảo giải thích các cơ chế đằng sau thủ thuật trong một bình luận. Hàm nội tuyến hoặc macro có tên tự ghi cũng sẽ hữu ích (nhưng có lẽ không đủ trong trường hợp này).
HelloGoodbye

3
Cũng như những lo ngại về khả năng đọc có thể nhớ rằng điều này sẽ nổ tung nếu ai đó vượt qua một giá trị khác 0 hoặc 1.
plugwash

2
@plugwash Tất nhiên bạn có thể thay đổi nó thành printf("%s\n","false\0true"+6*(x?1:0));chỉ ... 5% ít đọc hơn.
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; } Tương tự như với static inline char decimal2char(int d) { assert(d >= 0 && d <= 9); return '0' + d; }; chỉ cần bọc nó trong một chức năng được mô tả và không lo lắng về tính dễ đọc của nó.
yyny
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.