【问题标题】:Printing the structure using a single line in C?在 C 中使用单行打印结构?
【发布时间】:2015-12-21 07:29:07
【问题描述】:

在 C 中是否有任何可能的方式(通过使用任何函数或任何此类),以便我们可以使用单行以不同数据类型的结构打印内容? 比如说:

typedef struct ABC{
   int a;
   char b;
   long c;
}ABC1;

要打印它,我们需要编写: printf("%d %s %ld",ABC1.a,ABC1.b,ABC1.c)

任何其他方法,以便我可以打印 printf("????",????ABC1)??

【问题讨论】:

  • printf() 没有一些神奇的格式说明符可以正确识别任意用户定义的结构类型,并且无法计算出参数的类型,除非您在格式字符串中正确指定它。您可以创建一个知道如何以所需格式打印struct ABC 的函数,但它不知道如何打印其他结构类型。
  • 格式字符串应为"%d %c %ld" 以匹配实际参数。对实际问题的回答是否定的,C 没有“自省”能力来在运行时弄清楚 struct 是由什么组成的。要了解困难,请参阅Is there a way to print struct members in a loop without naming each member in C?
  • @dxiv 为什么必须在运行时计算出来?只需在编译时执行,请参阅下面的答案。

标签: c structure


【解决方案1】:

首先,代码可能无法编译。您已将 ABC1 定义为 ABC 结构的 typedef。 ABC1 不是变量,所以无法查看 ABC1.a 的内容。

假设您创建了一个 ABC1 类型的变量,您不能使用 printf 以“逻辑”格式“转储”结构的内容。 printf 函数接收一个内存地址并根据给定的字符串显示其内容。如果 printf 函数只有一个指向内存的指针(即一堆无法知道字节“类型”的字节),则它无法知道结构的格式。

【讨论】:

    【解决方案2】:

    没有。最好的解决方案是编写如下方法:

    1. void printABC(struct ABC*)
    2. char* abcToString(struct ABC*)(然后通过%s打印)。

    选项 2 可能更好,可用于写入文件等。

    【讨论】:

      【解决方案3】:

      Glibc 允许您为 printf 和家族建立自己的格式说明符,以便通过一些扩展来打印 UDT,否则这是不可能的。

      #include <stdio.h>
      #include <printf.h> /* For PA_POINTER */
      
      struct MyStruct
      {
          int a;
          double b;
      };
      
      struct print_info;
      int handler(FILE *stream, const struct print_info *i, 
              const void* const *args)
      {
          const struct MyStruct *ptr = *( (const struct MyStruct**) (*args) );
          int rc = fprintf(stream, "a: %d, b: %f\n", ptr->a, ptr->b);
      
          return rc;
      }
      
      int print_arginfo (const struct printf_info *info, size_t n,
                            int *argtypes)
      {
        if (n > 0)
          argtypes[0] = PA_POINTER;
        return 1;
      }
      
      int main(void)
      {
          struct MyStruct s = {55, -3.14};
          /* We're gonna use the M specifier */
          int spec = 'M';
          int rc = register_printf_function(spec, handler, print_arginfo);
      
          if (rc != 0)
              return 1;
      
          printf("%M", &s);
      
      };
      

      您可以找到文档here

      【讨论】:

        【解决方案4】:

        不,printf() 仅支持预定义数据类型的格式说明符,不支持用户定义数据类型 (struct)。而且printf()也没有办法自动学习你的struct的成员变量的类型。

        你需要滚动你自己的函数来完成你想要的任务。

        【讨论】:

          【解决方案5】:

          就像@john3136 说的那样。

          但这里是 1 的示例。

          void printABC(ABC1 *ABC) /* can also use 'struct ABC*' */
          {
             printf("%d %c %ld",ABC->a,ABC->b,ABC->c);
             /* Equivalent to the below */
             /* printf("%d %s %ld",(*ABC).a,(*ABC).b,(*ABC).c); */
          }
          

          所以现在每次你想打印整个内容时,你只需输入类似

          的内容
              ABC1 xyz;
          
              /* fill xyz here*/
          
              printABC(&xyz);
          

          它应该在一行中输入ABC1 内的所有内容。

          【讨论】:

          • 请注意:您将 ABC 作为指针传递,然后将ABC 1 作为对象使用。您应该在投票失败之前修复...
          • void printABC(struct *ABC) 这甚至无法编译。如果您的意思是 void printABC(struct ABC *abc) 可能,那么 ABC.a 需要是 abc-&gt;d 等等。
          • P.S.感谢@l3x,他刚刚更好地编辑了答案,但 printf 格式仍然是错误的(应该是 %c 而不是 %s)并且随后的 printABC(&amp;ABC1); 将无法编译,因为 ABC1 是类型定义。老实说,我不明白谁在 我之前的评论 @SergeBallesta 的初始评论之后支持这个答案。
          • @dxiv 抱歉,我错过了一对。现在应该没事了。
          • @l3x 现在看起来不错。虽然这基本上是你的答案,但如果你比较之前之后。这是一次值得称道的救援行动 ;-)
          【解决方案6】:

          如果您使用的是现代 C 编译器,则可以使用类型泛型宏:

          #include <stdio.h>
          
          typedef struct {
             int a;
             char b;
             long c;
          } ABC;
          
          // printf conversion specifiers:
          #define CS(x)   \
            _Generic((x), \
              int:  "%d", \
              char: "%c", \
              long: "%ld")
          
          
          int main (void)
          {
            ABC abc = {1, 'a', 2};
          
            printf(CS(abc.a), abc.a); printf(" ");
            printf(CS(abc.b), abc.b); printf(" ");
            printf(CS(abc.c), abc.c); printf(" ");
          
            return 0;
          }
          

          【讨论】:

            猜你喜欢
            • 2017-02-17
            • 2011-07-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-03-19
            • 1970-01-01
            • 1970-01-01
            • 2022-06-13
            相关资源
            最近更新 更多