【问题标题】:Difference between fprintf, printf and sprintf?fprintf、printf 和 sprintf 的区别?
【发布时间】:2011-06-05 08:49:51
【问题描述】:

谁能用简单的英语举例说明printffprintfsprintf之间的区别?

它在什么流中?

在阅读“C 中的文件处理”时,我真的对这三者感到困惑。

【问题讨论】:

  • 通过编写一些示例代码来试验它们。这是清楚地了解它们之间的区别的非常简单的方法。
  • 首选 snprintf() 到 sprintf() 以避免愚蠢的缓冲区溢出。
  • 首选流或 Boost 格式化程序以避免愚蠢的缓冲区溢出和讨厌的类型不安全错误
  • @Maxim,虽然你提出了一个有效的观点,但我会确保我的缓冲区不会溢出并将我的应用程序炸成碎片。如果流/增强格式化程序被证明会导致明显的瓶颈,我只会查看这些函数。 :)
  • @Maxim:重点是,没必要。我的代码不是瓶颈。 5m/sec 是交换发送多少消息,而不是我们能够处理多少。那么为什么要过早优化呢?

标签: c io stream printf


【解决方案1】:

在 C 中,“流”是一种抽象;从程序的角度来看,它只是字节的生产者(输入流)或消费者(输出流)。它可以对应于磁盘上的文件、管道、终端或其他一些设备,例如打印机或 tty。 FILE 类型包含有关流的信息。通常,您不会直接弄乱FILE 对象的内容,您只需将指向它的指针传递给各种I/O 例程即可。

共有三个标准流:stdin 是指向标准输入流的指针,stdout 是指向标准输出流的指针,stderr 是指向标准错误输出流的指针。在交互式会话中,这三个通常指的是您的控制台,尽管您可以将它们重定向到指向其他文件或设备:

$ myprog < inputfile.dat > output.txt 2> errors.txt

在本例中,stdin 现在指向inputfile.datstdout 指向output.txtstderr 指向errors.txt

fprintf 将格式化文本写入您指定的输出流。

printf 相当于写入fprintf(stdout, ...),并将格式化文本写入标准输出流当前指向的任何位置。

sprintf 将格式化文本写入char 数组,而不是流。

【讨论】:

  • “它只是字节的生产者(输入流)或消费者(输出流)。”这些是倒退吗?生产者不会创造(输出)一些东西吗?问是因为我真的不知道。
  • @DaveVoyles:这些是从您的程序的角度来看的。输入流产生字节供程序读取;一个输出流使用你的程序产生的字节。
  • 对于任何想知道f 前缀/后缀是什么的人。我最初认为printf/sprintf/scanf中的f表示文件。但这只是表示格式
【解决方案2】:

printf 输出到标准输出流 (stdout)

fprintf 转到文件句柄 (FILE*)

sprintf 转到您分配的缓冲区。 (char*)

【讨论】:

    【解决方案3】:

    printf("format", args) 用于将数据打印到通常是计算机显示器的标准输出上。

    sprintf(char *, "format", args) 类似于 printf。它不是在标准输出(即监视器)上显示格式化的字符串,而是将格式化的数据存储在 char 指针(第一个参数)指向的字符串中。字符串位置是 printf 和 sprint 语法之间的唯一区别。

    fprintf(FILE *fp, "format", args) 再次类似于 printf。在这里,不是在监视器上显示数据,或者将其保存在某个字符串中,而是将格式化的数据保存在文件指针指向的文件中,该文件指针用作 fprintf 的第一个参数。文件指针是对 printf 语法的唯一补充。

    如果 stdout 文件作为 fprintf 中的第一个参数,则认为其工作与 printf 相同。

    【讨论】:

      【解决方案4】:

      printf(...) 等价于fprintf(stdout,...)

      fprintf 用于输出到流。

      sprintf(buffer,...) 用于将字符串格式化为缓冲区。

      注意还有vsprintfvfprintfvprintf

      【讨论】:

      • v 的口味我认为是非标准的
      • v 风格在 C 标准中非常肯定。
      • @larsmans:啊,好的。感谢您的更正。这个问题曾经被标记为 [c++]
      【解决方案5】:

      你还可以用 vsnprintf() 函数做一些非常有用的事情:

      $ cat test.cc
      #include <exception>
      #include <stdarg.h>
      #include <stdio.h>
      
      struct exception_fmt : std::exception
      {
          exception_fmt(char const* fmt, ...) __attribute__ ((format(printf,2,3)));
          char const* what() const throw() { return msg_; }
          char msg_[0x800];
      };
      
      exception_fmt::exception_fmt(char const* fmt, ...)
      {
          va_list ap;
          va_start(ap, fmt);
          vsnprintf(msg_, sizeof msg_, fmt, ap);
          va_end(ap);
      }
      
      int main(int ac, char** av)
      {
          throw exception_fmt("%s: bad number of arguments %d", *av, ac);
      }
      
      $ g++ -Wall -o test test.cc
      
      $ ./test
      terminate called after throwing an instance of 'exception_fmt'
        what():  ./test: bad number of arguments 1
      Aborted (core dumped)
      

      【讨论】:

      • +1 确实有用,但请注意 vsnprintf 是非标准函数。我见过的大多数实现都实现了这个或类似的东西,但它是特定于实现的。
      • @larsmans 上面提到这实际上是 C 标准的一部分,所以我收回了
      • 这和 C 有什么关系?
      【解决方案6】:

      打印

      1. printf 用于在屏幕上执行输出。
      2. 语法 = printf("control string ", argument );
      3. 与文件输入/输出无关

      fprintf

      1. 用于在 FILE 句柄指向的文件中执行写操作的 fprintf。
      2. 语法为fprintf (filename, "control string ", argument );
      3. 与文件输入/输出相关

      【讨论】:

      • 如果这是从其他地方引用的,最好用链接引用出处,但绝对仍然保留您在此处引用的文本。
      【解决方案7】:

      sprintf:将格式化数据写入内存中的字符串而不是标准输出

      sprintf 的语法是:

      #include <stdio.h>
      int sprintf (char *string, const char *format
      [,item [,item]…]);
      

      这里,

      String 是指向内存中要写入数据的缓冲区的指针。

      格式是指向定义格式的字符串的指针。

      每个项目都是一个变量或表达式,指定要写入的数据。

      如果操作成功,则 sprintf 返回的值大于或等于零,换句话说,写入的字符数,不包括终止空字符,如果发生错误,则返回小于零的值。

      printf:打印到标准输出

      printf 的语法是:

      printf format [argument]…
      

      sprintf() 和 printf() 的唯一区别是 sprintf() 将数据写入字符数组,而 printf() 将数据写入标准输出设备 stdout。

      【讨论】:

        【解决方案8】:

        fprintf 这与流有关,其中printf 是类似于fprintf 但与流无关的语句,即fprintf 与文件相关

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-10-28
          • 2012-09-20
          • 2017-04-18
          • 1970-01-01
          • 1970-01-01
          • 2014-01-31
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多