在 C 中使用单行打印结构?

问题描述 投票:0回答:8

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

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

要打印这个,我们需要写:

printf("%d %s %ld",ABC1.a,ABC1.b,ABC1.c)

任何其他方法,以便我可以像这样打印

printf("????",????ABC1)
??

c structure
8个回答
2
投票

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

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


2
投票

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

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

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


1
投票

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);

};

您可以在这里找到文档。


1
投票

不,

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

你需要滚动自己的函数来实现你想要的任务。


1
投票

就像@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
内的所有内容。


1
投票

如果您使用的是现代 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;
}

0
投票

一种方法是为格式字符串和相应的参数定义宏:

#define ABCformat "%d,%c:%ld"
#define ABCarg(x) (x).a, (x).b, (x).c

并像这样使用它:

   ABC1 abc = {1, 'c', 42};
   printf("abc=" ABCformat "\n", ABCarg(abc));

0
投票

您可以使用宏来描述结构,然后宏可以用来帮助创建结构定义和漂亮的打印机。

因此,您的代码可能如下所示:

PSTRUCT(ABC, (int, a), (char, b), (long, c));

int main () {
    ABC abc = {1, 'a', 2};
    printf("%s\n", tostring_ABC(&abc));
}

PSTRUCT
宏扩展为结构定义和遍历结构并将值发送到字符串中的函数。

#define PSTRUCT(N, ...) \
        typedef struct { XX(PSTRUCT_ARG, __VA_ARGS__) } N; \
        const char *tostring_##N (const N *x) { \
            static _Thread_local char buf[512]; \
            int len = 0; \
            XX(PSTRUCT_ARG_PRINT, __VA_ARGS__) \
            return buf; \
        }

有辅助宏可以将各个字段正确扩展到结构定义中并打印字段值。

#define PSTRUCT_ARG(X) PSTRUCT_ARG2 X
#define PSTRUCT_ARG2(X, Y) X Y;
#define PSTRUCT_ARG_PRINT(X) PSTRUCT_ARG_PRINT2 X
#define PSTRUCT_ARG_PRINT2(X, Y) \
        len += snprintf(buf+len, sizeof(buf)-len, CS(x->Y), #Y, x->Y);

CS
宏在Lundin 的回答中定义。迭代
XX
宏定义为:

#define XX(X, ...) \
        XX_X(__VA_ARGS__, XX_5, XX_4, XX_3, XX_2, XX_1) \
        (X, __VA_ARGS__)
#define XX_X(_1,_2,_3,_4,_5,X,...) X
#define XX_1(X, _)      X(_)
#define XX_2(X, _, ...) X(_) XX_1(X, __VA_ARGS__)
#define XX_3(X, _, ...) X(_) XX_2(X, __VA_ARGS__)
#define XX_4(X, _, ...) X(_) XX_3(X, __VA_ARGS__)
#define XX_5(X, _, ...) X(_) XX_4(X, __VA_ARGS__)

它是如何工作的在我的一个不同的答案中有简要描述。

为简单起见,忽略空结构情况。

在线试用!

© www.soinside.com 2019 - 2024. All rights reserved.