C - 修改二进制文件中的记录,输出到文本文件将0插入文本文件

时间:2016-03-08 13:08:33

标签: c

我的C文件中有3个函数用于二进制文件:accadd用于添加记录,视图用于输出文本文件,修改用于修改记录。

记录具有以下结构:

struct date
{
    int day;
    int month;
    int year;
};

struct customer
{
    char name[40], acctype[10];
    int accno, age;
    double phone;
    float amount;
    struct date deposit;
} add;

视图功能不输出所有变量,只输出name,accno和phone。例如,添加了2个记录,这是输出文件:

Customer's List
Customer's Name:    Account Number: Customer's Phone No:
            John                  1            777777777
            Mary                  2            111111111

这很好,除非我运行修改功能并再次输出文件:

Customer's List
    Customer's Name:    Account Number: Customer's Phone No:
                John                  1            999999999
                Mary                  2            111111111
                                      0                    0
                                      0                    0
                                      0                    0
                                      0                    0
                                      0                    0
                                      0                    0
                                      0                    0
                                      0                    0
                                      0                    0
                                      0                    0
                                      0                    0
                                      0                    0
                                      0                    0

记录被修改但我得到了一堆领先的0。有什么理由吗?

修改功能:

void modify(char file[30]){
    FILE *view;
    int counter = 0;

    view = fopen(file, "rb+");

    if (view == NULL)
        exit(1);

    while (fread(&add, sizeof(add), 1, view) != 0)
    {
        if(add.phone==777777777){
            printf("Old phone is: %lf\n",add.phone);
            printf("New phone:\n");
            scanf("%lf", &add.phone);
            printf("New phone is: %lf\n",add.phone);
            fseek(view,sizeof(add)*counter,SEEK_SET);
            fwrite(&add,sizeof(add),1,view);
        }
        counter++;
    }
    fclose(view);

    if (counter == 0)
    {
        printf("NO RECORDS FOUND!\n");

    }
    else{
        printf("add.phone printed\n");
    }
}

EDIT1:视图功能。

void view(char file[30])
{
    FILE *view,*output;
    int test = 0;
    output=fopen("output.txt", "w");
    fprintf(output,"Customer's List\n");
    fprintf(output,"\tCustomer's Name:");
    fprintf(output,"\tAccount Number:");
    fprintf(output,"\tCustomer's Phone No:\n");
    view = fopen(file, "rb");

    if (view == NULL)
        exit(1);

    while (fread(&add, sizeof(add), 1, view) != 0)
    {
        fprintf(output,"\t%16s", add.name);
        fprintf(output,"\t%15d", add.accno);
        fprintf(output,"\t%20.0f", add.phone);
        fprintf(output,"\n");
        test++;
    }
    fclose(view);
    fclose(output);

    if (test == 0)
    {
        printf("NO RECORDS FOUND!\n");
    }
    else{
        printf("Output updated in file output.txt\n");
    }
}

EDIT2:MCVE

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

void menu(void);
void accadd(void);
void modify(char file[30]); 
void view(char file[30]);

struct date
{
    int day;
    int month;
    int year;
};

struct customer
{
    char name[40], acctype[10];
    int accno, age;
    double phone;
    float amount;
    struct date deposit;
} add;

void accadd(void)
{
    FILE *fp = fopen("cus.dat", "ab+");

    if (fp == NULL)
        exit(1);

    printf("ADD RECORD\n");
    printf("Enter today's date(date/month/year) \n");
    if (scanf("%d/%d/%d", &add.deposit.day, &add.deposit.month, &add.deposit.year) != 3)
        exit(1);

    printf("Enter account number\n");
    if (scanf("%d", &add.accno) != 1)
        exit(1);

    printf("Enter customer's name\n");
    if (scanf("%s", add.name) != 1)
        exit(1);

    printf("Enter customer's age\n");
    if (scanf("%d", &add.age) != 1)
        exit(1);

    printf("Enter customer's phone num\n");
    if (scanf("%lf", &add.phone) != 1)
        exit(1);

    printf("Enter the account type(in words): \n\t 1:Current\n\t 2:Saving\n\t 3:Fixed\n");
    if (scanf("%s", add.acctype) != 1)
        exit(1);

    printf("Almost done! Just enter the amount you want to deposit: ");
    if (scanf("%f", &add.amount) != 1)
        exit(1);

    fwrite(&add, sizeof(add), 1, fp);
    fclose(fp);
}

void view(char file[30])
{
    FILE *view,*output;
    int test = 0;
    output=fopen("output.txt", "w");
    fprintf(output,"Customer's List\n");
    fprintf(output,"\tCustomer's Name:");
    fprintf(output,"\tAccount Number:");
    fprintf(output,"\tCustomer's Phone No:\n");
    view = fopen(file, "rb");

    if (view == NULL)
        exit(1);

    while (fread(&add, sizeof(add), 1, view) != 0)
    {
        fprintf(output,"\t%16s", add.name);
        fprintf(output,"\t%15d", add.accno);
        fprintf(output,"\t%20.0f", add.phone);
        fprintf(output,"\n");
        test++;
    }
    fclose(view);
    fclose(output);

    if (test == 0)
    {
        printf("NO RECORDS FOUND!\n");
    }
    else{
        printf("Output updated in file output.txt\n");
    }
}

void modify(char file[30]){
    FILE *view;
    int counter = 0;

    view = fopen(file, "rb+");

    if (view == NULL)
        exit(1);

    while (fread(&add, sizeof(add), 1, view) != 0)
    {
        if(add.phone==777777777){
            printf("Old phone is: %lf\n",add.phone);
            printf("New phone:\n");
            scanf("%lf", &add.phone);
            printf("New phone is: %lf\n",add.phone);
            fseek(view,sizeof(add)*counter,SEEK_SET);
            fwrite(&add,sizeof(add),1,view);
        }
            counter++;
    }
    fclose(view);

    if (counter == 0)
    {
        printf("NO RECORDS FOUND!\n");

    }
    else{
        printf("add.phone printed: %i\n",counter);
        printf("add length %d\n",sizeof(add));
    }
}


void menu(void)
{
    int n,account_number;
    char file[30],account_name[30];
    printf("Enter your choice 1, 2, 3\n");

    while(1){

        if (scanf("%d", &n) != 1)
            exit(1);

        switch (n){
        case 1:
            accadd();
            break;
        case 2:
            printf("Enter the file\n");
            scanf("%s",&account_name);
            view(account_name);
            break;
        case 3:
            modify("cus.dat");
            break;
        }
        printf("Enter your choice 1, 2, 3\n");
    }
}

int main(void)
{
    menu();
    return 0;
}

2 个答案:

答案 0 :(得分:1)

经过一些更多的变量打印之后,我设法假设在fwrite之后我陷入了写作模式,所以我使用了

fseek(f,0,SEEK_SET); 

返回阅读模式。我不知道这个解释是否准确,但它解决了我的问题。

我还将我的修改功能简化为更清晰。

void modify(char file[30]){
    FILE *view;
    int counter = 0;

    view = fopen(file, "rb+");

    if (view == NULL)
        exit(1);

    while (fread(&add, sizeof(add), 1, view) != 0)
    {

        if(add.phone==777777777){
            add.phone=145;
            fseek(view,sizeof(add)*counter,SEEK_SET);
            fwrite(&add,sizeof(add),1,view);
            fseek(view,0,SEEK_SET);
        }
            counter++;
    }
    fclose(view);
}

我希望对任何想要修改二进制文件记录的人都有用。

答案 1 :(得分:0)

我最好的猜测是你的fread()方法在某种程度上行为不端。要调试它,您可能需要捕获返回值,以便在调试器中轻松检查。因此,请将view()函数更改为:

void view(char file[30])
{
    FILE *view,*output;
    size_t ret;
    int test = 0;

    /* ... */

    while ((ret = fread(&add, sizeof(add), 1, view)) != 0)
    {
        fprintf(output,"\t%16s", add.name);
        fprintf(output,"\t%15d", add.accno);
        fprintf(output,"\t%20.0f", add.phone);
        fprintf(output,"\n");
        test++;
    }
    fclose(view);
    fclose(output);

    /* ... */
}

在调试器中,在循环的第一行设置断点,并在每次迭代中检查ret变量。对于两个预期的迭代,ret的值应该是1,但是对于打印零的迭代,它是什么?

一种可能性是,它在某些情况下选择通过返回-1来表示错误(是的,那将被打破)。在这种情况下,您可以将条件从非零测试更改为测试fread()在读取1条记录时应具有的实际返回值。