Заполнить бинарный файл случайными числами (Си, С++)

Прикладное программирование Программирование на С++ Решение задач на С++ Заполнить бинарный файл случайными числами (Си, С++)

Помечено: ,

  • В этой теме 0 ответов, 1 участник, последнее обновление 2 месяца, 2 недели назад сделано Васильев Владимир Сергеевич.
Просмотр 0 веток ответов
  • Автор
    Сообщения
    • #6667
      @admin
      StudLance.ru

      Задача:
      написать программу, генерирующую файл с заданным количеством случайных целых чисел.

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

      Решение на языке Си

      Функция main будет запрашивать у пользователя количество чисел, вызывать вспомогательную функцию генерации (writeRandom) и выводить содержимое файла на экран (функция printFile):

      int main(void) {
        setlocale(LC_ALL, "Russian" );
        char *filename = "input.bin";
        int n;
      
        printf("Введи количество чисел: ");
        scanf("%d", &n);
      
        int errorCode = writeRandom(filename, n);
        if (errorCode != 0)
          return errorCode;
      
        errorCode = printFile(filename);
        return errorCode;
      }

      Для поддержки русских букв в консоли вызывается функция setlocale с параметром "Russian".

      Функции writeRandom и printFile нулевое значение при успешном завершении работы, иначе — код ошибки. Если по каким-то причинам функции writeRandom не удалось записать в файл числа — то приложение завершает работу сразу, не вызывая printFile.

      Функция writeRandom открывает файл для записи (с параметром "w+"), генерируют с помощью стандартной функции rand нужное количество чисел, каждое выводя в файл, и закрывает файл:

      int writeRandom(char* filename, int n) {
        FILE *pFile;
        srand (time(NULL));
      
        if((pFile = fopen(filename, "w+"))==NULL) {
          perror("Не удалось открыть файл");
          return 1;
        }
      
        for (int i = 0; i < n; ++i) {
          int value = rand() % 100 - 50;
          value *= value;
          fwrite(&value, sizeof(int), 1, pFile);
        }
      
        fclose(pFile);
        return 0;
      }

      Генератор случайных чисел выполняет генерацию на основании некоторого начального числа. Если его не задавать — то при каждом запуске программы мы будем получать одни и теже числа. Функция srand задает это начальное значение, при этом в качестве аргумента пердается результат работы функции time(NULL), возвращающей текущее значение времени. Таким образом, начальное значение зависит от момента времени и при каждом запуске программы мы будем получать разные числа в файле.

      Функция rand возвращает случайное число в большом диапазоне. Чтобы получить число в диапазоне от нуля до 100 мы применяем к результату операцию получения остатка от деления. Если от такого результата отнять еще 50 — то получится число от -50 до 50, т. к. например:

      82-50 = 32, 
      24-50 = -26.

      Вызов функции

      fwrite(&value, sizeof(int), 1, pFile);

      Нужно читать так:
      1. возьми байты по адресу &value;
      2. работай с ними группами по sizeof(int) байт, т. е. по столько байт, сколько нужно для представления одного целого числа:
      3. одну такую группу запиши в файл с дескриптором pFile.
      Функция printFile открывает файл для чтения (с опцией "r"), считывает значения с помощью функции read, выводит их по очереди на экран и закрывает файл.

      int printFile(char* filename) {
        FILE *pFile;
        if((pFile = fopen(filename, "r"))==NULL) {
          perror("Не удалось открыть файл");
          return 1;
        }
        printf("Содержимое файла:\n");
        int value;
        while (0 != fread(&value, sizeof(int), 1, pFile)) {
          printf("%d ", value);
        }
        printf("\n");
        fclose(pFile);
        return 0;
      }

      Считывание производится до тех пор, пока файл не кончится — при этом функция fread вернет нулевое значение (обычно она возвращает количество считанных байт). Именно поэтому результат fread сравнивается с нулем.

      Вызов функции

      fread(&value, sizeof(int), 1, pFile)

      Нужно читать так:
      1. Производи чтение с файла с дескриптором pFile группами по sizeof(int) байт, т. е. по столько байт, сколько нужно для представления одного целого числа;
      2. Считай 1 группу и помести ее по адресу &value.

      Пример диалога пользователя с системой приведен на рисунке:

      Исходный код программы целиком:

      #include <stdio.h>
      #include <stdlib.h>
      #include <time.h>
      #include <locale.h>
      int writeRandom(char* filename, int n) {
        FILE *pFile;
        srand (time(NULL));
        if((pFile = fopen(filename, "w+"))==NULL) {
          perror("Не удалось открыть файл");
          return 1;
        }
      
        for (int i = 0; i < n; ++i) {
          int value = rand() % 100 - 50;
          value *= value;
          fwrite(&value, sizeof(int), 1, pFile);
        }
      
        fclose(pFile);
        return 0;
      }
      int printFile(char* filename) {
        FILE *pFile;
        if((pFile = fopen(filename, "r"))==NULL) {
          perror("Не удалось открыть файл");
          return 1;
        }
        printf("Содержимое файла:\n");
        int value;
        while (0 != fread(&value, sizeof(int), 1, pFile)) {
          printf("%d ", value);
        }
        printf("\n");
        fclose(pFile);
        return 0;
      }
      int main(void) {
        setlocale(LC_ALL, "Russian" );
        char *filename = "input.bin";
        int n;
        printf("Введи количество чисел: ");
        scanf("%d", &n);
        int errorCode = writeRandom(filename, n);
        if (errorCode != 0)
          return errorCode;
        errorCode = printFile(filename);
        return errorCode;
      }

      Решение на С++

      Содержимое двоичного файла нельзя понять при открытии в текстовом редакторе и при открытии в двоичном — тоже нелегко. Однако нам надо будет проверять что работа выполнена верно, для этого напишем функцию, выводящую на экран содержимое двочного файла, состоящего из целых чисел:

      int printFile(const char* fname) {
        ifstream ifst(fname, ios_base::binary|ios::in);
        if (false == ifst.is_open())
          return 1;
        cout << "in file " << fname << ": " << endl;
        while (false == ifst.eof()) {
          int value;
          ifst.read((char*)&value, sizeof(int));
          cout << value << " ";
        }
        cout << endl;
        return 0;
      }

      Она принимает на вход имя файла, возвращает код ошибки (если ошибок нет — то ноль). До тех пор пока не кончится файл (eof не вернет true) функция считывает из файла целое число (sizeof(int) байт) и выводит его на экран.

      Для заполнения файла случайными числами также напишем функцию:

      int fillRandom(const char* fname, int n) {
        ofstream ofst(fname, ios_base::binary|ios::out);
        if (false == ofst.is_open())
          return 1;
        for (int i = 0; i < n; ++i) {
          int value = rand() % 100;
          ofst.write((char*)&value, sizeof(int));
        }
        return 0;
      }

      Она генерирует n случайных чисел и помещает их в файл. Обработка ошибок такая же как в предыдущей функции.
      Как при записи, так и при чтении число приводится к типу char* — массив байт, так как функции read/write работают с двоичными данными, т. е. с байтами, а char в С++ — это не только символ, но и байт.

      StudLance.ru

Просмотр 0 веток ответов
  • Для ответа в этой теме необходимо авторизоваться.
×