Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 17.01.2023, 22:17   #1
agent2
Новичок
Джуниор
 
Регистрация: 06.11.2022
Сообщений: 3
По умолчанию Как прочитать бинарный файл c++ с конца ?

fin.seekg(0, fin.end) не работает
Код:

#include <iostream>
#include <fstream>
#include <chrono>
#include <ctime>

using namespace std;
void FillFile(const char* FilePath);
void ShowFile(const char* FilePath);
int main(int argc, char* argv[])
{
    srand(static_cast<unsigned>(time(nullptr)));

    int max, min;

    char InputPath[] = "myFile.txt";

    FillFile(InputPath);
    ShowFile(InputPath);
}

void FillFile(const char* FilePath)
{
    ofstream fout(FilePath, ios::binary | ios::out);
    if (fout.is_open())
    {

        int Y = -10;
        int X = 20 + 1;

        int Y2 = 1;
        int X2 = 5 + 1;
        int countNums = rand() % (X2 - Y2) + Y2;
        cout << countNums << endl;

        if (fout.is_open())
        {
            for (int i = 0; i < countNums; i++)
            {
                int num = rand() % (X - Y) + Y;
                cout << num << " ";
                fout.write((char*)&num, sizeof(num));
            }
            cout << endl;
        }
    }
    else
    {
        cout << "Error\n";
        exit(0);
    }
    fout.close();
}

void ShowFile(const char* FilePath)
{
    ifstream fin(FilePath, ios::in | ios::binary);

    if (fin.is_open())
    {
        int number;
        fin.seekg(0, fin.end);
        while (fin.read((char*)&number, sizeof(number)))
        {

            cout << number << " ";
        }
    }
    else
    {
        cout << "Errr";
    }
    fin.close();
}

Последний раз редактировалось agent2; 17.01.2023 в 22:22. Причина: ПРАВКА
agent2 вне форума Ответить с цитированием
Старый 17.01.2023, 22:36   #2
macomics
Участник клуба
 
Регистрация: 17.04.2022
Сообщений: 1,833
По умолчанию

Так вы устанавливаете указатель файла в самый конец. Там больше нечего читать и поэтому цикл while не будет работать.
Чтобы считать int вам надо отступить от конца файла на -4 и считать этот int

Код:
fin.seekg(-4, fin.end);
А если надо показать файл от конца к началу, тогда надо после каждого удачного чтения выполнять отступ от текущей позиции назад на 2*sizeof(int) и контролировать позицию на достижение начала файла (fin.tellg() == 0)

Последний раз редактировалось macomics; 17.01.2023 в 22:50.
macomics вне форума Ответить с цитированием
Старый 17.01.2023, 22:52   #3
agent2
Новичок
Джуниор
 
Регистрация: 06.11.2022
Сообщений: 3
По умолчанию

macomics, а как сделать чтобы имменно все цифры из файла выводились с конца ? указываю больше отступ появляются неправильные значения
agent2 вне форума Ответить с цитированием
Старый 17.01.2023, 23:03   #4
macomics
Участник клуба
 
Регистрация: 17.04.2022
Сообщений: 1,833
По умолчанию

Ну смотрите. Опишу словами. Вот вы установили указатель в самый конец файла. Тогда при попытке чтения из файла функция вернет ошибку потому что нет данных для считывания.

Если вы отступите от конца файла на 1*sizeof(int) тогда до конца файла останутся байты позволяющие считать int. Функция чтения при этом сможет удачно его считать и переместит указатель в файле на sizeof(int) и он опять установится в самый конец файла.

Если после функции чтения вы от fin::cur отступите назад на sizeof(int), тогда вы отмените тот переход, который сделала функция read. А вам надо перейти к предыдущему элементу, а не к тому же самому. Тогда надо отступить назад на 2*sizeof(int).

Проблемы начинаются в начале файла. Проще всего получить длину файла и разделить на sizeof(int) и вместо while использовать for.
macomics вне форума Ответить с цитированием
Старый 18.01.2023, 00:33   #5
agent2
Новичок
Джуниор
 
Регистрация: 06.11.2022
Сообщений: 3
Сообщение с++ Открыть бинарный файл, заполненный случайными целыми числами

Открыть бинарный файл, заполненный случайными целыми числами в диапазоне [-10...20]. Количество чисел в файле заранее неизвестно. Найдите максимальный и минимальный элемент в файле. Все числа, находящиеся между ними, вывести на экран в обратном порядке. Массивы не использовать

Пытался сам чтото написать
Код:
#include <iostream>
#include <fstream>
#include <chrono>
#include <ctime>

using namespace std;
void FillFile(const char* FilePath);
void SearhMinMax(const char* FilePath, int* max, int* min);
void ShowFile(const char* FilePath);
int main(int argc, char* argv[])
{
    srand(static_cast<unsigned>(time(nullptr)));

    int max, min;

    char InputPath[] = "myFile.txt";

    FillFile(InputPath);
    ShowFile(InputPath);
    SearhMinMax(InputPath, &max, &min);
}

void FillFile(const char* FilePath)
{
    ofstream fout(FilePath, ios::binary | ios::out);
    if (fout.is_open())
    {
        int Y = -10;
        int X = 20 + 1;
        int Y2 = 1;
        int X2 = 50 + 1;
        int countNums = rand() % (X2 - Y2) + Y2;
        cout << countNums << endl;

        if (fout.is_open())
        {
            for (int i = 0; i < countNums; i++)
            {
                int num = rand() % (X - Y) + Y;
                cout << num << " ";
                fout.write((char*)&num, sizeof(num));
            }
            cout << endl;
        }
    }
    else
    {
        cout << "Error\n";
        exit(0);
    }
    fout.close();
}

void ShowFile(const char* FilePath)
{
    ifstream fin(FilePath, ios::in  | ios::binary);
    
    if (fin.is_open())
    {
        int number;
        fin.seekg(-8, fin.end);
        
        while (fin.read((char*)&number, sizeof(number)))
        {
            cout << number << " ";
        }
    }
    else
    {
        cout << "Errr";
    }
    fin.close();
}

void SearhMinMax(const char* FilePath, int* max, int* min)
{
    ifstream fin(FilePath, ios::binary | ios::in);
    int number;
    bool firstAuto = true;
    
    

    if (fin.is_open())
    {
        while (fin.read((char*)&number, sizeof(number)))
        {
            if (number > *max or firstAuto == 1)
            {
                *max = number;
            }
            if (number < *min or firstAuto == 1)
            {
                *min = number;
                firstAuto = 0;
            }
        }
    }
    fin.close();
    cout << *max << " " << *min;
}
agent2 вне форума Ответить с цитированием
Старый 19.01.2023, 05:49   #6
Пётр Седов
Форумчанин
 
Регистрация: 26.10.2022
Сообщений: 119
По умолчанию

agent2, попробуйте так:
Код:
#include <limits.h>
#include <algorithm>
#include <fstream>
#include <iostream>

using namespace std;

void print_nums_reverse(const char* file_path) {
  ifstream file(file_path, ios::binary);
  if (file.fail()) {
    cerr << "Cannot open file \"" << file_path << "\"." << endl;
    return;
  }

  // первый проход: определяем минимальное и максимальное число
  int min = INT_MAX;
  int max = INT_MIN;
  int nums_count = 0;
  int n;
  while (file.read(reinterpret_cast<char*>(&n), sizeof(int))) { // нет нарушения strict aliasing, там специально оговорен случай для char
    min = std::min(min, n);
    max = std::max(max, n);
    nums_count++;
  }
  if (nums_count != 0) {
    cout << "min = " << min << ", max = " << max << endl;
  }

  // второй проход: выводим числа в обратном порядке
  file.clear(); // убираем eofbit
  for (int i = nums_count - 1; i >= 0; i--) {
    file.seekg(i * sizeof(int), ios::beg);
    file.read(reinterpret_cast<char*>(&n), sizeof(int));
    if ((min < n) && (n < max)) {
      cout << n << ' ';
    }
  }
  cout << endl;

  // file.close вызывать не обязательно, деструктор сделает всё что надо
}
Цитата:
Сообщение от agent2 Посмотреть сообщение
Код:
    if (fout.is_open())
    {
        int Y = -10;
        int X = 20 + 1;
        int Y2 = 1;
        int X2 = 50 + 1;
        int countNums = rand() % (X2 - Y2) + Y2;
        cout << countNums << endl;

        if (fout.is_open())
Не надо одно и то же проверять два раза.
Цитата:
Сообщение от agent2 Посмотреть сообщение
Код:
        cout << "Error\n";
        exit(0);
Обычно консольные программы делают так, что ноль возвращается в случае успеха, а если случилась ошибка, то возвращается не ноль. По науке для этого даже специальные константы есть: EXIT_SUCCESS, EXIT_FAILURE. Но их редко используют.
Пётр Седов вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
прочитать stringlist с конца nibufep Общие вопросы Delphi 2 06.05.2016 00:39
C++, задача на бинарный файл (Бинарный файл состоит из записей по 5 бит) zaitsevmishka Помощь студентам 3 16.05.2014 21:39
Бинарный файл. Чтение записи с конца. rommster Общие вопросы C/C++ 30 12.12.2012 23:45
Прочитать бинарный файл Lazan Помощь студентам 6 16.06.2010 14:19
Не могу прочитать файл до конца... FEAR Общие вопросы C/C++ 9 04.01.2007 21:46