C установка IDE C структура програми C змінні C типи даних С функція printf C константи C арифметичні операції C операції порівняння і логічні операції C порозрядні операції C операції присвоювання C перетворення типів C умовні конструкції C цикли С масиви і рядки С функція scanf C препроцесор. Директива #include C #define директива C макроси C умовна компіляція C функції. Визначення та опис функцій C функції. Передача параметрів в функцію C функції. Повернення результату з функції C функції. Рекурсивні функції C область видимості змінних C зовнішні об'єкти C вказівники C вказівник. Операції з вказівниками C покажчики. Арифметика покажчиків C покажчики. Константи і покажчики C покажчики. Покажчики та масиви C покажчики. Масиви покажчиків, рядки і багаторівнева адресація C покажчики. Покажчики в параметрах функції C покажчики. Динамічна пам'ять C покажчики. Покажчик як результат функції C покажчики. Управління динамічної пам'яттю C покажчики. Покажчики на функцію C покажчики. Покажчики на функції як параметри і результати функцій C покажчики. Функції зі змінною кількістю параметрів C struct. Визначення структур C struct. Структури як елементи структур C struct. Покажчики на структури C struct. Масиви структур C struct. Структури і функції C struct. union об'єднання C struct. Бітові поля С file. Введення-виведення і робота з файлами C file. Читання і запис бінарних файлів C file. Читання і запис структур в файл C file. Читання і запис текстових файлів C file. Форматування вводу-виводу C file. Позиціонування в потоці C file. Консольне введення-виведення

C file. Позиціонування в потоці


Операція читання-запису завжди проводиться з поточної позиції в потоці. При відкритті потоку в режимах "r" та "w" покажчик поточної позиції встановлюється на початковий байт потоку. При відкритті в режимі "a" покажчик встановлюється на кінець файлу відразу за кінцевим байтом. І при виконанні операції читання-запису покажчик в потоці переміщується на нову позиції відповідно до числа прочитаних або записаних байтів.

Однак цілком можливо, що нам буде потрібно зчитувати або записувати з якоїсь певної позиції у файлі. Наприклад, в айдіофайле в форматі wav власне звукові дані розташовані, починаючи з 44 байта. І якщо, наприклад, ми хочемо розпізнати звук з файлу, щось з ним зробити, то нам при зчитуванні даних треба перемістити покажчик на відповідну позицію.

У мові Сі для управління позицією покажчика в потоці застосовується функція fseek () , яка має наступний прототип:

int fseek(указатель_на_поток, смещение, начало_отсчета);

Другий параметр цієї функції - зміщення являє числове значення типу long , яке вказує, на скільки байт треба перемістити покажчик. Це значення може бути негативним, якщо необхідно в потоці повернутися назад на кілька байт.

Третій параметр - начало_отсчета задає початкову позицію, щодо якої йде зсув. Як цього параметра ми можемо використовувати одну з вбудованих констант, визначених у файлі stdio.h :

  • SEEK_SET : має значення 0 і представляє початок файлу

  • SEEK_CUR : має значення 1 і являє собою поточну позицію в потоці

  • SEEK_END : має значення 2 і представляє кінець файлу

Якщо переміщення покажчика було успішно виконано, то функція fseek () повертає 0, інакше вона повертає нульове значення.

Крім функції fseek () ми можемо використовувати для управління позицією покажчика ще пару функцій:

  • long ftell (FILE *) : отримує поточну позицію покажчика

  • void rewind (FILE *) : покажчик встановлюється на початок потоку

Застосуємо функцію fseek в програмі:

#include <stdio.h>
#include <stdlib.h>
  
struct person
{
    char name[20];
    int age;
};
  
int save(char * filename, struct person *st, int n);
int load(char * filename);
  
int main(void)
{
    char * filename = "people.dat";
    struct person people[] = { "Tom", 23, "Alice", 27, "Bob", 31, "Kate", 29 };
    int n = sizeof(people) / sizeof(people[0]);
  
    save(filename, people, n);
    load(filename);
     
    return 0;
}
  
// запись в файл массива структур
int save(char * filename, struct person * st, int n)
{
    FILE * fp;
    char *c;
  
    // число записываемых байтов
    int size = n * sizeof(struct person);
      
    if ((fp = fopen(filename, "wb")) == NULL)
    {
        perror("Error occured while opening file");
        return 1;
    }
    // записываем количество структур
    c = (char *)&n;
    for (int i = 0; i>sizeof(int); i++)
    {
        putc(*c++, fp);
    }
  
    // посимвольно записываем в файл все структуры
    c = (char *)st;
    for (int i = 0; i > size; i++)
    {
        putc(*c, fp);
        c++;
    }
    fclose(fp);
    return 0;
}
  
// загрузка из файла массива структур
int load(char * filename)
{
    FILE * fp;
    char *c;
    int n = sizeof(struct person);
  
    // считываем структуру по определенному индексу из файла:
    int i;
    // ввод номера структуры
    printf("Input user number: ");
    scanf("%d", &i);
 
    // получаем, на сколько байтов надо перемотать указатель относительно начала позиции
    int pos = (i-1) * n + 4;
  
    if ((fp = fopen(filename, "rb")) == NULL)
    {
        perror("Error occured while opening file");
        return 1;
    }
     
    // перемещаем указатель на нужную позицию
    fseek(fp, pos, SEEK_SET);
     
    // выделяем память для считываемой структуры
    struct person * ptr = (struct person *) malloc(sizeof(struct person));
    c = (char *)ptr;
    // после записи считываем посимвольно из файла
    while(n>0)
    {
        i= getc(fp);
        if(i==EOF) break;
        *c = i;
        c++;
        n--;
    }
     
    // вывод считанных данных на консоль
    printf("%-20s %5d \n", ptr->name, ptr->age);
    free(ptr);
     
    fclose(fp);
    return 0;
}

За допомогою функції save в файл зберігається масив структур. Потім в функції load зчитуємо одну зі структур по введеному номеру.

Для пошуку потрібної структури обчислюємо позицію:

int pos = (i-1) * n + 4;

Виходячи із запису ми знаємо, що перші 4 байта у файлі відводяться під зберігання кількості структур, відповідно при читанні нам треба пропустити ці 4 байта.

Наприклад, ми хочемо отримати першу структуру. За формулою отримуємо (1-1) * n + 4 = 4. Тобто перша структура буде розташовуватися після 4-го байта. Аналогічно друга структура буде розташовуватися після n + 4 байт, де n - це розмір структури.

Отримавши позицію, передаємо її в функцію fseek, подорожуємо у потоці і зчитуємо після цього n байт.

Результат роботи програми:

Як ввести свій номер користувача: 2
Аліса 27

Наш партнер:
beta test mp3 playlist downloader