Вы, и не только Вы, совершаете одну и ту же ошибку. Даже если переделать условие на while(!feof(File)), то файл не будет считываться корректно. Такой подход концептуально не верен. Дело в том, что флаг EOF выставляется при попытке чтения за концом файла. Рассмотрим ситуацию, когда в файле три числа и как ваш цикл будет их считывать. Когда считалось последнее число, флаг EOF еще не выставлен, т.к. чтения за концом файла не было, поэтому получим следующее:
while(!feof(File))//Флаг EOF еще не выставлен, поэтому условие даст true
{
fread(&a[i], sizeof(int), 1, File);//Чтение не удалось, т.к. элементов нет, выставляется флаг EOF
//Но у нас нет никаких проверок на успех чтения,
//Поэтому код будет также выполнятся вне зависимости от ошибок чтения
pushBack(list, &a[i]); //Какое число вставится в конец? Правильно - последнее успешно считанное
i++;
}
То есть при таком подходе, создастся впечатление, что последний элемент считался дважды (собственно, форумы и сайты забиты подобными вопросами).
Каково может быть решение проблемы? Необходимо проверять флаг EOF уже ПОСЛЕ чтения, а не до:
while(true)
{
fread(&a[i], sizeof(int), 1, File);
if (feof(File)) {//Если выставился EOF
break;//Выходим из цикла
}
//...
}
Это будет работать, но решение тоже не очень хорошее. Вы читаете файл с помощью функции fread, а она в качестве результата возвращает количество считанных элементов. То есть мы можем проверить, все ли элементы считались или нет. Вы считываете за раз один элемент, поэтому в Вашем случае достаточно просто проверять успех чтения одного элемента:
//Выйдем из цикла, если один элемент не удалось считать
while(fread(&a[i], sizeof(int), 1, File) == 1)
{
//...
}
Однако, стоит заметить, что чтение из бинарного файла лучше производить по возможности "пачкой", а не по одному элементу. Приведу пример чтения в вектор:
std::vector<int> read_binary_data(char const * path)
{
auto close_file = [] (FILE * f) { fclose(f); };
using SmartPtr_t = std::unique_ptr<FILE, decltype(close_file)>;
SmartPtr_t file(fopen(path, "rb"), close_file);
if(!file) {
std::cerr << "File open failed\n";
throw std::runtime_error("file open failed");
}
std::vector<int> result;
size_t const size = 256;//Считывать будем по 256 элементов за раз
int buf[size];//Буфер под элементы
size_t count = 0;//Количество успешно считанных элементов
//если удалось считать хоть один элемент
while ((count = fread(buf, sizeof(*buf), size, file.get())) != 0) {
//то добавляем все считанные элементы в вектор
result.insert(result.end(), buf, buf + count);
}
return result;
}
Конечно же, пример несколько упрощен, например, в нем отсутствует реакция на ошибки, не связанные окончанием файла, но, думаю, идея понятна.
while(!feof(File))– Fat-Zer Apr 14 '18 at 07:15{ pushBack(list, &a[i++]); }```– Croessmah stands with Russia Apr 14 '18 at 07:40