【问题标题】:Is there a file pointer (FILE*) that points to nothing?是否有指向任何内容的文件指针 (FILE*)?
【发布时间】:2011-09-12 08:10:03
【问题描述】:

由于某些原因,我需要一个不指向任何内容的文件指针 (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
  • 因为fprintf的返回值对我来说很重要。
  • 在什么意义上重要?你想做什么?
  • 在某些操作系统上,您可以尝试fopen("/dev/null", "w"),但这不是一个很好的解决方案。更好的解决方案是使用其他方法来实现您在 fprintf 函数之外寻找的内容。
  • 为什么不使用sprintf呢?

标签: c++ file-pointer


【解决方案1】:

要解决您的实际问题(以 cmets 表示),请使用 snprintf 而不是 printf,前提是它在您的 C++ 实现中可用(这在 C++03 中不保证)。为缓冲区传入一个空指针,为大小传入 0。什么都不写,但是返回值是格式化字符串的长度(不包括nul终止符)。

[编辑:哎呀,我忘记了 Windows 上的 snprintf 不符合 C99。如果发生截断,它会返回错误,而不是所需的长度。对于 C++0x 需要符合 C99 标准的snprintf,我不知道他们会怎么做。]

要回答您的问题,您可以在类 UNIX 系统上打开 /dev/null 或在 Windows 上打开 nul。写入结果 FILE* 无效。但是,没有便携式零设备。

【讨论】:

    【解决方案2】:

    没有。

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 这应该是一个评论,但要回答它:因为这不会产生n请求的值。
      • @MSalters 这确实是一个答案。而且不要这么挑剔,很明显你在else部分设置了n=0
      • @Shabaz:显然PI = %f 的长度不是 0。这个建议甚至不会尝试产生请求的值 => 不是答案。
      • @MSalters:谢谢大家——我认为我的答案是最简单直接的答案(也是为了代码可读性)
      【解决方案4】:

      虽然正如 NirMH 所说,您可以将其附在if (nothing != NULL) 中,但还有另一种方法。您可以在读取模式下打开一个文件(使用"r"),当您将其发送到fprintf 时,写入将被忽略(编辑:如cmets 中所讨论的,请记住设置n=0,如果它是由返回的负数fprintf)。

      我个人建议第一种方法。我可能会做第二个的唯一原因是如果我不能更改功能。

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

      【讨论】:

      • 这是明确定义的行为吗?我不确定fprintf 是否必须产生正确的结果。特别是对只读文件进行操作时不能返回0(不写字符)吗?
      • 看这里:pubs.opengroup.org/onlinepubs/009695399/functions/printf.html 在返回值部分它显示If an output error was encountered, these functions shall return a negative value. 由于操作系统不允许写入以读取模式打开的文件,即使fprintf,此操作也会失败不检查它本身。所以,是的,它是定义明确的行为(可能不是直接定义的,而是连接你得到的链接)。而且,它不会返回 0,它会返回一个负值,如文档所述。
      • 即这证实了这种方法不起作用。负值不是“PI = %f 格式化后的长度”。
      • @Shahbaz 你不明白什么,OP 想知道PI = %f 的长度。 0 不是 n 的有效值。整个练习都是为了获得 n 的值。这样就可以为真正的缓冲区进行分配。每个人都知道将调用包含在条件中不会调用它。这不是问题所在。
      • @AjayBrahmakshatriya,你是对的。问题背后的意图正如你所说。不过,这个问题直接要求其他东西,未来的访问者会偶然发现这个问题,而不是基于提问者的意图,而是基于实际问题。
      【解决方案5】:

      你犯了一个设计错误。

      显然,您想知道的是写您的号码所需的字符数。

      您正在为此使用 _*printf_,这是个​​好主意。您只想计算“写入”的字符数,因此需要。但是你不想显示任何东西,所以你戳fprintf 而不仅仅是printf。但是 fprintf 如果没有要写入的 FILE 则无法工作...

      就像史蒂夫说的,你应该使用snprintf(),它会写入内存中的字符串。

      正如史蒂夫所说,带有 NULL 字符串的 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)
      

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

      【讨论】:

        【解决方案6】:

        你的意思是这样的吗?

        #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;
        }
        

        【讨论】:

          猜你喜欢
          • 2019-04-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多