Записать структуру в файл && прочитать структуру в динамически выделяемую память

Я пытаюсь записать структуру в файл, а затем прочитать структуру в динамически выделяемой памяти. Если этот алгоритм вообще работает, я не уверен насчет функции fread ... Может ли он прочитать все структуры в файле, написанном таким образом, и сохранить их в * ptr, чтобы я мог получить к нему доступ из памяти? Есть способ сделать это лучше?

 typedef struct num {
    int num1;
    int num2;   
}NR;

void write() {
    int successfullywritten;
    FILE *f;
    struct num nr;
    f = fopen("dat.txt", "a");
    printf("Enter first number\n");
    scanf("%d", &nr.num1);
    printf("Enter second number\n");
    scanf("%d", &nr.num2);
    successfullywritten=fwrite(&nr, sizeof num, 1, f);
    printf("Succesfully written: %d\n", successfullywritten);
    fclose(f);
}

void read() {

    int size, entrys,i,successfullyread;
    FILE *f;
    f = fopen("dat.txt", "r");
    struct num *ptr;
    fseek(f, 0L, SEEK_END);
    size = ftell(f);
    printf("\nSize of file dat.txt: %d\n", size);
    entrys = size / sizeof(num);
    ptr = (num*)malloc(entrys * sizeof(num));
    successfullyread=fread(ptr, sizeof(num), entrys, f);
    printf("sucessfully Read: %d\n", successfullyread);
    for (i = 0;i < entrys; i++) {
        /*fread((ptr+i), sizeof(ptr), 1, f);*/
        printf("%d  ", (*(ptr)).num1);
        printf("%d\n", (*(ptr)).num2);

    }
    printf("\n");printf("\n");

    fclose(f);
}

int main() {
    int n;
    while(1){
       printf("Chooose action:\n1) write to file\n2) read from file:\n");
       scanf("%d", &n);
       switch (n) {
          case 1:
             write();
             break;
          case 2:
             read();
             break;
       }
    }
    return 0;
}

на самом деле это не .txt, это .dat

purec 04.06.2018 14:09

Вы заинтересованы в хранении значений элементов структуры в файле или в сохранении самой структуры? В любом случае, подход список может лучше служить вашим интересам.

ryyker 04.06.2018 14:10

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

Serge Ballesta 04.06.2018 14:17
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
78
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Во-первых, есть много простых опечаток, таких как

  • Возникает путаница между типизированным именем или именем структуры. Этот entrys = size / sizeof(num); должен быть entrys = size / sizeof(struct num);
  • Этот ptr = (num*)malloc(entrys * sizeof(num)); должен быть ptr = malloc(entrys * sizeof(struct num));. Избегайте кастинга результата malloc().

Во-вторых, обнаружив size, вы забыли переместить f в начало файла. например, для

fseek(f, 0L, SEEK_END);
size = ftell(f);
fseek(f, 0L, SEEK_SET); /* you forgot to add this */ 

В-третьих, вы записываете данные в файл, используя fwrite(), используйте ab вместо режима a. & при чтении с использованием fread() используйте rb вместо r.

Также после чтения из файла вам необходимо освободить ptr, чтобы избежать утечки памяти.

free(ptr);

Вот пример кода

typedef struct num {
        int num1;
        int num2;
}NR;
void my_write(void) {
        int successfullywritten;
        FILE *f;
        struct num nr;
        f = fopen("dat.txt", "ab");
        printf("Enter first number\n");
        scanf("%d", &nr.num1);
        printf("Enter second number\n");
        scanf("%d", &nr.num2);
        successfullywritten=fwrite(&nr, sizeof(nr), 1, f);
        printf("Succesfully written: %d\n", successfullywritten);
        fclose(f);
}

void my_read(void) {

        int size, entrys,i,successfullyread;
        FILE *f;
        f = fopen("dat.txt", "rb");
        struct num *ptr;
        fseek(f, 0L, SEEK_END);
        size = ftell(f);
        fseek(f, 0L, SEEK_SET);
        printf("\nSize of file dat.txt: %d\n", size);
        entrys = size / sizeof(struct num);

        ptr = malloc(entrys * sizeof(struct num));
        successfullyread=fread(ptr, sizeof(struct num), 2, f);
        printf("sucessfully Read: %d\n", successfullyread);

        for (i = 0;i < entrys; i++) {
                /*fread((ptr+i), sizeof(ptr), 1, f);*/
                printf("%d  ", ptr[i].num1);
                printf("%d\n", ptr[i].num2);

        }
        free(ptr);
        printf("\n");printf("\n");
        fclose(f);
}
int main(void) {
        int n;
        while(1){
                printf("Chooose action:\n1) write to file\n2) read from file:\n");
                scanf("%d", &n);
                switch (n) {
                        case 1:
                                my_write();
                                break;
                        case 2:
                                my_read();
                                break;
                }
        }
        return 0;
}

Вы уверены, что заявление size = ftell(f); дает то, что необходимо? (с учетом его последующего использования)

ryyker 04.06.2018 14:39

Нет, я не уверен. Во-первых, файл содержит двоичные данные, поэтому я сомневаюсь в этой формуле entrys = size / sizeof(struct num);

Achal 04.06.2018 14:41

Да, у меня тоже есть такие же сомнения. Не стесняйтесь редактировать, если это необходимо.

Achal 04.06.2018 14:47

Поскольку ftell() возвращает long, long size может работать с большими файлами, которые не работают с int size.

chux - Reinstate Monica 04.06.2018 17:13

Другие вопросы по теме