如何将cin和cout重定向到文件?

15 浏览
0 Comments

如何将cin和cout重定向到文件?

如何将cin重定向到in.txt,将cout重定向到out.txt

0
0 Comments

问题的原因是需要将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”对所有正在运行的线程都起作用。这可能吗?

它应该影响所有线程。也许你的代码还有一些缺失。顺便问一下,你是否尝试在创建其他线程之前进行重定向设置?试试看,看看是否有效。

0
0 Comments

如何将cin和cout重定向到文件?

在编程竞赛中,以下是一个有用的用于cin/cout的短代码片段:

#include 
using 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重定向可以通过以下方式实现:

#include 
using 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流在单个文件范围内重定向,这对于竞技编程很有用:

#include 
using 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重定向到文件的原因和解决方法。

0
0 Comments

在编写程序时,有时候我们需要将输入和输出重定向到文件中。下面是一种解决方法:

首先,我们需要包含头文件,并使用命名空间std。

然后,我们可以使用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()); - 只需要额外一行代码,并且是可移植的。所以并不是非常简单 🙂

当然,这取决于你是否需要可移植性。我查找这个问题的原因是为了测试编码挑战问题,所以我只需要一个快速简单的答案。显然,这与编写生产代码的需求非常不同。

0