Простая программа файлового ввода/вывода C++

#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <process.h>
using namespace std;

int main(){
    system("cls");
    char mline[75];
    int lc=0;
    ofstream fout("out.txt",ios::out);
    ifstream fin("data.txt",ios::in);
    if(!fin){
        cerr<<"Failed to open file !";
        exit(1);
    }
    while(1){
        fin.getline(mline,75,'.');
        if(fin.eof()){break;}
        lc++;
        fout<<lc<<". "<<mline<<"\n";
    }
    fin.close();
    fout.close();
    cout<<"Output "<<lc<<" records"<<endl;
    return 0;
}

Приведенный выше код должен читать из файла "data.txt" следующий текст

«Поведение потока типа ifstream по умолчанию (при открытии файлов) позволяет пользователям читать содержимое из файла. Если режим файла — ios::in, то чтение выполняется только в текстовом файле, а если режим файла также включает ios:: binary вместе с ios::in, то чтение выполняется в двоичном режиме. В двоичном режиме не происходит преобразования символов, тогда как в текстовом режиме происходят определенные преобразования».

и создайте файл out.txt, в котором тот же текст хранится с использованием номеров строк (строка может иметь 75 символов или заканчиваться на «.» — в зависимости от того, что наступит раньше).

Всякий раз, когда я запускаю программу, она просто зависает в консоли, которая не отвечает ни на какие клавиши.

Может кто-нибудь сказать мне, что здесь происходит?


person Monk    schedule 04.09.2014    source источник
comment
По крайней мере, опубликуйте код, который скомпилируется! :-)   -  person paxdiablo    schedule 04.09.2014
comment
Он компилируется на CodeLite(g++) .   -  person Monk    schedule 04.09.2014
comment
Тогда CodeLite имеет серьезные недостатки: while(1)){ недопустимый синтаксис.   -  person paxdiablo    schedule 04.09.2014
comment
Не могли бы вы объяснить это, пожалуйста? (я почти новичок в программировании)   -  person Monk    schedule 04.09.2014
comment
У вас есть одна открывающая скобка, но две закрывающие скобки.   -  person Drew McGowen    schedule 04.09.2014
comment
Ой, извини ! Этого не видел! (Я исправил это перед компиляцией - я думаю, просто опубликовал старый код.)   -  person Monk    schedule 04.09.2014
comment
Если вы читаете до 75 символов в mline, что составляет 75 символов в ширину, куда идет завершающий нулевой символ? Кроме того: вы проверили fin при открытии, но почему бы не проверить и fout?   -  person Emilio Garavaglia    schedule 04.09.2014


Ответы (1)


Если какая-либо из попыток чтения в файле длиннее 74 символов, getline установит failbit вместо fin, и вы никогда не дойдете до конца файла. Измените код на следующий:

for (; fin; ++lc) {
  fin.getline(mline,75,'.');
  if (!fin.eof() && !fin.bad())
    fin.clear();
  fout<<lc<<". "<<mline<<"\n";
}

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

Подумайте о переходе на std::string.

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

int main()
{
  int lc = 0;
  std::ofstream fout("out.txt");
  std::ifstream fin("data.txt");

  for (std::string line; getline(fin, line, '.'); )
    fout << ++lc << ". " << line << "\n";

  std::cout << "Output " << lc << " records\n";
}
person user657267    schedule 04.09.2014
comment
Что ж, предыдущая ошибка была решена (путем внесения предложенных вами изменений). Но я открыл выходной файл - и он был пуст! - person Monk; 04.09.2014
comment
У меня работает нормально, возможно, что-то мешает доступу к вашему выходному файлу. - person user657267; 04.09.2014
comment
@Monk, вы не можете просто вывести из mline ... не гарантируется завершение NUL ... вы должны использовать fout.write(mline, fin.gcount()); - person Tony Delroy; 04.09.2014
comment
@TonyD istream::getline читает не более 1 символа, а затем добавляет нулевой символ. - person user657267; 04.09.2014
comment
@ user657267: ах да - я пойду спать... извините. Возможно, было бы неплохо добавить проверку if (!fout) ... - возможно, она не была открыта должным образом - также можно потерять параметр out - ofstream позаботится об этом. И в вашем исходном коде последняя строка не была бы написана из-за проверки eof() после ввода и перед выводом - вы до сих пор не делаете что-то подобное? - person Tony Delroy; 04.09.2014
comment
@Monk Проверьте, правильно ли открывается выходной файл, как и входной, возможно, он заблокирован другим процессом. - person user657267; 04.09.2014
comment
@user657267 user657267 Я только что сделал вывод из цикла while (1-я строка после запуска while) - и он не выдал вывод на консоль. Значит, элемент управления даже не входит в цикл while? - person Monk; 04.09.2014
comment
@Monk Обновлено решение, но, пожалуйста, рассмотрите возможность перехода на версию string, так как ее гораздо проще использовать. - person user657267; 04.09.2014
comment
@ user657267 Спасибо! Это прекрасно работает! Но не могли бы вы просто объяснить, что вы там делали? что будет означать while(fin)? также что делает fin.clear()? - person Monk; 04.09.2014
comment
@Monk while(fin), fin.clear(). - person user657267; 04.09.2014
comment
@ user657267 Я не могу понять, почему ты написал if(!fin && !fin.eof()){ fin.clear();} Не могли бы вы объяснить? когда я не включаю этот фрагмент кода, я получаю только 1 строку вывода, а если я его включаю, я получаю 8 строк (то есть правильную). - person Monk; 04.09.2014
comment
@Monk Я немного изменил его, так как !fin не был необходим, но на всякий случай вам нужно учитывать и badbit. В основном ошибка потока сбрасывается, если установлено только failbit, любая другая ошибка чтения (например, eof) нарушит цикл. - person user657267; 04.09.2014
comment
Не могли бы вы предложить хорошее место для чтения ошибок ввода-вывода файлов в C++? Кажется, я не могу понять. - person Monk; 04.09.2014
comment
@Monk В одной из книг для начинающих здесь должно быть то, что вам нужно. - person user657267; 04.09.2014