【问题标题】:What is the printf format specifier for bool?bool 的 printf 格式说明符是什么?
【发布时间】:2013-06-22 20:05:10
【问题描述】:

由于 ANSI C99,有 _Boolbool 通过 stdbool.h。但是是否还有 printf 用于 bool 的格式说明符?

我的意思是类似于那个伪代码:

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

将打印:

true

【问题讨论】:

  • 你可以阅读这篇文章以获取更多信息cplusplus.com/reference/cstdio/printf你总是可以做到的!
  • @billinkc,我的问题实际上并不是关于打印 bool 值的最佳方法 - 它是关于具体的 printf 说明符。这似乎不存在。一个不错的答案的另一个角度是:也许有一种方法可以将自定义格式说明符添加到 printf 进行 bool 转换...
  • 很公平,虽然我似乎没有能力取消 VtC,所以我只需要等待我的投票到期。
  • @maxschlepzig:解决问题的唯一方法是检查文档。如果您使用 GNU/Linux(例如,因为您没有告诉我们您的系统),您可以在 [Linux 手册页](man7.org) 上阅读最新的 printf 手册。如果要打印“true”/“false”字符串,可以手动构造它们,非常简单。

标签: c++ c boolean printf


【解决方案1】:

bool 没有格式说明符。您可以使用一些现有的用于打印整数类型的说明符来打印它,或者做一些更花哨的事情:

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

【讨论】:

  • @H2CO3 无论如何,我建议了一个解决方案,将“true”和“false”打印为 OP 请求。你提到的那部分我也稍微改变了措辞。
  • @IvayloStrandjev:是的,在 C 中一个 bool 类型,只是在 C89 版本中没有——它是 C99 语言规范的一部分。有一个新关键字_Bool,如果包含<stdbool.h>,那么bool 就是_Bool 的同义词。
【解决方案2】:

bool 类型没有格式说明符。但是,由于任何小于int 的整数类型在传递给printf() 的可变参数时都会提升为int,因此您可以使用%d

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

但为什么不呢:

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

或者,更好:

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

或者,甚至更好:

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

改为?

【讨论】:

  • 如果您摆脱非单字符串文字表达式作为格式字符串,我会为此 +1。这种用法很容易变成不安全的用法。 printf("%s", x ? "true" : "false"); 会解决这个问题。
  • 作为说明,我倾向于质疑 printf("%s", x ? "true" : "false");printf(x ? "true" : "false");更好 - 你在 完全 控制此处的格式字符串,因此存在 no 的危险,即它会得到类似 "%d" 的东西,这会导致问题。另一方面,fputs更好的选择。
  • @HelloGoodbye,将单个char * 传递给printf() 被认为是不好的做法,因为它实际上应该是格式字符串,并且未转义的百分号可能会导致您的程序崩溃(@987654321 @)。因此,printf("%s", ...) 更安全。如果您一开始并没有进行任何实际的格式化,那么printf 系列函数就太过分了,而puts()(或fputs(),如果您需要打印到stderr)更可取因为它更高效/简洁。
  • 为什么fputs“更好”?我一直在寻找改进我的 C 的方法。在什么情况下我应该使用 fputs 而不是 printf
  • @Arc676,对于没有格式化的字符串,fputs 比 printf 更快更简单(它必须解析字符串以查找格式化字符)。使用 fputs(stdout) 而不仅仅是 puts()(默认为 stdout)消除了 puts() 附加到输出的换行符。
【解决方案3】:

根据我刚刚使用的布尔值打印 1 或 0:

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

对标志特别有用:

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

【讨论】:

  • 注意!! 可能会被优化掉
  • @interestedparty333:如果 MY_FLAG 等于 1,那么 !!(flags &amp; MY_FLAG) 可以被 (flags &amp; MY_FLAG) 替换,但是没有损坏的编译器将无法优化掉 !!,除非它可以证明操作数不能有除 0 或 1 以外的任何值。
【解决方案4】:

如果你比 C 更喜欢 C++,你可以试试这个:

#include <ios>
#include <iostream>

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

【讨论】:

  • 这个答案是题外话,应该删除,因为它是关于另一种语言而不是问题中的语言。
  • @Lundin 我不同意这应该被删除。 SO 的目标不仅仅是帮助一个人,而是帮助所有有相同问题的人。当我搜索sprintf print boolean as true false c++ 时,这是出现的第一页(尽管如果此答案不存在,this page 可能是最重要的结果)。由于 C++ 几乎是 C 的超集,我认为这样的答案不应该被轻易抛弃。来自我的 +1。
  • @JeffG 是的,应该删除这样的答案,我们有非常明确的政策。阅读 C 和 C++ 标签 wiki。这个问题对 C 程序员没有帮助特别是因为 C 和 C++ 布尔系统完全不同并且问题被标记为 C。Google 无法理解搜索中的两个尾随 ++不是 SO 的问题。
  • @Lundin 我的评论无意被解释为对 SO 政策的评论。这确实是关于这个答案是否对问题有建设性的评论。这个答案可以立即识别为仅限 C++。没有人来这里寻求纯 C 的答案会被欺骗认为这将在 C 中工作并浪费时间尝试它。但是,这对于 C++ 来说是一个很好的答案。如果答案有用,即使它们对 OP 没有帮助,那么不应该保留它们吗?我认为,无论政策如何,都不应删除明确指出警告的建设性答案。
  • @JeffG 你可以在meta.stackoverflow.com 上提出来,这里不是讨论的地方。
【解决方案5】:

我更喜欢Best way to print the result of a bool as 'false' or 'true' in c?的回答,就像

printf("%s\n", "false\0true"+6*x);
  • x == 0, "false\0true"+ 0" 表示“假”;
  • x == 1, "false\0true"+ 6" 表示“真”;

【讨论】:

  • 这完全无法理解。我花了好一阵子才弄清楚"false\0true"+6*x 到底做了什么。如果你和其他人一起在一个项目中工作,或者只是在一个你想在 x 年后理解代码库的项目中工作,那么应该避免这样的结构。
  • 虽然我看到这可能会更优化,因为它是无分支的。如果您关心速度,这可能是一个选择,只需确保在评论中很好地解释该技巧背后的机制。具有自记录名称的内联函数或宏也会有所帮助(但在这种情况下可能还不够)。
  • 除了对可读性的担忧之外,请记住,如果有人传入 0 或 1 以外的值,这将会崩溃。
  • @plugwash 您当然可以将其更改为 printf("%s\n","false\0true"+6*(x?1:0));,这只是... 5% 可读性降低。
  • 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 &gt;= 0 &amp;&amp; d &lt;= 9); return '0' + d; } 相同;只需将它包装在一个描述性命名的函数中,不要担心它的可读性。
【解决方案6】:

ANSI C99/C11 不包含用于 bool 的额外 printf 转换说明符。

但是GNU C library provides an API for adding custom 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”,格式为 [-Wformat=] r = printf("结果是:%B\n", b); ^ main.c:34:3:警告:格式参数过多 [-Wformat-extra-args]

输出:

$ ./main 结果是:假 (写 21 个字符) $ ./main 1 结果是:真 (写20个字)

【讨论】:

    【解决方案7】:

    按照itoa()的传统:

    #define btoa(x) ((x)?"true":"false")
    
    bool x = true;
    printf("%s\n", btoa(x));
    

    【讨论】:

    • btoa 是非标准 JavaScript(Gecko 和 WebKit)中的“二进制字符串到 base 64 字符串”,因此您可能需要使用不同的名称。
    • @panzi:我不确定 C 程序员是否值得为非标准的 JavaScript 标识符付出努力。
    • @KeithThompson 我想我混淆了这些问题,并且不知何故认为这是关于 JavaScript 的,无论如何这没有任何意义。应该是深夜了。
    • 或者,对于我们当中更狡猾的人:"true\0false"[(!x)*5] :-)
    • @MooingDuck:也许是!!x*5
    【解决方案8】:

    你不能,但你可以打印 0 或 1

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

    source

    【讨论】:

      猜你喜欢
      • 2013-06-22
      • 2018-11-22
      • 1970-01-01
      • 2020-12-04
      • 1970-01-01
      • 2017-11-16
      • 2012-05-17
      • 2012-05-17
      • 1970-01-01
      相关资源
      最近更新 更多