如何将cin和cout重定向到文件?
问题的原因是需要将cin和cout重定向到文件,解决方法是使用ifstream和ofstream以及streambuf类来实现。
下面是一个工作示例,代码中的每一行都有注释说明其功能:
#include#include #include void f() { std::string line; while(std::getline(std::cin, line)) //从文件in.txt中输入 { std::cout << line << "\n"; //输出到文件out.txt } } int main() { std::ifstream in("in.txt"); std::streambuf *cinbuf = std::cin.rdbuf(); //保存旧的buf std::cin.rdbuf(in.rdbuf()); //重定向std::cin到in.txt! std::ofstream out("out.txt"); std::streambuf *coutbuf = std::cout.rdbuf(); //保存旧的buf std::cout.rdbuf(out.rdbuf()); //重定向std::cout到out.txt! std::string word; std::cin >> word; //从文件in.txt中输入 std::cout << word << " "; //输出到文件out.txt f(); //调用函数 std::cin.rdbuf(cinbuf); //重新设置为标准输入 std::cout.rdbuf(coutbuf); //重新设置为标准输出 std::cin >> word; //从标准输入中输入 std::cout << word; //输出到标准输出 }
你可以将保存和重定向合并为一行:
auto cinbuf = std::cin.rdbuf(in.rdbuf()); //保存和重定向
`std::cin.rdbuf(in.rdbuf())`将`std::cin`的缓冲区设置为`in.rdbuf()`,然后返回与`std::cin`关联的旧缓冲区。对于`std::cout`或任何其他流都可以使用相同的方法。
在重置cin和cout到标准IO之前,需要关闭文件吗?
:不需要。如果需要的话,可以使用`in`和`out`从`in.txt`和`out.txt`中读取和写入。而且,当`in`和`out`超出范围时,文件会自动关闭。
我喜欢这个解决方案胜过使用`freopen`,因为如果我使用`freopen`,就无法再获得`stdout`。[stackoverflow.com/questions/26699524/…](https://stackoverflow.com/questions/26699524)
如果我不想保留cin或cout的旧buf,我应该删除它们吗?
我尝试了这个解决方案,但是出现了“**** stack smashing detected ***”的错误。这在某些情况下是预期结果吗?
:除了这个解决方案所建议的之外,你还做了其他的事情吗?我确定你在这里做了更多的事情。你能否发布一个能复现错误的最小代码,以及你得到的错误信息的截图?在Github上创建一个gist并在这里分享链接。
谢谢,的确是我的问题。不过,我发现在同一个线程中执行“cout重定向”的所有输出都会被写入文件。但是,来自其他线程的所有“cout”都不会被写入文件,但它们仍然被禁止,并不显示在屏幕上。我希望重定向“cout”对所有正在运行的线程都起作用。这可能吗?
它应该影响所有线程。也许你的代码还有一些缺失。顺便问一下,你是否尝试在创建其他线程之前进行重定向设置?试试看,看看是否有效。
如何将cin和cout重定向到文件?
在编程竞赛中,以下是一个有用的用于cin/cout的短代码片段:
#includeusing namespace std; int main() { ifstream cin("input.txt"); ofstream cout("output.txt"); int a, b; cin >> a >> b; cout << a + b << endl; }
这种方法的另一个好处是普通的fstream比同步的stdio流更快。
但是这种方法只适用于单个函数的范围内。
全局cin/cout重定向可以通过以下方式实现:
#includeusing namespace std; void func() { int a, b; std::cin >> a >> b; std::cout << a + b << endl; } int main() { ifstream cin("input.txt"); ofstream cout("output.txt"); // 可选的性能优化 ios_base::sync_with_stdio(false); std::cin.tie(0); std::cin.rdbuf(cin.rdbuf()); std::cout.rdbuf(cout.rdbuf()); func(); }
需要注意的是,`ios_base::sync_with_stdio`也会重置`std::cin.rdbuf`,所以顺序很重要。
还可以轻松地将标准IO流在单个文件范围内重定向,这对于竞技编程很有用:
#includeusing std::endl; std::ifstream cin("input.txt"); std::ofstream cout("output.txt"); int a, b; void read() { cin >> a >> b; } void write() { cout << a + b << endl; } int main() { read(); write(); }
但在这种情况下,我们必须逐个选择std声明,并避免使用`using namespace std`,否则会产生歧义错误:
error: reference to 'cin' is ambiguous cin >> a >> b; ^ note: candidates are: std::ifstream cin ifstream cin("input.txt"); ^ In file test.cpp std::istream std::cin extern istream cin; /// Linked to standard input ^
根据上面的内容,我们可以得出如何将cin和cout重定向到文件的原因和解决方法。
在编写程序时,有时候我们需要将输入和输出重定向到文件中。下面是一种解决方法:
首先,我们需要包含头文件
然后,我们可以使用freopen函数将输出重定向到文件中。具体而言,我们可以使用freopen("output.txt","w",stdout)将输出重定向到名为"output.txt"的文件中。
接下来,我们可以使用cout来输出内容。例如,我们可以使用cout<<"write in file"来将"write in file"写入文件中。
最后,我们可以在main函数中返回0来结束程序。
需要注意的是,上述方法同时也会将printf函数的输出重定向到文件中,这在某些情况下可能是有益的。
根据我的了解,stdout和cout始终保持同步。
然而,当我们设置std::sync_with_stdio(false)时,stdout和cout就不再同步。尽管默认情况下它被设置为true。
这种方法有一些不太美观之处,我们应该使用iostream库的std命名空间,而不是stdio库的std命名空间。
为什么呢?因为C++标准并不要求iostream库使用stdio库,所以这种方法不具备可移植性。之所以这个答案看起来更简单,是因为原始答案提供了更多信息和设置和保留的示例。
如果两种方法在功能上相等,C++的等效方法应该是ofstream out("out.txt"); cout.rdbuf(out.rdbuf()); - 只需要额外一行代码,并且是可移植的。所以并不是非常简单 🙂
当然,这取决于你是否需要可移植性。我查找这个问题的原因是为了测试编码挑战问题,所以我只需要一个快速简单的答案。显然,这与编写生产代码的需求非常不同。