C语言 如何将格式化数据附加到 printf() 调用



我想实现一个可变参数函数,它的行为类似于printf,只是它打印了一些前缀。例如,假设我希望前缀为time(0)的值。如果我打电话:

wrapped_printf("Hello, world %d", 5678);

我会期待这样的东西:

1571441246 Hello, world 5678

作为输出。

显然,替换格式字符串没什么大不了的;是可变参数业务给我带来了麻烦。我应该将其实现为...函数吗?拿va_list?我如何在前面加上我的额外参数?

这就是我现在所拥有的。它编译并运行(它甚至是有效的 C89...(,但额外的参数被搞砸了。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>
int wrapped_printf(const char* format_str, ...)
{
static const char* const prefix = "%d ";
static const size_t prefix_length = 3;
va_list ap;
size_t format_string_length = strlen(format_str);
char* const prefixed_format_str = malloc(format_string_length + prefix_length + 2);
/* 1 for the trailing '' and 1 for a line break */
if (prefixed_format_str == NULL) { exit(EXIT_FAILURE); }
strncpy(prefixed_format_str, prefix, prefix_length);
strncpy(prefixed_format_str + prefix_length, format_str, format_string_length);
prefixed_format_str[prefix_length + format_string_length] = 'n';
prefixed_format_str[prefix_length + format_string_length + 1] = '';
va_start(ap, format_str);
return printf(
prefixed_format_str,
(int) time(0),
ap);
va_end(ap);
}
int main()
{
wrapped_printf("Hello world %dn", 5678);
return EXIT_SUCCESS;
}

看到它在科利鲁失败了。

笔记:

  • 只需拨打一个电话 - 但它可以是printf()vprintf().
  • 可以使用一个大的字符串缓冲区,将前缀sprintf()到其中,然后sprintf()原始参数;但这也不是我的意思。
  • 我不介意使用特定于编译器的代码 - 但如果你建议这样做,请尝试在多个平台上覆盖多个编译器 - 尤其是带有 AMD64 处理器的 GNU/Linux 上的 GCC 或 clang。

完全不可能在普通 C 中将参数附加到可移植的va_list。这是肯定可以做到的,但它需要每个体系结构以及编译器调用约定的编译器级向导。

对于可移植的方式,像libffi这样的库和格式字符串的解析器...


我建议,如果可能的话,如果你有幸使用C99+,你可以改用宏;那么你可以用编译时字符串串联在格式字符串前面"%d ",并在参数中添加数字。但是格式需要是字符串文字。

或者,如果您确实需要使用函数,那么我不会受到不对前缀后跟这些前缀单独使用printf的限制 -输出将是行缓冲或完全缓冲的,因此不太可能有任何区别。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>
#define wrapped_printf_macro(f_, ...) 
printf("%lld " f_, (long long)time(0), __VA_ARGS__)
int wrapped_printf(const char* format_str, ...)
{
static const char* const prefix = "%d ";
static const size_t prefix_length = 3;
va_list ap;
printf("%lld ", (long long int)time(0));
va_start(ap, format_str);
vprintf(format_str, ap);
va_end(ap);
}

int main()
{
wrapped_printf_macro("Hello world %dn", 5678);
wrapped_printf("Hello world %dn", 5678);
return EXIT_SUCCESS;
}

相关内容

  • 没有找到相关文章

最新更新