Як перенаправити cin і cout на файли?


Відповіді:


219

Ось робочий приклад того, що ви хочете зробити. Прочитайте коментарі, щоб знати, що робить кожен рядок у коді. Я перевірив це на своєму ПК з 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- або будь-яким потоком з цього питання.

Сподіваюся, що це допомагає.


4
Чи потрібно закривати файли, перш ніж скинути cin і cout на стандартний IO?
updogliu

3
@updogliu: Ні , якщо ви хочете, ви можете використовувати inі outдля читання і запису до, in.txtі out.txtвідповідно. Крім того , файли будуть автоматично закриті , коли inі outвиходять з області видимості.
Наваз

Мені подобається це рішення над рішенням, freopenтому що я більше не можу отримати stdoutспину, якщо використовую freopen. stackoverflow.com/questions/26699524 / ...
xxks-ККК

88

Просто напишіть

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

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

14
Це перенаправлення stdout, а не cout.
updogliu

5
Це також перенаправить printf, що в деяких випадках може бути хорошою справою.
JDiMatteo

5
@AkshayLAradhya Не під час встановлення std::sync_with_studio(false);, хоча за замовчуванням встановлено значення true.
vsoftco

2
@ PřemyslŠťastný чому?
reggaeguitar

4
Якби відповіді були однакові за функціональністю, еквівалент цього C ++ був би ofstream out("out.txt"); cout.rdbuf(out.rdbuf());- лише один додатковий рядок, і він портативний. Не набагато простіше :)
nevelis

19

Ось короткий фрагмент коду для затінення 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;
}

Це дає додаткову перевагу, що звичайні fstreams швидші, ніж синхронізовані потоки 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. Отже, порядок має значення.

Дивіться також Значення ios_base :: sync_with_stdio (помилково); 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
                   ^

Див. Також Як правильно використовувати простори імен у C ++? , Чому "використання простору імен std" вважається поганою практикою? і Як вирішити зіткнення імені між простором імен C ++ та глобальною функцією?


15

припустимо, що ім'я проги компіляції - x.exe, а $ - оболонка системи або підказка

$ 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;
}

Читайте повну статтю Використовуйте std :: rdbuf для перенаправлення cin та cout


1
На питання відповіли майже 6 років тому (у 2012 році), але ви вже додали відповідь у 2018 році. Ваша відповідь така ж, як і прийнята відповідь. Тож мені цікаво, чому ви опублікували це, коли у вас не було нічого нового додати?
Наваз

Моя відповідь виділяє лише версію cout, а детальну відповідь надано за посиланням нижче.
HaseeB Mir

Що нового у вашій відповіді немає в прийнятій відповіді?
Наваз

2
Моя відповідь не поєднує перенаправлення як на cout, так і на cin, моя версія відокремлена, щоб зробити її більш зрозумілою
HaseeB Mir
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.