c/c++重定向


这个对经常在OJ上做题的童鞋们很有用。OJ基本都是用标准输入输出(USACO除外)。但如果你在调试的时候也都是从控制台输入,那就太浪费宝贵的时间了。我们可以重定向标准输入,调试的时候从文件读,提交时从标准输入读。
在C语言中,方法比较简单。使用函数freopen():
freopen("data.in","r",stdin);
freopen("data.out","w",stdout);
这样就把标准输入重定向到了data.in文件,标准输出重定向到了data.out文件。
这两句代码之后,scanf函数就会从data.in文件里读,而printf函数就会输出到data.out文件里了。
C++中,对流重定向有两个重载函数:
streambuf* rdbuf () const;
streambuf* rdbuf (streambuf*
就相当于get/set方法。

code
streambuf *backup;
ifstream fin;
fin.open("data.in");
backup = cin.rdbuf();   // back up cin's streambuf
cin.rdbuf(fin.rdbuf()); // assign file's streambuf to cin
// ... cin will read from file
cin.rdbuf(backup);     // restore cin's original streambuf


注意最后我们使用了cin.rdbuf(backup)把cin又重定向回了控制台
然而,如果用C语言实现同样的功能就不那么优雅了。
因为标准控制台设备文件的名字是与操作系统相关的。
在Dos/Windows中,名字是con
freopen("con", "r", stdin);
在Linux中,控制台设备是/dev/console
freopen("/dev/console", "r", stdin);
另外,在类unix系统中,也可以使用dup系统调用来预先复制一份原始的stdin句柄。

以下是一个简单的 C++ 代码示例,用于实现一个支持基本 I/O 重定向的 shell: ```cpp #include <iostream> #include <string> #include <vector> #include <cstring> #include <unistd.h> #include <sys/wait.h> #include <fcntl.h> // 分割命令行输入为命令和参数 std::vector<std::string> split(const std::string& input, char delimiter) { std::vector<std::string> tokens; std::string token; for (char c : input) { if (c == delimiter) { if (!token.empty()) { tokens.push_back(token); token.clear(); } } else { token += c; } } if (!token.empty()) { tokens.push_back(token); } return tokens; } // 执行命令 void executeCommand(const std::vector<std::string>& args, const std::string& inputFile, const std::string& outputFile) { pid_t pid = fork(); if (pid < 0) { std::cerr << "Fork failed" << std::endl; return; } else if (pid == 0) { // 子进程 if (!inputFile.empty()) { int fd = open(inputFile.c_str(), O_RDONLY); if (fd < 0) { std::cerr << "Failed to open input file" << std::endl; exit(EXIT_FAILURE); } dup2(fd, STDIN_FILENO); close(fd); } if (!outputFile.empty()) { int fd = open(outputFile.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0644); if (fd < 0) { std::cerr << "Failed to open output file" << std::endl; exit(EXIT_FAILURE); } dup2(fd, STDOUT_FILENO); close(fd); } std::vector<char*> c_args; for (const auto& arg : args) { c_args.push_back(const_cast<char*>(arg.c_str())); } c_args.push_back(nullptr); execvp(c_args[0], c_args.data()); std::cerr << "Command execution failed" << std::endl; exit(EXIT_FAILURE); } else { // 父进程 wait(nullptr); } } // 解析命令行输入,处理重定向 void parseAndExecute(const std::string& input) { std::string command; std::string inputFile; std::string outputFile; auto parts = split(input, '>'); if (parts.size() > 1) { command = parts[0]; outputFile = parts[1]; } else { parts = split(input, '<'); if (parts.size() > 1) { command = parts[0]; inputFile = parts[1]; } else { command = input; } } auto args = split(command, ' '); executeCommand(args, inputFile, outputFile); } int main() { std::string input; while (true) { std::cout << "$ "; std::getline(std::cin, input); if (input == "exit") { break; } parseAndExecute(input); } return 0; } ``` ### 代码说明 1. **`split` 函数**:用于将输入的命令行字符串按指定分隔符分割成多个部分。 2. **`executeCommand` 函数**:创建子进程执行命令,处理输入输出重定向。 3. **`parseAndExecute` 函数**:解析命令行输入,识别重定向符号并提取输入输出文件名。 4. **`main` 函数**:提供一个简单的 shell 界面,循环读取用户输入并执行命令。 ### 编译和运行 将上述代码保存为 `shell.cpp`,使用以下命令编译: ```sh g++ shell.cpp -o shell ``` 运行编译后的程序: ```sh ./shell ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值