Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Считывание данных из перенаправленного потока


Автор: Compositum 4.1.2013, 16:46
Доброго времени суток.

Изучаю C++, разбираюсь с потоками... Имеется исходный текстовый файл input.txt со следующим содержимым:
Цитата

11
12
13
14
15
16
17

Я хочу перенаправить поток ввода на файл input.txt, а поток вывода - в output.txt, после чего прочитать всё, что поступает во входной поток. 

Код

// Перенаправление потоков ввода/вывода в C++
#include <iostream>
#include <fstream>

int main () {    
    // Сначала перенаправляем ввод...
    std::streambuf *inputBuckup = std::cin.rdbuf(); // запоминаем "родной" буфер потока ввода    
    std::ifstream inputFileStr("c:\\temp\\input.txt", std::ios::in);// файл для чтения в поток ввода
    if (!inputFileStr){
        std::cout << "Can't open the input file." << std::endl;
        return 1;
    }
    std::streambuf *inputFileBuf = inputFileStr.rdbuf(); // получаем буфер потока файла ввода    
    std::cin.rdbuf(inputFileBuf); // перенаправляем поток ввода на файл ввода

    // Теперь перенаправляем вывод...
    std::streambuf *outputBackup = std::cout.rdbuf();  // запоминаем "родной" буфер потока вывода
    std::ofstream outputFileStr("c:\\temp\\output.txt", std::ios::out);// файл для записи из потока вывода
    if (!outputFileStr){
        std::cout << "Can't open the output file." << std::endl;
        return 2;
    }
    std::streambuf *outputFileBuf = outputFileStr.rdbuf(); // получаем буфер потока файла вывода
    std::cout.rdbuf(outputFileBuf); // перенаправляем поток вывода на файл вывода

    // Теперь читаем всё, что имеется в потоке ввода, внося дополнительные поправки и 
    // перенаправляем полученный результат в поток вывода...    
    int i = 1;    
    // Когда при вводе достигается конец файла, потоку, связанному с файлом, присваивается
    // значение false.
    while(std::cin){
        // Предполагается, что в файле input.txt записаны числовые значения...
        int x = 0;
        std::cin >> x;
        std::cout << "row " << i++ << ": " << x;
    }    

    // При закрытии файлов их буферы потоков будут уничтожены. 
    // Поэтому, прежде чем закрыть файл, возвращаем обратно "родные" буферы потоков:
    std::cin.rdbuf(inputBuckup);
    std::cout.rdbuf(outputBackup);

    // Закрываем файлы
    inputFileStr.close();
    outputFileStr.close();

    return 0;
}


Однако в файле output.txt я получаю не то, что ожидал. Получаю такое:

Цитата

row 1: 0


В чём ошибка?

Автор: NoviceF 4.1.2013, 16:56
Как-то всё очень замудрено.. сейчас найду попроще код на тему.

В общем код на тему, на сколько соответствует заданию не буду вникать, но мне кажется должен дать пищу для размышлений:

Код

#include <fstream>
#include <iostream>

template<typename In, typename Out>
void Process(In& in, Out& out)
{
   //do some work, for example
   out << in.rdbuf();
}

using namespace std;

int main(int argc, char* argv[])
{
   fstream in, out;
   if (argc > 1) in.open (argv[1], ios::in  | ios::binary);
   if (argc > 2) out.open(argv[2], ios::out | ios::binary);
   
   Process (in.is_open()  ? in  : cin,
            out.is_open() ? out : cout);
}

Автор: Compositum 4.1.2013, 17:13
Цитата

Как-то всё очень замудрено.. 

На мой взгляд там всё понятно. За основу я взял код http://www.cplusplus.com/reference/ios/ios/rdbuf/.
Цитата

В общем код на тему, на сколько соответствует заданию не буду вникать

Он не помогает понять причину проблемы.

Автор: Compositum 4.1.2013, 18:27
Если я содержимое файла input.txt заменю на такое:
Цитата(input.txt)

Иванов И.И. 4-43-21
Петров П.П. 4-65-11
Сидоров С.С. 4-21-21
Васильев В.В. 4-47-53


и в цикле внесу такие изменения:
Код

while(std::cin){
    std::string surname; // фамилия
    std::string initials; // инициалы
    std::string phone;// телефон
    std::cin >> surname >> initials >> phone;
    if (surname.length())
        std::cout << "row " << i++ << ": " << surname << " " << initials <<
        " " << phone << std::endl;
}


То всё работает как надо:

Цитата(output.txt)

row 1: Иванов И.И. 4-43-21
row 2: Петров П.П. 4-65-11
row 3: Сидоров С.С. 4-21-21
row 4: Васильев В.В. 4-47-53


Хотелось бы понять, почему с числами не работает...

Автор: NoviceF 4.1.2013, 19:52
К сожалению, сейчас нет IDE под рукой, а при помощи stringstream на http://liveworkspace.org организовать правдоподобно вывод в файл не получается, в поток то данные сохраняются и цифрами и стрингами, а вот в файл, на основе которого создаётся stringstream ничего не сохраняется.. Так что если и смогу проверить что-нибудь в "полевых условиях" - не раньше часов 2х ночи :(

Автор: NoviceF 4.1.2013, 23:56
Внезапно, но, вот вход
Код

10
20
30
40


вот выход:
Код

row 1: 10row 2: 20row 3: 30row 4: 40row 5: 0

так что с кодом всё в порядке..

Автор: volatile 5.1.2013, 01:00
Цитата(Compositum @  4.1.2013,  16:46 Найти цитируемый пост)
 while(std::cin){
        // Предполагается, что в файле input.txt записаны числовые значения...
        int x = 0;
        std::cin >> x;
        std::cout << "row " << i++ << ": " << x;
    }    

Цитата(Compositum @  4.1.2013,  16:46 Найти цитируемый пост)
Однако в файле output.txt я получаю не то, что ожидал. Получаю такое:
row 1: 0
В чём ошибка?


Ошибка в том, что поток надо проверять не до ввода, а после ввода. (очень частая ошибка.)
В вашем случае std::cin >> x; не смог прочитать из файла, и x осталась без изменений.
на следующей итерации, цикл завершился, так как while(std::cin) дал false.

В вот почему не смог прочитать из файла, может быть сотни причин. смотрите у себя...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)