C不加载从文件信息(FREAD,FWRITE)

问题描述:

#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写PROGRAMM这将输入一些数据文件,并可以从文件中读取数据,该问题可能与FWRITE或fread,当我尝试从文件加载并写入数据时,似乎崩溃了。任何想法为什么它不能正常工作?我甚至可以这样做,因为它是动态结构数组。提前致谢。C不加载从文件信息(FREAD,FWRITE)

+2

欢迎堆栈溢出!这听起来像你可能需要学习如何使用调试器来遍历代码。使用一个好的调试器,您可以逐行执行您的程序,并查看它与您期望的偏离的位置。如果你打算做任何编程,这是一个重要的工具。进一步阅读:[如何调试小程序](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/)。 –

+2

指针特定于单个进程。你不能保存指针。没有办法将指针加载到另一个进程中,即使它是相同的程序。要么使用数组,要么想出一种方法来[*序列化*](https://en.wikipedia.org/wiki/Serialization)每个结构中的数据。是的,指针都是你保存的。 –

+0

至于数组的问题,你总是无条件地为每个字符串分配'SLENG'字符。这确实比编译时固定大小的数组要好。 –

为了将结构保存到文件中,它必须只包含标量值,而不是指向内存对象的指针。修改您的结构,而不是使用指针数组:

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(尽管与'bsearch'一致,但在C标准中与'size_t fread(void * ptr,size_t size,size_t nmemb,FILE * stream);'和'fwrite()'不一致'和'qsort'。 – chqrlie

+0

是的,但它只是符合文档 – Fefux