2016-12-07 10 views
1
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#define SLENG 50 //just a random value 

typedef struct Song 
{ 
    char *name; 
    char *nameSong; 
    char *timeSong; 
    int date; 
} Song; 

void saveToFile(Song *x, int *songCount) //Saves info to the binary file 
{ 
    FILE *f = fopen("array.txt", "w"); 
    if (f == NULL) 
    { 
     printf("Error\n"); 
    } 
    fwrite(songCount, sizeof(int), 1, f); 
    fwrite(x, sizeof(struct Song), (*songCount), f); 
    fclose(f); 
} 

void readSong(Song *x, int *songCount) //Reads info fromt he file and writes it 
{ 
    FILE *fr = fopen("array.txt", "r"); 
    if (fr == NULL) 
    { 
     printf("Error\n"); 
    } 
    printf("Songs:\n"); 
    fread(songCount, sizeof(int), 1, fr); 
    fread(x, sizeof(struct Song), (*songCount), fr); 
    for(int i=0; i < (*songCount); i++) 
    { 
     printf("%d. %s %s %s %d\n", (i+1), x[i].name, x[i].nameSong, x[i].timeSong, x[i].date); 
    } 
    fclose(fr); 
} 

void insertSong(Song *x, int Count) //Inserts new song into the array. 
{ 
    printf("\nInsert name of the band:\n"); 
    x[Count].name=malloc(SLENG * sizeof(char)); 
    scanf("%s", x[Count].name); 

    printf("Insert name of the song:\n"); 
    x[Count].nameSong=malloc(SLENG * sizeof(char)); 
    scanf("%s", x[Count].nameSong); 

    printf("Insert length of the song:\n"); 
    x[Count].timeSong=malloc(SLENG * sizeof(char)); 
    scanf("%s", x[Count].timeSong); 

    printf("Insert then song was created:\n"); 
    scanf("%d", &(x[Count].date)); 
    printf("\n"); 
} 

main() 
{ 
    int songCount, menuOption; 
    Song *x=malloc(SLENG*sizeof(char)+SLENG*sizeof(char)+SLENG*sizeof(char)+sizeof(int)); 
    printf("1. insert song\n 2. load from file\n "); 
    scanf("%d", &menuOption); 
    switch(menuOption) 
    { 
     case(1) : 
      printf("Insert how many songs do you want to input?\n"); 
      scanf("%d", &songCount); 
      for(int i=0; i<songCount; i++) 
      { 
       insertSong(x, i); 
      } 
      saveToFile(x, &songCount); 
      break; 
     case(2) : 
      readSong(x, &songCount); 
      break; 
    } 
} 

У меня есть assingment написать программка, которая будет ввод некоторых данных в файл и может прочитать эти данные из этого файла, проблема, вероятно, с FWRITE или fread, couse, кажется, сбой каждый раз, когда я пытаюсь загрузить и записать данные из файла. Любые идеи, почему это не работает должным образом? И могу ли я сделать это так, как это динамический массив структуры. Заранее спасибо.C не загружает данные из файла (Fread, FWRITE)

+2

Добро пожаловать на переполнение стека! Похоже, вам, возможно, потребуется научиться использовать отладчик для выполнения вашего кода. С хорошим отладчиком вы можете выполнить свою программу по очереди и посмотреть, где она отклоняется от ожидаемого. Это важный инструмент, если вы собираетесь заниматься программированием. Дальнейшее чтение: [Как отлаживать небольшие программы] (https://ericlippert.com/2014/03/05/how-to-debug-small-programs/). –

+2

Указатели относятся только к одному процессу. Вы не можете сохранить указатели. Невозможно загрузить указатели в другой процесс, даже если это одна и та же программа. Либо используйте массивы, либо придумайте способ [* serialize *] (https://en.wikipedia.org/wiki/Serialization) данных в каждой структуре. И да, указатели - это все, что вы экономите. –

+0

Что касается массивов, вы выделяете символы «SLENG» для каждой строки, всегда и безоговорочно. Это действительно не лучше, чем наличие массива фиксированного размера времени компиляции. –

ответ

2

Чтобы сохранить структуру в файле, она должна содержать только скалярные значения, а не указатели на объекты памяти. Измените структуру использовать массивы вместо указателей:

typedef struct Song { 
    char name[SLENG]; 
    char nameSong[SLENG]; 
    char timeSong[SLENG]; 
    int date; 
} Song; 

и изменить код соответственно, но учтите, что:

  • сохранения и чтения структуры и из файла необходимо открыть его в двоичном режиме "wb" и "rb".
  • очень вводящий в заблуждение, чтобы назвать двоичный файл array.txt.
  • вам не нужно передавать адрес счета при записи в файл, но вам нужно передать адрес указателя массива при чтении, поскольку вы еще не знаете, сколько памяти выделяется.

Вот измененный код:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

#define SLENG 50 // this value is used in the file format 

typedef struct Song { 
    char name[SLENG]; 
    char nameSong[SLENG]; 
    char timeSong[SLENG]; 
    int date; 
} Song; 

int saveToFile(Song *x, int songCount) { //Saves info to the binary file 
    FILE *f = fopen("array.bin", "wb"); 
    if (f == NULL) { 
     printf("Error\n"); 
     return -1; 
    } 
    fwrite(songCount, sizeof(int), 1, f); 
    int written = fwrite(x, sizeof(struct Song), songCount, f); 
    fclose(f); 
    return written; 
} 

int readSong(Song **x, int *songCount) { //Reads info from the file and writes it 
    int count = 0; 
    FILE *fr = fopen("array.bin", "rb"); 
    if (fr == NULL) { 
     printf("Error\n"); 
     return -1; 
    } 
    printf("Songs:\n"); 
    fread(&count, sizeof(int), 1, fr); 
    *x = calloc(count, sizeof(Song)); 
    if (*x == NULL) { 
     printf("Cannot allocate %d bytes of memory\n", count); 
     fclose(fr); 
     return -1; 
    } 
    int found = fread(*x, sizeof(struct Song), count, fr); 
    for (int i = 0; i < found; i++) { 
     printf("%d. %s %s %s %d\n", i + 1, 
       (*x)[i].name, (*x)[i].nameSong, (*x)[i].timeSong, (*x)[i].date); 
    } 
    fclose(fr); 
    return *songCount = found; 
} 

void insertSong(Song *x, int Count) { //Inserts new song into the array. 
    printf("\nInsert name of the band:\n"); 
    scanf("%49s", x[Count].name); 

    printf("Insert name of the song:\n"); 
    scanf("%49s", x[Count].nameSong); 

    printf("Insert length of the song:\n"); 
    scanf("%49s", x[Count].timeSong); 

    printf("Insert then song was created:\n"); 
    scanf("%d", &(x[Count].date)); 
    printf("\n"); 
} 

int main(void) { 
    int songCount, menuOption; 
    Song *x = NULL; 

    printf("1. insert song\n 2. load from file\n "); 
    scanf("%d", &menuOption); 

    switch (menuOption) { 
     case 1: 
     printf("Insert how many songs do you want to input?\n"); 
     if (scanf("%d", &songCount) == 1) { 
      x = calloc(songCount, sizeof(Song)); 
      for (int i = 0; i < songCount; i++) { 
       insertSong(x, i); 
      } 
      saveToFile(x, songCount); 
     } 
     break; 
     case 2: 
     readSong(&x, &songCount); 
     break; 
    } 
    free(x); 
    x = NULL; 

    return 0; 
} 
+0

Вы изменили аргументы в функции calloc – Fefux

+0

@Fefux: порядок аргументов 'calloc()' не имеет никакого влияния, но он действительно документирован как 'void * calloc (size_t nmemb, size_t size); 'в стандарте C, который несовместим с' size_t fread (void * ptr, size_t size, size_t nmemb, FILE * stream); 'и' fwrite() ', хотя и совместим с' bsearch' и 'qsort'. – chqrlie

+0

Да, но это только для документации – Fefux

 Смежные вопросы

  • Нет связанных вопросов^_^