`fgetpos` не возвращает правильную позицию

Обновление: чтобы обойти проблему ниже, я сделал

if (ftell(m_pFile) != m_strLine.size())
fseek(m_pFile, m_strLine.size(), SEEK_SET);
fpos_t position;
fgetpos(m_pFile, &position);

это тогда возвращает правильную позицию для моего файла. Тем не менее, я все еще хотел бы понять, почему это происходит?


Я хочу получить позицию в текстовом файле. Для большинства файлов я читаю первую строку, сохраняю позицию, делаю некоторые другие вещи и возвращаюсь к позиции потом …

m_pFile = Utils::OpenFile(m_strBaseDir + "\\" + Source + "\\" + m_strFile, "r");
m_strLine = Utils::ReadLine(m_pFile);
bEOF = feof(m_pFile) != 0;
if (bEOF)
{
Utils::CompilerError(m_ErrorCallback,
(boost::format("File '%1%' is empty.") % m_strFile).str());
return false;
}

// Open.
pFileCode = Utils::OpenFile(strGenCode + "\\" + m_strFile, options.c_str());
m_strLine = Utils::Trim(m_strLine);
Utils::WriteLine(pFileCode, m_strLine);

// Store location and start passes.
unsigned int nLineCount = 1;
fpos_t position;
fgetpos(m_pFile, &position);
m_strLine = Utils::ReadLine(m_pFile);
...
fsetpos(m_pFile, &position);
m_strLine = Utils::ReadLine(m_pFile);

Со всеми предоставленными мне файлами хранилище fgetpos а также fsetpos работает правильно. Проблема с файлом, который я создал, который выглядит как

НАПРИМЕР

который почти идентичен поставляемым файлам. Проблема в том, что для файла выше fgetpos(m_pFile, &position); не возвращает правильный position (Я знаю, что fpos_t position является конкретной реализацией). После первого ReadLine Я получаю position из 58 (отредактировано от 60) так что когда я пытаюсь прочитать вторую строку с

fsetpos(m_pFile, &position);
m_strLine = Utils::ReadLine(m_pFile);

я получил

на 700

вместо

Выбор: функция ADJEXCL

Почему fgetpos не возвращает позицию конца первой строки?


_Заметка. Utils.ReadLine метод это:

std::string Utils::ReadLine(FILE* file)
{
if (file == NULL)
return NULL;
char buffer[MAX_READLINE];
if (fgets(buffer, MAX_READLINE, file) != NULL)
{
if (buffer != NULL)
{
std::string str(buffer);
Utils::TrimNewLineChar(str);
return str;
}
}
std::string str(buffer);
str.clear();
return str;
}

с

void Utils::TrimNewLineChar(std::string& s)
{
if (!s.empty() && s[s.length() - 1] == '\n')
s.erase(s.length() - 1);
}

Редактировать. Следуя предложениям по отладке в комментариях, я добавил следующий код

m_pFile = Utils::OpenFile(m_strBaseDir + "\\" + Source + "\\" + m_strFile, "r");
m_strLine = Utils::ReadLine(m_pFile);
// Here m-strLine = "          Logic Definition Report Chart Version: New Version 700" (64 chars).
long vv = ftell(m_pFile); // Here vv = 58!?

fpos_t pos;
vv = ftell(m_pFile);
fgetpos(m_pFile, &pos); // pos = 58.
fsetpos(m_pFile, &pos);
m_strLine = Utils::ReadLine(m_pFile);

0

Решение

Извините, но ваши функции Utils явно написаны некомпетентными. Некоторые проблемы — это вопрос стиля. Для обрезки:

void Utils::TrimNewLineChar(std::string& s)
{
if (!s.empty() && *s.rbegin() == '\n')
s.resize(s.size() - 1); // resize, not erase
}

или в C ++ 11

void Utils::TrimNewLineChar(std::string& s)
{
if (!s.empty() && s.back() == '\n')
s.pop_back();
}

ReadLine еще хуже, заменить его на:

std::string Utils::ReadLine(FILE* file)
{
std::string str;
char buffer[MAX_READLINE];
if (file != NULL && fgets(buffer, MAX_READLINE, file) != NULL)
{
// it is guaranteed that buffer != NULL, since it is an automatic array
str.assign(buffer);
Utils::TrimNewLineChar(str);
}
// copying buffer into str is useless here
return str;
}

Что в прошлом str(buffer) в оригинале меня особенно беспокоит. Если fgets достигает новой строки, заполняет буфер или достигает конца файла, вы гарантированно получите правильно завершенную строку в вашем буфере. Если возникает какая-то другая ошибка ввода / вывода? Кто знает? Это может быть неопределенное поведение.

Лучше не полагаться на ценность buffer когда fgets выходит из строя.

1

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


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