简体   繁体   English

C指针,结构和fwrite

[英]C pointer, struct and fwrite

I'm currently trying to write and read a simple linked list into a file, but it doesn't really seem to work and I'm not sure if it is even possible. 我目前正在尝试编写一个简单的链接列表并将其读入一个文件,但它似乎并没有真正起作用,我不确定它是否可行。

typedef struct flug
{
    int            flugnummer;
    char            flugziel[50];
    enum TAG        flugtag;
    int            flugzeit_stunde;
    int            flugzeit_minute;
    int            gateway;
    char            status[10];
    struct flug    *next;
}FLUG;

typedef FLUG *ELEM_ZGR;

I fear the problem might be that I'm not only writing chars, but int .. and especially enums, too. 我担心问题可能是我不仅要写字符,而且还要写int ...尤其是enums。

int fluege_sichern() {
ELEM_ZGR curr;

FILE *fp;
char* tag;

curr = first;

if (fopen_s(&fp, datei,"a+b") != 0) {
    printf("\nDatei %s nicht zum Anhaengen zu oeffnen",datei);
    PAUSE;
    exit(1);
}

for(curr = first; curr != NULL; curr = curr->next) {
    fwrite(curr, sizeof(FLUG), 1, fp);
}

    fclose(fp);
    return 1;
}

This is supposed to be the function to write the elements into a file as binaries. 这应该是将元素作为二进制文件写入文件的功能。 I don't get any errors in this function. 我在这个函数中没有任何错误。

void fluege_laden() {
ELEM_ZGR curr;
FILE *fp;
int i = 0;

if (fopen_s(&fp, datei,"rb") != 0) {
    printf("\nDatei %s nicht zum Lesen zu oeffnen",datei);
    PAUSE;
    exit(1);
}

while(1) {
     fread(&curr, sizeof(FLUG), 1, fp);
     printf("\n%d", curr->flugnummer);
     //fluege_sortieren(curr);
}
}

I get the error when I try to print out curr->flugnummer. 尝试打印curr-> flugnummer时出现错误。

Ok so I changed the two functions a little, but it still doesn't seem to work. 好的,所以我稍微改变了两个功能,但它似乎仍然没有用。 I'm sorry, I don't seem to get it... 对不起,我似乎没有得到...

[EDIT2] Another version that doesn't work: [EDIT2]另一个不起作用的版本:

void fluege_laden() {
    ELEM_ZGR curr;  // <<<- allocate an actual struct here rather than just a pointer
    FILE *fp;

    int i = 0;
    curr = first;

    if (fopen_s(&fp, datei,"rb") != 0) {
        printf("\nDatei %s nicht zum Lesen zu oeffnen",datei);
        PAUSE;
        exit(1);
    }

    while(1) {
        fread(curr, sizeof(FLUG), 1, fp);
        printf("\n%d", curr->flugnummer);   // <<<
        printf("\n%s", curr->flugziel);
        //fluege_sortieren(curr);
        PAUSE;
    }

}

int fluege_sichern() {
ELEM_ZGR curr;
FILE *fp;

curr = first;

if (fopen_s(&fp, datei,"a+b") != 0) {
    printf("\nDatei %s nicht zum Anhaengen zu oeffnen",datei);
    PAUSE;
    exit(1);
}

for(curr = first; curr != NULL; curr = curr->next) {
    fwrite(curr, sizeof(FLUG), 1, fp);
}

    fclose(fp);
    return 1;
}

curr is an uninitialised pointer (a FLUG* ) and is therefore not pointing to valid memory when fread() is called. curr是一个未初始化的指针( FLUG* ),因此在调用fread()时不指向有效的内存。 Writing to invalid memory is undefined behaviour (the program could seg fault or execute incorrectly or worst case execute correctly). 写入无效内存是未定义的行为(程序可能会出错或执行错误或最坏情况下正确执行)。 Either create a stack allocated object (of type FLUG ) or dynamically allocate memory for curr . 创建堆栈分配对象( FLUG类型)或为curr动态分配内存。

Personally, I find it very confusing when a pointer is typedef d as at the point of use it is not obvious that the variable is a pointer: 就个人而言,当指针是typedef d时,我发现它非常令人困惑,因为在使用时,变量是一个指针并不明显:

ELEM_ZGR curr;

The following is unambiguous: 以下内容是明确的:

FLUG* curr; /* Or just 'FLUG curr;' for this case. */

Check the result of fread() to ensure the program is not operating on stale data: 检查fread()的结果以确保程序不在陈旧数据上运行:

FLUG curr;
while (1 == fread((&curr, sizeof(FLUG), 1, fp))
{
    printf("\n%d", curr.flugnummer);
}

(In response to the question edit) (回答问题编辑)

In short, change: 简而言之,改变:

fwrite(curr, sizeof(FLUG*), 1, fp);
fread(&curr, sizeof(FLUG*), 1, fp);

to: 至:

fwrite(curr, sizeof(FLUG), 1, fp);
fread(curr, sizeof(FLUG), 1, fp);

In both cases, curr is a FLUG* and is pointing to valid memory for storing a FLUG so you need to read the sizeof(FLUG) , not the sizeof(FLUG*) . 在这两种情况下, curr都是FLUG*并且指向用于存储FLUG有效内存,因此您需要读取sizeof(FLUG) ,而不是sizeof(FLUG*) The typical size for a pointer of any type is 4 or 8 bytes. 任何类型指针的典型大小为4或8个字节。 On my x86 box it is 4 bytes and the size of a FLUG is 88 bytes. 在我的x86盒子上它是4个字节, FLUG的大小是88个字节。 The size argument to both fwrite() and fread() instructs the number of bytes to read and write: fwrite()fread()size参数指示要读取和写入的字节数:

fwrite(curr, sizeof(FLUG), 1, fp); /* write 88 bytes to fp from address curr. */
fread(curr, sizeof(FLUG), 1, fp); /* read 88 bytes from fp and write to the
                                     address beginning at curr. */

Passing the address of &curr to fread() means a FLUG** is being passed to fread() which is incorrect. &curr的地址传递给fread()意味着将FLUG**传递给fread() ,这是不正确的。

In the read routine ELEM_ZGR curr; 在读取例程ELEM_ZGR curr; is just an uninitialised pointer. 只是一个未初始化的指针。 You need to do something like this: 你需要做这样的事情:

void fluege_laden() {
    FLUG curr;  // <<<- allocate an actual struct here rather than just a pointer
    FILE *fp;
    int i = 0;

    if (fopen_s(&fp, datei,"rb") != 0) {
        printf("\nDatei %s nicht zum Lesen zu oeffnen",datei);
        PAUSE;
        exit(1);
    }

    while(1) {
        fread(&curr, sizeof(FLUG), 1, fp); // <<<
        printf("\n%d", curr.flugnummer);   // <<<
        //fluege_sortieren(curr);
    }
}

Also, in the write routine you need to write the whole struct, eg 此外,在write例程中,您需要编写整个结构,例如

int fluege_sichern() {
    ELEM_ZGR curr;
    FILE *fp;
    char* tag;

    curr = first;

    if (fopen_s(&fp, datei,"a+b") != 0) {
        printf("\nDatei %s nicht zum Anhaengen zu oeffnen",datei);
        PAUSE;
        exit(1);
    }

    for(curr = first; curr != NULL; curr = curr->next) {
        fwrite(curr, sizeof(FLUG), 1, fp); // <<<- curr is already a pointer - do not dereference here !
    }

    fclose(fp);
    return 1;
}

Whoa! 哇! Think what memory you're reading into there. 想想你正在读什么内存。 Your fread is asking for data to get dumped in some random location (because curr is uninitialised, so points to memory that probably doesn't exist in your process). 您的fread是要求将数据转储到某个随机位置(因为curr未初始化,因此指向您的进程中可能不存在的内存)。 You need to allocate some FLUGs and read into them. 您需要分配一些FLUG并读入它们。

Another problem is that you shouldn't be writing pointers to file; 另一个问题是你不应该写文件指针; the data only has meaning within your process. 数据仅在您的流程中具有意义。 When you read back the FLUGs, at the very least, you should set cur->next to something sensible (like the next FLUG!). 至少读回FLUG时,应该将cur-> next设置为明智的设置(例如下一个FLUG!)。

You are writing pointers to a file, called a shallow copy . 您正在编写指向文件的指针,称为浅拷贝 Pointers are not transferable, you need to write code to do a deep copy . 指针不可转移,您需要编写代码来进行深层复制 Either that, or use something like JSON or YAML. 要么是这样,要么使用像JSON或YAML这样的东西。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM