【问题标题】:How to redirect cin and cout to files?如何将 cin 和 cout 重定向到文件?
【发布时间】:2023-03-06 09:18:01
【问题描述】:

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

【问题讨论】:

标签: c++


【解决方案1】:

这是您想要做的工作示例。阅读 cmets 以了解代码中每一行的作用。我已经在我的电脑上用 gcc 4.6.1 测试过它;它工作正常。

#include <iostream>
#include <fstream>
#include <string>

void f()
{
    std::string line;
    while(std::getline(std::cin, line))  //input from the file in.txt
    {
        std::cout << line << "\n";   //output to the file out.txt
    }
}
int main()
{
    std::ifstream in("in.txt");
    std::streambuf *cinbuf = std::cin.rdbuf(); //save old buf
    std::cin.rdbuf(in.rdbuf()); //redirect std::cin to in.txt!

    std::ofstream out("out.txt");
    std::streambuf *coutbuf = std::cout.rdbuf(); //save old buf
    std::cout.rdbuf(out.rdbuf()); //redirect std::cout to out.txt!

    std::string word;
    std::cin >> word;           //input from the file in.txt
    std::cout << word << "  ";  //output to the file out.txt

    f(); //call function


    std::cin.rdbuf(cinbuf);   //reset to standard input again
    std::cout.rdbuf(coutbuf); //reset to standard output again

    std::cin >> word;   //input from the standard input
    std::cout << word;  //output to the standard input
}

您可以在一行中保存和重定向:

auto cinbuf = std::cin.rdbuf(in.rdbuf()); //save and redirect

这里std::cin.rdbuf(in.rdbuf()) 将std::cin's 缓冲区设置为in.rdbuf(),然后返回与std::cin 关联的旧缓冲区。 std::cout 或任何 stream 也可以做到这一点。

希望对您有所帮助。

【讨论】:

  • 在将 cin 和 cout 重置为标准 IO 之前是否需要关闭文件?
  • @updogliu:不。如果需要,可以使用in 和out 分别读取和写入in.txt 和out.txt。此外,当in 和out 超出范围时,文件将自动关闭。
  • 比起freopen,我更喜欢这个解决方案,因为如果我使用freopen,我将无法再取回我的stdout。 stackoverflow.com/questions/26699524/…
  • 如果我不想让旧的 buf 远离 cin 或 cout 怎么办?我应该delete他们吗?
【解决方案2】:

随便写

#include <cstdio>
#include <iostream>
using namespace std;

int main()
{
    freopen("output.txt","w",stdout);
    cout<<"write in file";
    return 0;
}

【讨论】:

  • 这也会重定向 printf,这在某些情况下可能是件好事。
  • @AkshayLAradhya 设置std::sync_with_studio(false); 时不会,尽管默认设置为true。
  • @PřemyslŠťastný 为什么?
  • 如果答案在功能上是相同的,C++ 等价物将是ofstream out("out.txt"); cout.rdbuf(out.rdbuf()); - 只多出一行,而且它是可移植的。没那么简单:)
  • @nevelis 很公平,你是对的。我想这取决于你是否需要它是便携式的。我查找这个的原因是为了测试编码挑战问题,所以我只是想要一个快速简单的答案。显然,这与编写生产代码的人的需求截然不同。
【解决方案3】:

这里有一个短代码 sn-p 用于遮蔽 cin/cout,对编程竞赛很有用:

#include <bits/stdc++.h>

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 <bits/stdc++.h>

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");

    // optional performance optimizations    
    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。所以顺序很重要。

另见Significance of ios_base::sync_with_stdio(false); cin.tie(NULL);

Std io 流也可以很容易地在单个文件的范围内隐藏,这对于竞争性编程很有用:

#include <bits/stdc++.h>

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
                   ^

另请参阅How do you properly use namespaces in C++?、Why is "using namespace std" considered bad practice? 和 How to resolve a name collision between a C++ namespace and a global function?

【讨论】:

    【解决方案4】:

    假设您的编译程序名称是 x.exe $ 是系统 shell 或提示符

    $ x <infile >outfile 
    

    将从 infile 获取输入并输出到 outfile 。

    【讨论】:

    • 这与 C++ 无关,并且在任何不平凡的示例中都会失败,例如当您的程序产生写入控制台的子进程时。至少这是我在尝试这种重定向时遇到的问题,因此我在这里。
    【解决方案5】:

    试试这个把 cout 重定向到文件。

    #include <iostream>
    #include <fstream>
    
    int main()
    {
        /** backup cout buffer and redirect to out.txt **/
        std::ofstream out("out.txt");
    
        auto *coutbuf = std::cout.rdbuf();
        std::cout.rdbuf(out.rdbuf());
    
        std::cout << "This will be redirected to file out.txt" << std::endl;
    
        /** reset cout buffer **/
        std::cout.rdbuf(coutbuf);
    
        std::cout << "This will be printed on console" << std::endl;
    
        return 0;
    }
    

    阅读全文Use std::rdbuf to Redirect cin and cout

    【讨论】:

    • 该问题已在 6 年前(2012 年)得到解答,但您现在已在 2018 年添加了答案。您的答案与已接受的答案相同。所以我想知道,当你没有 anything new 要添加时,你为什么要发布这个?
    • 我的回答只特别突出 cout 版本,详细答案在下面的链接中提供。
    • 您的答案中的new 是什么,而accepted 答案中没有?
    • 我的答案没有混合 cout 和 cin 的重定向,我的版本分开以使其更具可读性
    • @HaseeBMir 但问题是如何重定向cin 和cout。抱歉,如果他们只重定向cin 或只重定向cout,大多数程序员将能够剥离他们不需要的那一半已接受答案。
    【解决方案6】:

    如果你的输入文件是in.txt,你可以使用freopen将stdin文件设置为in.txt

    freopen("in.txt","r",stdin);
    

    如果你想对你的输出做同样的事情:

    freopen("out.txt","w",stdout);
    

    这适用于 std::cin(如果使用 c++)、printf 等...

    这也将帮助您在 clion、vscode 中调试代码

    编辑
    如果你想重置标准输入

    fclose(stdin);
    stdin = fdopen(0, "r"); //reopen: 0 is file descriptor of std input
    

    并重置标准输出

    fclose(stdout);
    stdout = fdopen(1, "w"); //reopen: 1 is file descriptor of std output
    

    【讨论】:

    • 在这种情况下如何重置stdout?
    • @Broxigar 编辑添加有关重置的信息
    【解决方案7】:

    接受的答案显示了重定向cin 和cout 的正确方法。您需要构造另一个生命周期超过cin 或cout 的流对象。如果你想写一个像freopen这样的函数,你可以为每个要重定向的流分配一个数组,以保存分配的流对象。

    #include <iostream>
    #include <string>
    #include <fstream>
    #include <vector>
    
    using namespace std;
    
    template<typename>
        struct fstream_traits { };
    template<typename CharT, typename Traits>
        struct fstream_traits<basic_istream<CharT, Traits>> { using type = basic_ifstream<CharT, Traits>; };
    template<typename CharT, typename Traits>
        struct fstream_traits<basic_ostream<CharT, Traits>> { using type = basic_ofstream<CharT, Traits>; };
    
    template <typename Stream>
    void redirect(Stream& str, string filename)
    {
        using fstream_type = typename fstream_traits<Stream>::type;
        static int index = std::ios_base::xalloc();
        if (str.pword(index) == nullptr)
        {
            str.pword(index)= new vector<ios_base*>{};
            str.register_callback([](ios_base::event event, std::ios_base& stream, int index) {
                if (event == ios_base::erase_event)
                {
                    for (auto fs : *(vector<ios_base*>*)stream.pword(index))
                        delete fs;
                    delete (vector<ios_base*>*)stream.pword(index);
                }
            }, index);
        }
        vector<ios_base*>* list = (vector<ios_base*>*)str.pword(index);
        list->push_back(new fstream_type{filename});
        str.rdbuf(dynamic_cast<fstream_type*>(list->back())->rdbuf())->~basic_streambuf();
    }
    
    int main()
    {
        redirect(cout, "out.txt");
        cout << "Redirected text!";
        return 0;
    }
    

    如果您明确使用istream/ostream 而不是Stream,则不需要模板和别名。

    【讨论】:

      【解决方案8】:

      C++ 中的 I/O 重定向

      https://www.geeksforgeeks.org/io-redirection-c/

      // Cpp program to redirect cout to a file
      #include <fstream>
      #include <iostream>
      #include <string>
       
      using namespace std;
       
      int main()
      {
          fstream file;
          file.open("cout.txt", ios::out);
          string line;
       
          // Backup streambuffers of  cout
          streambuf* stream_buffer_cout = cout.rdbuf();
          streambuf* stream_buffer_cin = cin.rdbuf();
       
          // Get the streambuffer of the file
          streambuf* stream_buffer_file = file.rdbuf();
       
          // Redirect cout to file
          cout.rdbuf(stream_buffer_file);
       
          cout << "This line written to file" << endl;
       
          // Redirect cout back to screen
          cout.rdbuf(stream_buffer_cout);
          cout << "This line is written to screen" << endl;
       
          file.close();
          return 0;
      }
      

      【讨论】:

      • 您好,欢迎来到 Stackoverflow。你已经用很多答案回答了一个非常古老的问题。请edit您的问题并解释为什么这个答案比其他答案更好
      猜你喜欢
      • 1970-01-01
      • 2017-05-24
      • 2023-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多