有一个文件指针(FILE *)可以指向空吗?

3

由于某些原因,我需要一个指向空的文件指针(FILE*)。这意味着我可以将其传递给fprintf函数,并且fprintf会忽略该文件指针。

例如:

void my_function()
{
  FILE* nothing = NULL; // NULL is not correct.
  int n = fprintf(nothing, "PI = %f", 3.14); // Note: When nothing = NULL, error ocured.
}

有没有一个指向空的文件指针(FILE*)?

你想打印到哪里?如果你的意思是屏幕,尝试使用stdout - Adam M-W
我想要格式化后 "PI = %f" 的长度。 - Amir Saniyan
2
为什么不使用sprintf呢? - littleadv
你知道吗,你可以定义格式不超过X个字符等等...了解一下格式字符串,有一个选项可以指定最多允许%f占用的字符数(包括小数点后面的位数)。 - littleadv
由于此标签为C ++,因此可能有更好的C ++库解决方案。 Boost.Format应该尊重C格式字符串:http://codepad.org/xwLTIdJJ - visitor
显示剩余6条评论
6个回答

8
为解决您在评论中提到的实际问题,使用snprintf而不是printf,前提是它在您的C++实现中可用(这在C++03中不能保证)。将缓冲区传递给空指针,并将大小传递为0。没有写入任何内容,但返回值是格式化字符串的长度(不包括nul终止符)。
[编辑:糟糕,我忘记了Windows上的snprintf不符合C99标准。如果发生截断,则会返回错误,而不是所需长度。我不知道他们将如何处理C++0x需要符合C99的snprintf的事实。]
回答您的问题,您可以在类UNIX系统上打开/dev/null,在Windows上打开nul。对生成的FILE*的写入没有影响。然而,没有便携式的null-device。

6

不行。

你的代码将会导致运行时异常。例如,如果你使用的操作系统支持,你可以使用/dev/null,但在C++中没有内置类似的东西。


0

你正在犯一个设计错误。

显然,你想知道的是写入数字所需的字符数。

你正在使用 _*printf_ 来实现这个目标,这是一个好主意。你只需要计算“写入”的字符数,因此需要的字符数。但是你不想显示任何东西,所以你选择了 fprintf 而不是仅仅使用 printf。但是 fprintf 没有文件可写入...

像 Steve 说的那样,你应该使用 snprintf(),它可以将内容写入内存中的字符串。

正如 Steve 所说,提供一个空字符串的 snprintf 应该可以按预期工作,除了在 Windows 上。在 Windows 上,只需提供一个临时字符串,之后将其丢弃即可。

size_t computeNumCharsNeededToPrintMyStuff(double d)
{
    size_t ret = 0;
    size_t maxBuffSize = 100; // should be plenty enough

    char *tmpBuff = new char[maxBuffSize ];
    ret = snprintf(tmpBuff, maxBuffSize, "PI = %f", d);
    delete[] tmpBuff;

    return ret;
}

然后你只需要调用:

n = computeNumCharsNeededToPrintMyStuff(3.14)

(这个函数可以改进,以计算显示任何内容所需的大小,但我现在宁愿保持简单。)


0
为什么不用一个 if (NULL != nothing) 语句包装 fprintf 方法调用?

这本应该是一条注释,但是为了回答它:因为那样不会产生所请求的值 n - MSalters
@MSalters 这确实是一个答案。不要太挑剔了,显然你在else部分设置了n=0 - Shahbaz
1
@Shabaz:显然,PI = %f的长度不为0。这个建议甚至没有尝试产生所请求的值=>不是一个答案。 - MSalters
@MSalters:谢谢大家 - 我认为我的答案是最简单和直接的答案(也适用于代码可读性)。 - NirMH

0

虽然像NirMH所说,你可以将它包含在if (nothing != NULL)中,但还有另一种方法。你可以以读模式(使用"r")打开一个文件,当你将其发送到fprintf时,写入会被忽略(编辑:如评论中所讨论的那样,如果fprintf返回的是负数,请记得将n=0设置为0)。

我个人建议使用第一种方法。我可能只会使用第二种方法,如果我不能更改该函数。

如果你不关心你的代码是否依赖于系统,你可以在Linux中使用/dev/null,在Windows中使用nul等。


这是良好定义的行为吗?我不确定 fprintf 是否必须产生正确的结果。特别地,当在只读文件上操作时,它不能返回0(未写入任何字符)吗? - MSalters
看这里:http://pubs.opengroup.org/onlinepubs/009695399/functions/printf.html,在返回值部分写道:“如果遇到输出错误,则这些函数将返回负值。”由于操作系统不允许在读模式下打开的文件中写入,即使“fprintf”本身没有检查,此操作也会失败。因此,是的,它是良好定义的行为(也许不是直接定义的,但连接链接后你可以得到它)。而且,它不会返回“0”,而会返回如文档所述的负值。 - Shahbaz
即,这证实了该方法不起作用。负值并不是“格式化后PI =%f的长度”。 - MSalters
@Shahbaz,你不明白OP想知道PI = %f的长度。0不是n的有效值。整个练习是为了获得n的值,以便可以为实际缓冲区进行分配。每个人都知道将调用包含在条件中不会调用它。这不是问题所在。 - Ajay Brahmakshatriya
@AjayBrahmakshatriya,你说得对。问题背后的意图正如你所说。然而,问题直接询问了另外一件事情,未来的访问者将会根据实际问题而不是提问者的意图来查看这个问题。 - Shahbaz
话虽如此,整个问题有点无用,这里的信息都已过时(例如,Windows 的 snprintf 最终符合 C99 等)。 - Shahbaz

0
你是指像这样的东西吗?
#include <stdio.h>
int main()
{
    FILE *fdevnull = fopen("/dev/null", "w");
    printf("printf length=%d\n", fprintf(fdevnull, "Hello World '%s'=%f\n", "PI", 3.14159));
    fclose(fdevnull);
    return 0;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接