是否有任何 C 标准中定义的通用 printf-ish 例程

发布于 2024-10-22 02:25:04 字数 531 浏览 4 评论 0 原文

在许多 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* 和长度的结构,并将该结构的地址传递给一个函数,该函数将在空间允许的情况下按顺序输出每个字符。

对于这样的函数是否有任何标准,如果想要一个函数将任意格式输出到 TCP 端口,则可以使用该标准?一种常见的做法是分配一个希望足够大的缓冲区,使用 snprintf 将数据放在那里,然后从缓冲区中输出数据。不过,如果有一种标准方法来指定打印格式化程序应使用每个字符调用用户提供的例程,那么看起来会更干净。

In many C libraries, there is a printf-style routine which is something like the following:

int __vgprintf(void *info, (void)(*print_function(void*, char)), const char *format, va_list params);

which will format the supplied string and call print_function with the passed-in info value and each character in sequence. A function like fprintf will pass __vgprintf the passed-in file parameter and a pointer to a function which will cast its void* to a FILE* and output the passed-in character to that file. A function like snprintf will create a struct holding a char* and length, and pass the address of that struct to a function which will output each character in sequence, space permitting.

Is there any standard for such a function, which could be used if e.g. one wanted a function to output an arbitrary format to a TCP port? A common approach is to allocate a buffer one hopes is big enough, use snprintf to put the data there, and then output the data from the buffer. It would seem cleaner, though, if there were a standard way to to specify that the print formatter should call a user-supplied routine with each character.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

画离情绘悲伤 2024-10-29 02:25:04

这样的函数是否有任何标准,如果想要一个函数向 TCP 端口输出任意格式,可以使用该标准?

您可以使用 FILE* 中>fdopen() 并将其传递给 fprintf()。但是,这不适用于非阻塞套接字。

首先在缓冲区中进行格式化可以为您提供更大的灵活性以及将其与非阻塞套接字一起使用的能力。

Is there any standard for such a function, which could be used if e.g. one wanted a function to output an arbitrary format to a TCP port?

You can wrap a file descriptor or a socket into FILE* using fdopen() and pass it into fprintf(). However, this does not work with non-blocking sockets.

Formatting in a buffer first gives you much greater flexibility and the ability to use it with non-blocking sockets.

那一片橙海, 2024-10-29 02:25:04

open_memstream 是 POSIX 中的标准,并且可能在即将推出的 C1x 标准中被标准化为 C 语言的一部分。然而,这并不为您提供任意回调;它要求整个输出适合内存,因此它实际上并不比使用 snprintf (可能由自动分配缓冲区的函数包装)更好。

在 POSIX 系统上,一种解决方案是创建一个通往新线程的管道,然后使用 dprintf(或 fdopen 和 fprintf)写入它。线程将接收管道另一端的输入,并可以按照自己喜欢的方式处理它。当然,这有点慢(每次刷新输出时至少有几个系统调用,如果可用的核心太少,则可能需要上下文切换),但它可以满足您的要求。同样的方法适用于任何具有管道、线程以及 fdopendprintf 等价物的系统,因此如果需要,您也应该能够使其在 Windows 上工作。

另一种方法是使用 tmpfilefprintffread(均为标准 C)。 tmpfile 的良好实现甚至可以在内存中创建虚拟文件,并推迟任何实际文件的创建,直到调用 fileno 或“文件”大小超过特定限制。

编辑:重新阅读问题后,似乎OP只需要使用带有套接字的fprintf。在这种情况下,fdopen/fprintfdprintf 直接完成任务。

open_memstream is standard in POSIX, and might be standardized as part of the C language in the upcoming C1x standard. However this does not offer you an arbitrary callback; it requires that the whole output fit into memory, so it's really not any better than using snprintf (possibly wrapped by a function that automatically allocates a buffer).

On POSIX systems, one solution is to make a pipe to a new thread, and then use dprintf (or fdopen and fprintf) to write to it. The thread will receive the input on the other end of the pipe and can process it however it likes. Of course this is mildly slow (at least a couple syscalls every time output is flushed, and possibly a context switch if you have too few cores available) but it does what you want. The same approach will work on any system with pipes, threads, and the equivalent of fdopen or dprintf, so you should be able to make it work on Windows too if needed.

Another approach is to use tmpfile, fprintf, and fread (all standard C). A good implementation of tmpfile could even create a virtual file in memory, and postpone any actual file creation until fileno is called or the "file" size exceeds a certain limit.

Edit: Upon rereading the question, it seems OP just needs to use fprintf with sockets. In that case, fdopen/fprintf or dprintf accomplishes the task directly.

紫轩蝶泪 2024-10-29 02:25:04

非标准,但请查看 Linux 上的 fopencookie 和 BSD 上的 funopen。可以将它们包装在应用程序的标准 API 中,因为它们非常相似。我相信 Cygwin 和 Mac OS X 至少也支持两者之一。

这两个函数都允许您创建一个带有函数指针的FILE *,用于读取、写入、查找和关闭流。创建后,您可以fprintf 进入流。

Nonstandard, but take a look at fopencookie on Linux and funopen on BSD. It might be possible to have wrap them in a standard API from your application, since they're very similar. I believe that Cygwin and Mac OS X support at least one of the two as well.

Both functions allow you to create a FILE * with function pointers for reading, writing, seeking, and closing the stream. Once created, you can fprintf into the stream.

岁月蹉跎了容颜 2024-10-29 02:25:04

我严重怀疑是否存在这样的标准函数,但是您当然可以创建自己的实现来尝试和模仿它。对不起。

I seriously doubt there is such a standard function, but you can of course create your own implementation to try and mimic it. Sorry.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文