У меня есть функция с именем readNextString(ifstream &file , char* &pBuffer)
, которая извлекает следующую строку из файла, до достижения ','
или '\n'
, удаляет пробелы в начале и в конце строки, сохраняет остальное в pBuffer и возвращает true, если все работает нормально - false в противном случае. Все работает до тех пор, пока не будет достигнут конец файла. Когда установлен флаг eof
, я не могу перенести указатель get. Я попытался это:Чтение из файла после достижения конца файла
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";
}
Надеется, что я достаточно ясно. Если вы обнаружите некоторые другие ошибки или возможные ошибки, я буду рад услышать их и узнать из него.
FYI вы _really_ не хотите разбирать строки из такого файла. Либо прочитайте весь файл в буфер, либо прочитайте большие куски за раз в буфер и проанализируйте его в памяти. Не делайте миллионных чтений. Это медленно. И для этого на самом деле сложнее. – David
@Dave Чтение символа по символу не обязательно медленное; 'istream' выполняет буферизацию. Однако использование seek _is_ медленное; во множестве реализаций поиск приведет к потере буфера и двум системным вызовам на символ. (Этого не нужно, но поиск в буфере должен быть достаточно редким, чтобы библиотека не оптимизировала их.) –