在许多C库中,有一个printf样式的例程,如下所示:
int __vgprintf(void *info, (void)(*print_function(void*, char)), const char *format, va_list params);
将格式化提供的字符串并使用传入的信息值和每个字符依次调用print_function。像fprintf这样的函数将传递__vgprintf传入的文件参数和一个指向函数的指针,该函数将其void *转换为FILE *并将传入的字符输出到该文件。像snprintf这样的函数将创建一个包含char *和length的结构,并将该结构的地址传递给一个函数,该函数将在空间允许的情况下按顺序输出每个字符。
这种功能是否有任何标准,如果可以使用,例如一个人想要一个函数来输出任意格式到TCP端口?一种常见的方法是分配一个希望足够大的缓冲区,使用snprintf将数据放在那里,然后从缓冲区输出数据。但是,如果有一种标准方法可以指定打印格式化程序应该为每个字符调用用户提供的例程,那么看起来会更清晰。
答案 0 :(得分:2)
这种功能是否有任何标准,如果可以使用,例如一个人想要一个函数来输出任意格式到TCP端口?
您可以使用fdopen()
将文件描述符或套接字打包到FILE*
并将其传递到fprintf()
。但是,这不适用于非阻塞套接字。
首先在缓冲区中进行格式化会为您提供更大的灵活性,并能够将其与非阻塞套接字一起使用。
答案 1 :(得分:2)
open_memstream
是POSIX的标准配置,可能在即将推出的C1x标准中被标准化为C语言的一部分。但是,这不会为您提供任意回调;它要求整个输出适合内存,所以它实际上没有比使用snprintf
更好(可能由自动分配缓冲区的函数包装)。
在POSIX系统上,一种解决方案是将管道连接到新线程,然后使用dprintf
(或fdopen
和fprintf
)写入它。线程将在管道的另一端接收输入,并且可以随意处理它。当然这有点慢(每次刷新输出时至少有几个系统调用,如果你的内核太少,可能会进行上下文切换),但它可以满足您的需要。相同的方法适用于任何具有管道,线程和相当于fdopen
或dprintf
的系统,因此如果需要,您也应该能够在Windows上运行。
另一种方法是使用tmpfile
,fprintf
和fread
(所有标准C)。 tmpfile
的良好实现甚至可以在内存中创建虚拟文件,并推迟任何实际文件创建,直到调用fileno
或“文件”大小超过某个限制。
编辑:在重新阅读问题时,似乎OP只需要使用带有套接字的fprintf
。在这种情况下,fdopen
/ fprintf
或dprintf
会直接完成任务。
答案 2 :(得分:1)
非标准,但请查看Linux上的fopencookie
和BSD上的funopen
。也许可以将它们包装在应用程序的标准API中,因为它们非常相似。我相信Cygwin和Mac OS X也支持这两者中的至少一个。
这两个函数都允许您创建一个带有函数指针的FILE *
,用于读取,写入,搜索和关闭流。创建后,您可以fprintf
进入流。
答案 3 :(得分:0)
我严重怀疑有这样一个标准功能,但你当然可以创建自己的实现来试图模仿它。遗憾。