程序员求职经验分享与学习资料整理平台

网站首页 > 文章精选 正文

C语言 I/O重定向(重定向c库函数printf到串口)

balukai 2025-03-26 09:41:46 文章精选 12 ℃

直接操作stdout

代码如下:

#include 
 
 int main(){
	    FILE *old_stdout = stdout;
	    stdout = fopen("output.log", "w"); // 重定向标准输出
	    printf("This goes to file");       // 输出到文件
	    fclose(stdout);
	    stdout = old_stdout;               // 恢复原输出
      printf("This goes to terminal\n");
 }

代码解析

1.保存原始的 stdout

FILE *old_stdout = stdout;
  • stdout 是标准输出流,默认指向终端(控制台)。
  • 这里将 stdout 的指针保存到 old_stdout 中,以便后续恢复。

2.重定向 stdout 到文件

stdout = fopen("output.log", "w"); // 重定向标准输出
  • 使用 fopen 打开一个文件 output.log,模式为 "w"(写模式,如果文件存在则清空内容,不存在则创建)。
  • 将 stdout 指向这个文件。此时,所有通过 printf 等标准输出函数的输出都会被写入 output.log,而不是终端。

3.输出到文件

printf("This goes to file"); // 输出到文件
  • 由于 stdout 已经被重定向到 output.log,printf 的输出会写入文件,而不是显示在终端。

4.关闭文件并恢复 stdout

fclose(stdout);              // 关闭文件
stdout = old_stdout;         // 恢复原输出
  • fclose(stdout):关闭文件流,确保所有缓冲数据写入文件。
  • stdout = old_stdout:将 stdout 恢复为原始的终端输出流。此时,printf 的输出会重新显示在终端。

代码的潜在问题

  1. 直接操作 stdout 的风险
  • 直接修改 stdout 可能会导致未定义行为,尤其是在多线程环境中。
  • 更安全的方式是使用 freopen,它会自动处理流的重定向和恢复。
  1. 文件打开失败
  • 如果 fopen 失败(例如文件无法创建),stdout 会被设置为 NULL,导致后续 printf 崩溃。
  • 应该检查 fopen 的返回值。

改进版本:使用 freopen

freopen 是专门用于重定向流的函数,更安全且符合标准。以下是改进后的代码:

#include 

int main() {
    // 保存原始的 stdout
    FILE *old_stdout = stdout;

    // 重定向 stdout 到文件
    if (freopen("output.log", "w", stdout) == NULL) {
        perror("Failed to redirect stdout");
        return 1;
    }

    // 输出到文件
    printf("This goes to file\n");
  
    // 先关闭当前的 stdout 流
     if (fclose(stdout) != 0) { 
        perror("Failed to close redirected stdout");
        return 1;
    }

    // 恢复 stdout   Unix/Linux 系统中,/dev/tty 表示当前终端设备,windows不支持
    if (freopen("/dev/tty", "w", stdout) == NULL) {
        perror("Failed to restore stdout");
        return 1;
    }
  
  	/*此写法能够支持windows,linux
     stdout = old_stdout; // 恢复原来的 stdout
     if (fflush(stdout) != 0) { // 确保缓冲区被刷新
          perror("Failed to flush stdout");
          return 1;
     }
   */

    // 输出到终端
    printf("This goes to terminal\n");

    return 0;
}

代码详解

  1. 使用 freopen 重定向
  • freopen("output.log", "w", stdout):将 stdout 重定向到 output.log。
  • 如果重定向失败,freopen 返回 NULL,可以安全处理错误。
  1. 恢复 stdout
  • 在 Unix/Linux 系统中,/dev/tty 表示当前终端设备。
  • 使用 freopen("/dev/tty", "w", stdout) 将 stdout 恢复为终端输出。
  1. 错误处理
  • 每次调用 freopen 后都检查返回值,确保重定向和恢复操作成功。

输出结果

  1. 文件 output.log 内容
This goes to file
  1. 终端输出
This goes to terminal

总结

方法

优点

缺点

直接操作 stdout

简单直观

不安全,可能导致未定义行为

使用 freopen

安全、标准、支持错误处理

需要额外代码处理恢复逻辑

使用 freopen,它是更安全、更标准的重定向方式。

最近发表
标签列表