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

fykwrbwg  于 2023-05-22  发布在  其他
关注(0)|答案(8)|浏览(147)

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

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

要打印这个,我们需要写:printf("%d %s %ld",ABC1.a,ABC1.b,ABC1.c)
有没有其他方法可以像printf("????",????ABC1)一样打印??

bqujaahr

bqujaahr1#

首先,代码可能无法编译。您已经将ABC1定义为ABC结构的typedef。ABC1不是变量,因此无法查看ABC1.a的内容。
假设您创建了一个ABC1类型的变量,您不能使用printf以“逻辑”格式“转储”结构的内容。printf函数接收一个内存地址,并根据给定的字符串显示其内容。如果printf函数只有一个指向内存的指针(即,一堆字节,无法知道字节的“类型”)。

uemypmqf

uemypmqf2#

不,最好的解决方案是写一个像这样的方法:

  1. void printABC(struct ABC*)
  2. char* abcToString(struct ABC*)(然后通过%s打印)。
    选项2可能更好,可以用于例如写入文件等。
nwo49xxi

nwo49xxi3#

Glibc允许您为printf和family建立自己的格式说明符,以便通过一些扩展打印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);

};

您可以在这里找到文档。

xj3cbfub

xj3cbfub4#

不支持,printf()只支持预定义数据类型的格式说明符,不支持用户定义的数据类型(struct)。此外,printf()也无法自动 * 学习 * struct的成员变量类型。
你需要滚动你自己的函数来实现你想要的任务。

9jyewag0

9jyewag05#

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

7hiiyaii

7hiiyaii6#

如果你使用的是一个比较现代的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;
}
s71maibg

s71maibg7#

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

#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));
5uzkadbs

5uzkadbs8#

你可以用一个宏来描述这个结构,然后这个宏可以用来帮助创建结构定义,和漂亮的打印机。
因此,您的代码可能看起来像这样:

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

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

其优点是,如果您以相同的方式定义另一个结构,您将获得一个可用的新打印函数。

PSTRUCT(XYZ, (int, x), (double, y), (const char *, z));

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's answer相同。迭代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__)

它的工作原理在a different answer of mine中有简要描述。
为简单起见,忽略空结构情况。
在线试用!

相关问题