【问题标题】:How to get the pointer of a struct inside a file如何获取文件内结构的指针
【发布时间】:2021-02-20 19:11:38
【问题描述】:

我想在文件中添加轮渡作为节点并跟踪前一个和下一个指针,目的是创建一个循环双向链表。船名作为主函数的参数写入终端。

添加渡轮函数代码:

int Register_ferry(char *f){
FILE *pFile;
pFile = fopen("Ferries.txt","a+");
if(pFile!=0){
    FILE *dFile;
    dFile = fopen("Ferries.txt","r+");
    ferry *new_node=(ferry*)malloc(sizeof(ferry));
    ferry *new_node2=(ferry*)malloc(sizeof(ferry));
    fseek(pFile,0,SEEK_END);
    if(ftell(pFile)==0){
        new_node->fld=atoi(f);
            new_node->next=new_node;
        new_node->prev=new_node;
        printf("CURR: %p\n",new_node);
        printf("NEXT: %p\n",new_node->next);
        printf("PREV: %p\n",new_node->prev);
    }
    else if(ftell(pFile)==8){
        new_node->fld=atoi(f);
        fseek(dFile,0,SEEK_SET);
        fread(new_node2,sizeof(new_node2),1,dFile);
        new_node->next=new_node2;
        new_node->prev=new_node2;
        new_node2->next=new_node;
        new_node2->prev=new_node;
        fwrite(new_node2, sizeof(new_node),1,dFile);
            printf("CURR: %p\n",new_node);
        printf("NEXT: %p\n",new_node->next);
        printf("PREV: %p\n",new_node->prev);    
    }
    else{   
        new_node->fld=atoi(f);
        fseek(dFile,-8,SEEK_END);
        fread(new_node2,sizeof(new_node2),1,dFile);
            new_node->prev=new_node2;
        fseek(dFile,0,SEEK_SET);
        fread(new_node2,sizeof(new_node2),1,dFile);
        new_node->next=new_node2;
        printf("CURR: %p\n",new_node);
        printf("NEXT: %p\n",new_node->next);
        printf("PREV: %p\n",new_node->prev);    
    }
    fwrite(new_node, sizeof(new_node), 1, pFile);
    fclose(pFile);
    free(new_node);
    free(new_node2);
}
return 0;} 

main的代码:

 int main(int narg , char* argv[]){
 if (strcmp(argv[1], "R")==0)
 {  
    Register_ferry(argv[2]);
     }
 return 0;} 

渡轮的结构:

typedef struct ferry{
int fld;
struct ferry *next;
struct ferry *prev;
}ferry;

调用程序的照片:

经过一些尝试,我意识到使用 printf 命令我不会获得文件内节点的指针,而是我使用函数 malloc 创建的节点的指针。所以我的问题是我应该如何获取文件内节点的指针以保持循环双向链表应有的状态?

最后,由于某种原因,我的函数和第一个 if 没有以它们对应的 '}' 结束,但由于某种原因仍然很重要。但是终端没有提示任何错误,所以有点奇怪。

【问题讨论】:

标签: c file ubuntu pointers struct


【解决方案1】:

完整示例:

  • 内存中的循环链表,文件中的平面链表
  • 只有一个结构来定义数据和链接(指针)
  • 只有一个文件(不需要标题或额外文件)
  • 不读写指针,只读写数据
  • 在读取期间计算指针
  • 为每个节点分配内存
  • 释放所有声明的内存
  • 添加程序参数以读取所有渡轮并退出
  • 添加的程序参数也允许保存名称
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct ferry {
    int fld;
    char name[20];
    struct ferry *next;
    struct ferry *prev;
}ferry;

/* Full size used for malloc, without pointers for read/write */
#define FERRY_SIZE (sizeof(ferry))
#define FERRY_SIZE_WITHOUT_POINTERS (FERRY_SIZE - (sizeof(ferry*)*2))

#define FILE_DATA "Ferries.txt"

int write_ferries(ferry*first_node) {
    FILE *data_file;
    int count = 0;

    /* We will modify the pointer to loop over the linked list */
    ferry*node = first_node;

    data_file = fopen(FILE_DATA,"w");
    do {
        count++;
        fwrite(node, FERRY_SIZE_WITHOUT_POINTERS,1,data_file);
        node = node->next;
    } while(node != first_node);

    fclose(data_file);

    return count;
}

ferry* read_ferries() {
    FILE *data_file;
    int data_size;
    int num_nodes;
    ferry*first_node = NULL, *prev_node = NULL;
    int i;

    /* Get file size */
    /* If file does not exists or its size is zero, return NULL */
    data_file = fopen(FILE_DATA,"r+");
    if(data_file == NULL) {
        return NULL;
    }

    fseek(data_file,0,SEEK_END);
    data_size = ftell(data_file);

    if(data_size == 0) {
        fclose(data_file);
        return NULL;
    }

    /* Calculate num of nodes using file size and struct size */
    num_nodes = data_size / FERRY_SIZE_WITHOUT_POINTERS;
    fseek(data_file,0,SEEK_SET);

    /* Read all ferries and assign prev/next following file order */
    for(i = 0; i < num_nodes; i++) {
        ferry *node = malloc(FERRY_SIZE);
        fread(node,FERRY_SIZE_WITHOUT_POINTERS,1,data_file);

        if(first_node == NULL) {
            first_node = node;
        }

        /* Assign prev/next using order in file */
        if(i > 0) {
            node->prev = prev_node;
            prev_node->next = node;
        }

        prev_node = node;
    }

    fclose(data_file);

    /* Link first and last nodes */
    prev_node->next = first_node;
    first_node->prev = prev_node;

    return first_node;
}

int free_all_nodes(ferry*first_node) {
    ferry*last_node = first_node->prev;
    ferry*node = first_node;

    do {
        node = node->next;
        free(node->prev);
    } while(node != last_node);
}

int Register_ferry(char *fld, char *name){
    /* Generate the new node */
    ferry *new_node = malloc(FERRY_SIZE);
    new_node->fld = atoi(fld);
    if(name != NULL && strlen(name) > 0) {
        strcpy(new_node->name, name);
    }

    /* Read all ferries, get the first */
    ferry*first_node = read_ferries();

    if(first_node == NULL) {
        /* If this is the first node */
        new_node->prev = new_node;
        new_node->next = new_node;
        write_ferries(new_node);

        printf("CURR: %p\n",new_node);
        printf("NEXT: %p\n",new_node->next);
        printf("PREV: %p\n",new_node->prev);

        /* Free single node memory */
        free(new_node);
    }
    else {
        printf("first_node CURR: %p\n",first_node);
        printf("first_node NEXT:%p\n",first_node->next);
        printf("first_node PREV:%p\n",first_node->prev);

        /* Link the new node */
        new_node->prev = first_node->prev;
        new_node->next = first_node;
 
        /* Update the first node to point its prev to the new one */
        first_node->prev = new_node;
 
        /* Update the last node to point its next to the new one */
        new_node->prev->next = new_node;

        /* Save the entire list */
        write_ferries(first_node);

        printf("CURR: %p\n",new_node);
        printf("NEXT: %p\n",new_node->next);
        printf("PREV: %p\n",new_node->prev);

        /* Free all allocated memory for nodes */
        free_all_nodes(first_node);
    }

    return 0;
}

int show_ferries(void) {
    ferry*first_node = read_ferries();
    ferry*node = first_node;
    int count = 0;

    if(first_node == NULL) {
        printf("No ferries yet.\n");
        return 0;
    }

    do {
        count++;
        printf("Ferry %d: %d - %s\n", count, node->fld, node->name);
        node = node->next;
    } while(node != first_node);

    free_all_nodes(first_node);

    return count;
}

int main(int argc, char*argv[]) {
    if (strcmp(argv[1], "R") == 0) {  
        Register_ferry(argv[2], argv[3]);
    }
    if (strcmp(argv[1], "L") == 0) {  
        show_ferries();
    }

    return 0;
}

【讨论】:

  • 我真的找不到话来感谢您从头开始编写代码以帮助互联网上的一个随机人。我真的很沮丧,因为我被困在这一点上好几天了,但是在看到你的工作后,我振作起来继续练习。再次非常感谢您的帮助!
  • 不客气 ;) 我希望它有助于更​​好地理解 C 和编程,并鼓励你继续走这条路。
【解决方案2】:

我认为将您的渡轮数据包装到一个链表结构中会更好。然后,您可以将所有渡轮保存在一个平面文件中,并将它们链接到另一个文件中,而无需将二进制指针保存到该文件中。

typedef struct {
    int fld;
    char name[20];
    /* Some other fields */
} ferry;

// From https://stackoverflow.com/a/18582440/2928168 :
typedef struct list {
    struct ferry *node;
    struct list *prev;
    struct list *next;
} list;

然后,您可以使用freadfwrite 通过循环列表将轮渡数据加载并保存到文件中。有关订单的数据需要使用其他技术保存在不同的文件中,或者作为第一个文件的标题。例如,为每个节点保存三个整数,指向 3 个节点的 index:当前、上一个和下一个。

【讨论】:

  • 问题是我需要有 int fld(又名船的名称)、next 和 prev 指针在同一个结构中,称为 ferry(我忘了写在帖子上,只是添加它)。
  • 保存到文件中的指针是没有意义的,所以不能直接使用fread/fwriteThe thing is I need to have the int fld(aka the name of the ship), the next and the prev pointers in the same struct called ferry 为什么?
  • 因为这就是练习的内容,但我想我可以稍微修改一下。你有什么视频可以说明你的建议吗?
  • Because that's what the exercise reads 然后,它迫使您不要使用 fread/fwtite 将二进制数据读入结构,或者使用需要“翻译”的中间结构" 变成最终的 ferry 形状。
  • 添加了完整工作示例的新答案。
猜你喜欢
  • 1970-01-01
  • 2012-09-07
  • 2011-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-17
相关资源
最近更新 更多