【问题标题】:How can I dynamically fill an array of pointers to structs that I have made?如何动态填充指向我已创建的结构的指针数组?
【发布时间】:2016-12-05 02:27:00
【问题描述】:

首先,一些背景知识,我正在为我的系统编程课程编写一个文件服务器。我要做的是编写4个客户端程序和一个服务器来编辑客户端文件的目录。我已经弄清楚如何在客户端实际传输文件,以及如何通过套接字实际获取它们,我很难将文件存储在服务器上。为了尝试解决这个问题,我创建了 2 个结构:

在内存中存储文件名和内容的 FileSlot 结构:

#ifndef __FILESLOT_H__
#define __FILESLOT_H__

#include "csapp.h"

typedef struct FILESLOT {
        char *filename;
        char *contents;
        uint32_t length;
} FileSlot;

#endif

还有一个 FileDrawer 结构,以便实际跟踪服务器上的文件,因为我必须能够添加、删除和列出它们:

#ifndef __FILEDRAWER_H__
#define __FILEDRAWER_H__

#include "csapp.h"
#include "fileslot.h"

typedef struct FILEDRAWER {
        FileSlot* files[100];
        uint32_t drawerSize;
} FileDrawer;

void new_fd(FileDrawer *fd);

uint32_t get_size(FileDrawer *fd);

void add_file(FileDrawer *fd, FileSlot *fs);

void rem_file(FileDrawer *fd, int index);

int search_files(FileDrawer *fd, char *name);

#endif

基本上我在服务器循环中使用这些结构,因为服务器接收到“放置”命令,我希望服务器创建一个 FileSlot,并将其粘贴到 FileDrawer 中。在过去的几天里,我浏览了论坛,到目前为止了解到我需要使用 malloc(),我对此有点模糊,但如果我学得正确,我可以创建一个指向 FileSlot 的指针用 malloc() 分配,用必要的信息填充它,然后将 FileDrawer 中的 files[] 元素之一指向新分配的 FileSlot:

#include "filedrawer.h"
#include "fileslot.h"

int main(int argc, char** argv) {
        FileDrawer *fdp = (FileDrawer*)malloc(sizeof(FileDrawer));
        new_fd(fdp);

        int i;
        while (i < 5) {
                uint32_t length = i;
                FileSlot* fsp = (FileSlot*)malloc(sizeof(FileSlot));
                fsp->filename = "file name";
                fsp->contents = "contents";
                fsp->length = length;
                add_file(fdp, fsp);
                i++;
        }
        for(i = 0; i < fdp->drawerSize; i++) {
                printf("File Name %s \n", fdp->files[i]->filename);
        }
        free(fdp);
        return 1;
}

但是这似乎不起作用,我从打印循环中得到了非常奇怪的输出。

另外:这是我的 FileDrawer 函数的实现,以防我在这里也输入了任何错误

void new_fd(FileDrawer* fdp) {
        FileDrawer fd;
        fd = *fdp;
        fd.drawerSize = 0;
        *fdp = fd;
}

uint32_t get_size(FileDrawer* fdp) {
        return fdp->drawerSize;
}    

void add_file(FileDrawer* fdp, FileSlot *fs) {
    FileDrawer fd = *fdp;
    fd.files[fd.drawerSize] = fs;
    fd.drawerSize++;
    *fdp = fd;
}

void rem_file(FileDrawer* fdp, int index) {
    FileDrawer fd;
    fd = *fdp;
    int i;
    for(i = index; i < fd.drawerSize; i++) {
            fd.files[i] = fd.files[i+1];
    }
    fd.drawerSize--;
    *fdp = fd;
}

int search_files(FileDrawer* fdp, char *name) {
    int i;
    int index = -1;
    for(i = 0; i < fdp->drawerSize; i++) {
            if ((fdp->files[i]->filename) == name) {
                        index = i;
                }
        }
        return index;
}

编辑:我进去修复了 malloc,并按照建议消除了效率低下的问题,非常感谢!现在,我的 fdtest 在第一个 strcpy 的 SEGFAULT 中退出,我不知道为什么。有什么想法吗?

【问题讨论】:

    标签: c arrays struct


    【解决方案1】:

    这是你的主要问题:

        int i;
        while (i < 5) {
    

    您在使用之前未能初始化i。因为它是未初始化的,它的值是不确定的,试图读取它会导致undefined behavior

    i初始化为0,它将正常运行。

        int i = 0;
        while (i < 5) {
    

    除此之外,您的代码还存在一些效率低下的问题。

    new_fdadd_file 中,您将取消引用的指针的内容复制到局部变量中,修改局部变量,然后将内容复制回来。那是不必要的工作。只需直接处理传入的指针即可。

    void new_fd(FileDrawer* fdp) {
            fdp->drawerSize = 0;
    }
    
    void add_file(FileDrawer* fdp, FileSlot *fs) {
        fdp->files[fdp->drawerSize] = fs;
        fdp->drawerSize++;
    }
    

    您可以在rem_file 中执行类似的更改。

    另外,don't cast the return value of malloc,因为它可以隐藏细微的错误。

    【讨论】:

    • 谢谢!听起来不错,我修复了 malloc 语句。我必须释放()我分配的每个 FileSlot 吗?还是最后的 free(fdp) 语句也会处理这些??
    • @AustinWilliams 每次调用malloc 都必须有对应的调用free。因此,您需要遍历files 列表并在每个列表上调用free。在你之前这样做 free fdp 包含它们。
    猜你喜欢
    • 2018-11-03
    • 1970-01-01
    • 1970-01-01
    • 2021-10-22
    • 1970-01-01
    • 1970-01-01
    • 2012-04-22
    • 2012-07-16
    • 1970-01-01
    相关资源
    最近更新 更多