3

所以我有一个 input.bin 文件,其中包含以下内容

IK-SZH;jdl72u;John Doe;2013-03-28 11:05
IK-GRR;kat91n;Jane Doe;2013-03-21 15:41
IK-GRR;oat62f;Jane Doe;2013-03-24 08:08

我正在做的是将它读入一个结构。用数据做一些事情。添加/删除行。然后我想以与上面相同的格式将结构的内容写回 input.bin 文件。

但不是像上面那样出现。是这样的(没有空格):

IK-SZH NUL jdl72u NUL John Doe NUL NUL NUL NUL NUL 2013-03-28 NUL NUL NUL IK-GRR NUL kat91n NUL Jane Doe NUL NUL NUL NUL ...

当我重新读取文件(使用 NUL)时,它只将第一行放入结构中

我的代码

typedef struct foo {
    char kid[7];    
    char jid[7];    
    char name[21];  
    char time[20];  

} Foo;

Foo foo[200];
FILE* fp;
int size;

-------- 文件阅读器

void read(char* filename){
    fp = fopen(filename, "rb"); 
    int i = 0;

    while (!feof(fp)) {

        if (fp==NULL){perror("File opening error\n"); exit(1);}

        fscanf(fp,"%[^;]; %[^;]; %20[^\;]; %s\n", foo[i].kid, foo[i].jid,
                foo[i].name, foo[i].time);
        i++;
    }

    size = i;

    print();

    fclose(fp);
}


void print(){
    int i;
    for (i = 0; i < size; ++i){
        printf("%s\t %s\t %s\t %s\n", foo[i].kid, foo[i].jid,
               foo[i].name, foo[i].time);
    }
}

----- 作家

void write(){
    char str[1000];

    FILE* f = fopen("input.bin", "wb");
    fseek(f, 0, SEEK_SET);
    int i;
    for (i = 0; i < jel_size; i++)
            fwrite(&foo[i], sizeof(struct foo), 1, f);
    fclose(f);

}

试过这个,但这并没有向文件写入任何内容:

    char str[1000];
    sprintf(str,"%s;%s;%s;%s\n", jelent[i].kazon,
                    jelent[i].jazon,jelent[i].nev,  jelent[i].ido );

        write(f,&str,sizeof(str))!=sizeof(str);
4

2 回答 2

5

您的结构定义是:

typedef struct foo
{
    char kid[7];    
    char jid[7];    
    char name[21];  
    char time[20];  
} Foo;

将结构写入文件的代码位于write()

for (i = 0; i < jel_size; i++)
    fwrite(&foo[i], sizeof(struct foo), 1, f);

如果将结构初始化为所有字节为零,那么对于您提到的第一行数据:

IK-SZH;jdl72u;John Doe;2013-03-28 11:05

我们可以推断该结构包含:

IK-SZH\0
jdl72u\0
John Doe\0\0\0\0\0\0\0\0\0\0\0\0\0
2013-03-28 11:05\0\0\0\0

这或多或少与您所说的文件包含的内容一致:

IK-SZH NUL jdl72u NUL John Doe NUL NUL NUL NUL NUL 2013-03-28 NUL NUL NUL 

据我估计,您在名称和时间之后缺少几个 NUL,在日期之后缺少一个 NUL。

如果您想要文本输出,则必须write()使用fprintf()类似于函数fscanf()中的语句来格式化数据。read()您可能应该从函数返回一个状态以指示它是否成功。您也可以为检查fclose()是否成功而争论。

void write(void)
{
    FILE *fp = fopen("input.bin", "w");
    if (fp != 0)
    {
        for (int i = 0; i < jel_size; i++)
            fprintf(fp, "%s;%s;%s;%s\n", foo[i].kid, foo[i].jid, foo[i].name, foo[i].time);
        fclose(fp);
    }
}

如果你想要二进制输出,你应该在read(). 同样,您应该考虑返回成功或失败的指示;避免全局变量也很好。

void read(const char *filename)
{
    FILE *fp = fopen(filename, "rb"); 
    if (fp != 0)
    {
        for (i = 0; fread(&foo[i], sizeof(foo[i]), 1, fp) == 1; i++)
            ;
        fclose(fp);
        size = i;
    }
}

任何一种技术都行得通;试图将一个用于输出而另一个用于输入将导致混乱和混乱。

请注意,POSIX 使用的函数read()write()具有不同的接口。虽然您坚持使用标准 C,但这些名称对您来说是公平的,但您可能最好使用替代名称,例如reader()andwriter()foo_read()and foo_write()

于 2013-04-02T01:11:15.120 回答
2

https://gist.github.com/anonymous/5288805

稍微更改了代码,进行了注释,并进行了测试,因此可以肯定地工作。

于 2013-04-01T23:56:50.150 回答