C语言标准流实战:stdin/stdout/stderr重定向的5个常见场景与代码示例

张开发
2026/5/18 10:42:29 15 分钟阅读
C语言标准流实战:stdin/stdout/stderr重定向的5个常见场景与代码示例
C语言标准流实战stdin/stdout/stderr重定向的5个常见场景与代码示例在Linux系统编程中标准输入输出流的重定向就像给程序安装了一个智能导流系统。想象一下你正在调试一个服务器程序突然发现关键错误信息被淹没在海量日志中——这就是stderr分离的价值。本文将用5个真实场景带你掌握C语言标准流操控的核心技巧。1. 日志分级存储分离stdout与stderr后台服务程序最头疼的问题就是日志混杂。下面这段代码演示如何将常规输出和错误日志分别写入不同文件#include stdio.h #include unistd.h int main() { // 模拟正常业务流程 for(int i0; i5; i) { printf(Processing item %d\n, i); // stdout if(i 3) { fprintf(stderr, [ERROR] Invalid data at index %d\n, i); // stderr } sleep(1); } return 0; }编译运行时的重定向技巧$ ./logger output.log 2 error.log关键点对比流类型默认输出缓冲方式典型重定向符号stdout屏幕行缓冲stderr屏幕无缓冲2提示在紧急调试时可以用21将stderr合并到stdout便于实时查看所有输出2. 自动化测试用文件模拟用户输入单元测试中经常需要模拟各种输入场景。这个例子展示如何用文本文件驱动测试流程#include stdio.h #include string.h #define MAX_LEN 100 void process_command(const char* input) { if(strcmp(input, start) 0) { printf(System initialized\n); } else if(strcmp(input, shutdown) 0) { fprintf(stderr, WARNING: System will power off\n); } else { printf(Unknown command: %s\n, input); } } int main() { char buffer[MAX_LEN]; while(fgets(buffer, MAX_LEN, stdin)) { buffer[strcspn(buffer, \n)] \0; // 去除换行符 process_command(buffer); } return 0; }测试用例文件test_input.txt内容start invalid shutdown执行测试$ ./test_program test_input.txt test_output.log 2 test_error.log3. 管道处理多程序协作的数据流水线Linux管道符|的本质就是stdout到stdin的重定向。这个数据清洗示例展示了三个程序的协作/* data_generator.c - 生成测试数据 */ #include stdio.h int main() { for(int i0; i10; i) { printf(%d,%d,%d\n, i, i*i, i%3); } return 0; } /* data_filter.c - 过滤异常数据 */ #include stdio.h int main() { int a,b,c; while(scanf(%d,%d,%d, a, b, c) 3) { if(c ! 0) { printf(%d,%d\n, a, b); } else { fprintf(stderr, Filtered: %d\n, a); } } return 0; } /* data_analyzer.c - 数据分析 */ #include stdio.h int main() { int x,y, sum0; while(scanf(%d,%d, x, y) 2) { sum y; printf(Current sum: %d\n, sum); } return 0; }构建数据处理流水线$ ./data_generator | ./data_filter 2 filtered.log | ./data_analyzer4. 动态重定向运行时切换输出目标某些场景需要在程序运行过程中灵活切换输出目标。这个配置解析器示例展示了freopen的用法#include stdio.h #include stdlib.h void set_log_file(const char* filename) { if(freopen(filename, a, stdout) NULL) { perror(Failed to redirect stdout); exit(EXIT_FAILURE); } setvbuf(stdout, NULL, _IOLBF, 0); // 设置为行缓冲 } int main(int argc, char** argv) { printf(Initializing system...\n); if(argc 1) { set_log_file(argv[1]); } printf(Configuration loaded\n); fprintf(stderr, Debug messages still go to stderr\n); return 0; }运行示例$ ./redirect_demo # 输出到屏幕 $ ./redirect_demo app.log # 输出重定向到文件5. 错误处理进阶结合errno与stderr系统调用错误需要精确诊断。这个文件操作示例展示了错误处理的完整流程#include stdio.h #include errno.h #include string.h #include fcntl.h #include unistd.h void try_open_file(const char* filename) { int fd open(filename, O_RDONLY); if(fd -1) { int err errno; fprintf(stderr, [%s] Failed to open file: %s (errno%d)\n, __TIME__, strerror(err), err); return; } char buffer[256]; ssize_t n read(fd, buffer, sizeof(buffer)-1); if(n -1) { perror(Read error); } else { buffer[n] \0; printf(File content: %s\n, buffer); } close(fd); } int main() { try_open_file(existing.txt); try_open_file(nonexistent.txt); return 0; }典型输出File content: Hello world [14:25:36] Failed to open file: No such file or directory (errno2)错误处理要点立即保存errno值避免被后续调用覆盖使用perror或strerror转换错误代码在错误消息中包含时间戳等上下文信息通过stderr确保错误信息及时显示掌握这些标准流操控技巧后你可以构建更健壮的日志系统设计灵活的自动化测试方案创建高效的数据处理管道实现动态配置的输出系统编写专业的错误处理逻辑

更多文章