C++: читаем файл построчно, если длина строки не ограничена
В этой лекции написано:
Если максимальная длина строки принципиально не ограничена, помочь может либо предварительное посимвольное чтение файла для её определения, либо работа с файлом как с бинарными данными
На самом деле, и то, и другое. Попробуем прочитать построчно файл, максимальная длина строки которого не ограничена, точней, ограничена только возможностями нашей оперативной памяти.
Идея состоит в том, чтобы сначала при посимвольном чтении файла найти максимальную длину строки maxlen
,
считая, что все строки заканчиваются символом "перевод строки" \n
. Символ "возврат каретки" \r
, который в
Windows-системах добавляется перед переводом строки, при этом игнорируется, чтобы не получить
на единицу большей длины, чем нужно.
После этого выделяем память под буфер длиной maxlen+3
(на всякий случай, чтобы учесть
\r
, \n
и возможный нуль-терминатор) и затем во втором цикле читаем файл уже построчно стандартной
функцией fgets
.
У меня очередная строка файла просто выводится в консоль, на самом деле строки можно поочередно обрабатывать вместо комментария "//Обработка строки buf
".
Проверено в консоли Visual Studio 2015.
#define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <cstdlib> #include <windows.h> using namespace std; void error(int n) { char *msg[] = { "OK","Can't open file","Can't allocate memory" }; cout << endl << msg[n]; system("pause>nul"); exit(n); } int main() { setlocale(LC_ALL, "Russian"); FILE *f = fopen("data.txt", "rb"); if (!f) error(1); int len = 0, maxlen = 0; char c; while (1) { //При первом чтении файла находим максимальную длину строки fread(&c, 1, 1, f); if (c == '\r') continue; //Игнорируем символ "возврат каретки" int e = feof(f); //Это конец файла? if (c == '\n' || e) { //Последняя строка тоже может оказаться самой длинной! if (len > maxlen) maxlen = len; len = 0; } else len++; if (e) break; } cout << "Max. length of string = " << maxlen << endl; //Выделяем память для одной строки и встаём на начало файла: char * buf = new char[maxlen + 3]; if (!buf) error(2); fseek(f, 0L, SEEK_SET); while (1) { //При втором чтении читаем строками fgets(buf, maxlen + 2, f); int len = strlen(buf); if (len && buf[len - 2] == '\r' && buf[len - 1] == '\n') { //Если это формат текстового файла из DOS/Windows (CR/LF) buf[len - 2] = '\n'; buf[len - 1] = '\0'; } //Обработка строки buf fputs(buf, stdout); //Сама добавит \n при выводе if (feof(f)) break; buf[0] = '\0'; } fclose(f); error(0); }
Так как мы не работаем с капризной в Studio функцией fgetc
, вот таких проблем
у нас не возникнет.
11.12.2018, 14:30 [2592 просмотра]