abcd
efg
hi
j
Программа должна создать файл, модифицированный следующим образом:
abcd
efg
hi
j
5 9 12 14 24
Так выглядит первая попытка реализации:
#include <iostream>
#include <fstream>
main() {
// открыть файл для ввода и дозаписи
fstream inOut( "copy.out", ios_base::in|ios_base::app );
int cnt = 0; // счетчик байтов
char ch;
while ( inOut.get( ch ))
{
cout.put( ch ); // скопировать на терминал
++cnt;
if ( ch == '\n' ) {
inOut << cnt ;
inOut.put( ' ' ); // пробел
}
}
// вывести окончательное значение счетчика байтов
inOut << cnt << endl;
cout << "[ " << cnt << " ]" << endl;
return 0;
}
inOut – это объект класса fstream, связанный с файлом copy.out, открытым для ввода и дозаписи. Если файл открыт в режиме дозаписи, то все новые данные записываются в конец.
При чтении любого (включая пробельные) символа, кроме конца файла, мы увеличиваем переменную cnt на 1 и копируем прочитанный символ на терминал, чтобы вовремя заметить ошибки в работе программы.
Встретив символ новой строки, мы записываем текущее значение cnt в inOut. Как только будет достигнут конец файла, цикл прекращается. Окончательное значение cnt выводится в файл и на экран.
Программа компилируется без ошибок и кажется правильной. Но если подать на вход несколько фраз из романа “Моби Дик” Германа Мелвилла:
Call me Ishmael. Some years ago, never mind
how long precisely, having little or no money
in my purse, and nothing particular to interest
me on shore, I thought I would sail about a little
and see the watery part of the world. It is a
way I have of driving off the spleen, and
regulating the circulation.
то получим такой результат:
[ 0 ]
Программа не вывела ни одного символа, видимо, полагая, что файл пуст. Проблема в том, что файл открыт для дозаписи и потому позиционирован на конец. При выполнении инструкции