如何将输入写入二进制文件并在 c 中读取?

How to write inputs into a binary file and read it in c?

最近我在做一个初学者项目。但是我不知道如何更新文件被困了好几天。然后我发现我可以用二进制文件来做,所以我开始使用二进制文件而不是普通文件。但是现在当我写入二进制文件时它可以工作(我假设),但是当我从它读取时,它给了我 segmentation fault (core dumped).

这是我的结构

struct date{  // structure for dates
    int mm, dd, yyyy;
};

struct {
    char *initials, *name, *email, *acc_type;  // unchangeable values 
    char id_num[11], occupation[25], address[100];  // changeable values
    int phone, acc_num, balance;
    struct date birth_day;  // structure for birth day
} new_acc;

这是我的写作功能...

void create_new(void)
{
    // Allocating memory for each member in struct
    new_acc.name = (char *) malloc(sizeof(new_acc.name));  
    new_acc.initials = (char *) malloc(sizeof(new_acc.initials));
    new_acc.email = (char *) malloc(sizeof(new_acc.email));
    new_acc.acc_type = (char *) malloc(sizeof(new_acc.acc_type));

    system("clear");
    puts("Answer the questions to make a account");

    time_t l;  // To generate a number
    srand((unsigned) time(&l));  // Generating a random number to account number
    new_acc.acc_num = l;  // Assign l value to acc_num var in struct

    printf("Enter your full name: ");
    scanf(" %100[^\n]", new_acc.name);  // scan for name, 100 characters, and also accepting spaces

    printf("Enter your name with initials: ");
    scanf(" %100[^\n]", new_acc.initials);

    printf("Enter your birthday (mm/dd/yyyy): ");
    scanf(" %d %d %d", &new_acc.birth_day.mm, &new_acc.birth_day.dd, &new_acc.birth_day.yyyy)

    printf("Enter your address: ");
    scanf(" %100[^\n]", new_acc.address);

    printf("Enter your phone number: ");
    scanf(" %10d", &new_acc.phone);

    printf("Enter your id number: ");
    scanf(" %10[0-9a-zA-Z]", new_acc.id_num);

    printf("Enter your occupation: ");
    scanf(" %50[^\n]", new_acc.occupation);

    printf("Enter your email address:");
    scanf(" %s", new_acc.email);

    printf("Enter the account type:\n");
    printf("\t#Saving\n\tFixed (1 year)\n\tFixed (2 year)\n\tFixed (3 year)\n");
    scanf(" %20s", new_acc.acc_type);

    printf("Enter amount to deposite: $");
    scanf(" %d", &new_acc.balance);

    FILE *fp;
    fp = fopen("employees", "a");  // Opening file in append mode 

    if (fp == NULL)  // If  file couldn't open 
        puts("Cannot open a file...");

    // Here, I also used while loop, but I don't know how to break it so I used for loop
    for (int i = 0; i <= 12; ++i)  // Looping 12 times  
        fwrite(&new_acc, sizeof(new_acc), 1, fp);  // writting to file 

     fclose(fp);  // Closing file

    // freeing memory after use
    free(new_acc.name);
    free(new_acc.initials);
    free(new_acc.email);
    free(new_acc.acc_type);

    int out;
    printf("Successfully created a account!\nYour account number is %d\n", new_acc.acc_num);
    printf("Press 1 to exit, and 0 to go to main menu...");
    scanf("%d", &out);

    switch (out){
    case 1:
        exit(0);
        break;
    case 0:
        menu();
        break;
    }
}

这里还有我的阅读代码片段

FILE *fp; 
    fp = fopen("employees", "r");

    if (fp == NULL)
        puts("Cannot open a file...");

    for (int i = 0; i <= 12; ++i)
        fread(&new_acc, sizeof(new_acc), 1, fp);

    fclose(fp);

    printf("%d\n", new_acc.acc_num); // It only prints acc_num
    // After that it gives me segmentation fault 
    printf("%s\n", new_acc.name);
    printf("%s\n", new_acc.initials);
    printf("%s\n", new_acc.birth_day);
    printf("%s\n", new_acc.address);
    printf("%d\n", new_acc.phone);
    printf("%s\n", new_acc.id_num);
    printf("%s\n", new_acc.occupation);
    printf("%s\n", new_acc.email);
    printf("%s\n", new_acc.acc_type);
    printf("%d\n", new_acc.balance);

我不确定是否正确写入和读取 bin 文件...

我在写入 bin 文件和从中读取时都出错了。

首先要感谢@lulle

  • 正如他在评论中提到的,我将结构中的 char* 更改为 char 数组。
char initials[80], name[250], email[100], acc_type[25];
  • 我还更改了文件模式。我使用 ab 来编写代码片段。并且 rb 在阅读片段中。

  • 然后我更改了我的写作片段。

这里我循环了12次,每条记录写了12次。伤心啊? 发生这种情况是因为我在 fwrite 中只使用了结构 &new_acc 的地址。如果您在 fwrite`` or fread``` 中只使用一个结构的地址,它将写入您的整个结构。那就是发生在我身上的事。我写了整个结构 12 次。

for (int i = 0; i <= 12; ++i)  // Looping 12 times  
        fwrite(&new_acc, sizeof(new_acc), 1, fp);  // writting to file 

所以我没有循环,而是改成了这个

fwrite(&new_acc, sizeof(new_acc), 1, fp); \ This line will write whole struct

但是如果你想使用结构的成员而不是整个结构,你可以自由使用循环。这是一个例子。这个例子和上面的一样。但请记住在写入文件时使用 i 或您在 for 循环中使用的任何变量。而不是 i,如果你使用成员名称,它也会写 12 次(或者直到你正在循环......)

for (int i = 0; i <= 12; ++i)  // Looping 12 times  
        fwrite(&new_acc.[i], sizeof(new_acc.[i]), 1, fp);  // writting to file 
  • 同样的事情发生在阅读部分(我猜……)。 所以我更改了如下代码片段
    FILE *fp; 
    fp = fopen("employees", "rb");

    if (fp == NULL)
        puts("Cannot open a file...");

    int i = 0;
    while(fread(&new_acc, sizeof(new_acc), 1, fp) != 0){  /* use fread one time */
    printf("%d\n", new_acc.acc_num);
    printf("%s\n", new_acc.name);
    printf("%s\n", new_acc.initials);
    printf("%s\n", new_acc.birth_day);
    printf("%s\n", new_acc.address);
    printf("%d\n", new_acc.phone);
    printf("%s\n", new_acc.id_num);
    printf("%s\n", new_acc.occupation);
    printf("%s\n", new_acc.email);
    printf("%s\n", new_acc.acc_type);
    printf("%d\n", new_acc.balance);    
    
    ++i;
    }

    fclose(fp);