Чтение из файла после достижения конца файла

У меня есть функция с именем readNextString(ifstream &file , char* &pBuffer) который извлекает следующую строку из файла, пока ',' или же '\n' достигается, удаляет пробелы в начале и в конце строки, сохраняет остаток в pBuffer и возвращает true, если все работало нормально — иначе false. Все работает, пока не будет достигнут конец файла. Когда eof флаг установлен, я не могу переместить мой указатель получения.
Я пробовал это:

if(file.eof())
{
file.clear();
file.seekg(0 , ios::end)
}

…а затем удалите пробелы в конце строки. Это почти помогло. Функция извлекает строку без пробелов, но я получаю бесконечный цикл.

Мой актуальный вопрос: как я могу проверить, является ли следующий символ EOFи если я не могу — есть ли альтернативный способ сделать это?

Вот моя настоящая функция:

bool readNextString(ifstream &file , char* &pBuffer)
{
if(file.eof()){
return false;
}
for(; file.good() && isWhitespace(file.peek()) && !file.eof() ; file.seekg(1 , ios::cur))
;
if(file.eof()){
cout << "The file is empty.\n";
return false;
}else{
streamoff startPos = file.tellg();
cout << "startPos : " << startPos << endl;
for(;file.good() && file.peek()!='\n' && file.peek()!=',' && file.peek()!= EOF; file.seekg(1 , ios::cur))
;
streamoff A = file.tellg();
cout << "A : " << A << endl;
file.seekg(-1 , ios::cur);
for(;file.good() && isWhitespace(file.peek()) ; file.seekg(-1 , ios::cur))
;
file.seekg(2 , ios::cur);
streamoff endPos = file.tellg();
cout << "endPos : " << endPos << endl;
pBuffer = new char[endPos-startPos];
if(pBuffer)
{
file.seekg(startPos , ios::beg);
file.get(pBuffer , endPos-startPos , ',' || '\n');
for(;file.good() && file.peek()!='\n' && file.peek()!=',' && file.peek()!= EOF; file.seekg(1 , ios::cur))
;
file.seekg(2 , ios::cur);
streamoff temp = file.tellg();
cout << "temp : " << temp << endl;
return true;
}else{
cout << "Error! Not enough memory to complete the task.\nPlease close some applications and try again.\n";
return false;
}
}
}

И это то место, где я это называю:

void printCities()
{
ifstream city ;
city.open("cities.txt", fstream::in);
if(city.is_open())
{
char *currCity;
int counter = 1;
while(readNextString(city , currCity))
{
cout << counter++ << ". " << currCity << endl;
delete[] currCity;
currCity = NULL;
}
if(city.eof())
cout << "There are no cities added.\n";
city.close();
}else
cout << "Error by opening 'cities.txt'.Make sure that the file exist and try again.\n";
}

Надеюсь, я был достаточно ясен. Если вы найдете какие-то другие ошибки или возможные ошибки, я буду рад услышать это и извлечь уроки из этого.

3

Решение

Как я могу проверить, является ли следующий символ EOF?

Как это

if (file.peek() == EOF)
{
// next char is EOF
...
}
3

Другие решения

Первый, не использовать поиск, чтобы пропустить пробелы. Просто получите
характер и покончим с этим.

Во-вторых, вы, кажется, неправильно поняли значение
istream::good() а также istream::eof(), Есть никогда
в любое время где istream::good() уместно, и
istream::eof() обычно только уместно после вход имеет
не удалось. Что касается вашей петли, пропускающей пробел, обычный
решение будет:

while ( isspace( file.peek() ) && file.peek() != EOF ) {
file.get();     //  ignore read character...
}

Аналогичные комментарии справедливы и для других циклов, за исключением того, что
Вы не хотите игнорировать прочитанные символы. Коллекционировать
персонажи до следующего ',', например:

std::string field;
while ( file.peek() != ',' && file.peek() != EOF ) {
field.push_back( file.get() );
}

(И ваш file.get( pBuffer, endPos - startPos, ',' || '\n' )
конечно, не делает то, что вы ожидаете; выражение ','
|| '\n'
всегда буду оценивать true, который при конвертации
к char, является '\01.)

Наконец, хотя приведенная выше стратегия будет работать, она гораздо предпочтительнее
вводить большие единицы текста в std::streamи разобрать
тот. Если текст ориентирован на строки, используйте что-то вроде:

std::string line;
while ( std::getline( file, line ) ) {
//  Parse line, using std::istringstream if appropriate,
//  although this doesn't seem to be the case for your code.
}

Это на несколько порядков проще, чем то, что вы делаете.

1

Хорошо. Я сделал это иначе! getline () для ПОБЕДЫ! : D
Итак, это мой код (на этот раз гораздо более читабелен):

bool readNextString(ifstream &file , char pBuffer[] )
{
while(isWhitespace(file.peek()) && !file.eof())
file.ignore(1);
if(!file.eof())
{
streamoff start = file.tellg();
stringstream toComma;
if(file.getline(pBuffer , 200 , ','))
{
toComma << pBuffer;
toComma.getline(pBuffer ,200, '\n');
int i=strlen(pBuffer)-1;
for(; isWhitespace(pBuffer[i]) ;i--)
;
pBuffer[i+1] = '\0';
file.clear();
file.seekg(start + strlen(pBuffer) , file.beg);
return true;
}else return false;
}
return false;
}

Я также внес некоторые изменения в свою другую функцию:

void printCities()
{
ifstream city ;
city.open("cities.txt", fstream::in);
if(city.is_open())
{
if(!isEmpty(city))
{
char currCity[200];
int counter = 1;
while(readNextString(city , currCity) && counter < 10)
cout << counter++ << ". " << currCity << endl;
}else
cout << "There are no cities added.\n";
city.close();
}else
cout << "Error by opening 'cities.txt'.Make sure that the file exist and try again.\n";
}

Функция isEmpty(ifstream &file) возвращает true, если файл пуст, и false в противном случае.

Спасибо всем за помощь!
С наилучшими пожеланиями !

0
По вопросам рекламы [email protected]