简体   繁体   English

如何在此处打印结构的名称变量?

[英]How can I print the name variable of my struct here?

I have an ArrayList struct and Department struct that go as follows:我有一个 ArrayList 结构和 Department 结构,如下所示:

typedef struct ArrayList {
   void** elements;
   int size;
   int length;
} ArrayList;

typedef struct Department {
   char* name;
   ArrayList* courses;
} Department;

To print my list, I'm using these two methods:要打印我的列表,我使用这两种方法:

void* get(ArrayList* arraylist, int i) {
    if (i < 0 || i >= arraylist -> size) {
        return (void*) NULL;
    }
    return arraylist -> elements[i];
}

void printAL(ArrayList* arraylist) {
    for (int i = 0; i < arraylist -> size; i++) {
        printf("%s\n", (char*) get(arraylist, i));
    }
}

The issue I'm facing, however, is that when I add a Department to my ArrayList, the line 'return arraylist -> elements[i];'然而,我面临的问题是,当我将部门添加到我的 ArrayList 时,“return arraylist -> elements[i];”行returns the address of that struct.返回该结构的地址。 I'm trying to get it to print the name of the struct using 'return arraylist -> elements[i] -> name' but I keep getting a warning that I'm dereferencing a void* pointer, followed by an error that says 'request for member 'name' in something not a structure'.我试图让它使用“return arraylist -> elements[i] -> name”打印结构的名称,但我不断收到警告,说我正在取消引用 void* 指针,然后出现一个错误'在不是结构的东西中请求成员'姓名''。 This obviously means that 'arraylist -> elements[i]' isn't a struct but rather an address.这显然意味着 'arraylist -> elements[i]' 不是结构而是地址。 How can I reference the name of the struct at that address then?那么如何在该地址引用结构的名称? I'm quite confused because of the double pointer in the ArrayList struct.由于 ArrayList 结构中的双指针,我很困惑。

TIA!蒂亚!

You need different printing functions for each different type of data element that could be in the ArrayList .对于可能位于ArrayList中的每种不同类型的数据元素,您需要不同的打印功能。 You need one function to print departments;您需要一项功能来打印部门; you need a different function to print courses.您需要不同的功能来打印课程。 You pass the function pointer to the printing function — printAL() — along with a pointer to other data (which in this case is probably just a FILE * , but could be a more general structure).您将函数指针传递给打印函数 — printAL() — 以及指向其他数据的指针(在这种情况下,它可能只是一个FILE * ,但可能是一个更通用的结构)。

This is analogous to the qsort() function in standard C. It can sort any data type;这类似于标准 C 中的qsort()函数。它可以对任何数据类型进行排序; you just need to pass it a different comparator function for different data types.你只需要为不同的数据类型传递一个不同的比较器函数。

Like this:像这样:

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

typedef struct ArrayList
{
    void **elements;
    int size;           /* Allocated size */
    int length;         /* Space in use */
} ArrayList;

typedef struct Department
{
    char *name;
    ArrayList *courses;
} Department;

static void *get(ArrayList *arraylist, int i)
{
    if (i < 0 || i >= arraylist->size)
        return NULL;
    return arraylist->elements[i];
}

static void printAL(ArrayList *arraylist, void (*function)(const void *data, void *thunk), void *thunk)
{
    for (int i = 0; i < arraylist->length; i++)
    {
        (*function)(get(arraylist, i), thunk);
    }
}

static void put(ArrayList *al, void *data)
{
    if (al->length >= al->size)
    {
        size_t new_size = (al->size + 2) * 2;
        void  *new_data = realloc(al->elements, new_size * sizeof(void *));
        if (new_data == 0)
        {
            fprintf(stderr, "Failed to allocate %zu bytes memory\n", new_size * sizeof(void *));
            exit(1);
        }
        al->elements = new_data;
        al->size = new_size;
    }
    al->elements[al->length++] = data;
}

/*
typedef struct Course
{
    const char *name;
    const char *code;
    // ...
} Course;

static void print_courseinfo(const void *data, void *thunk)
{
    FILE *fp = thunk;
    const Course *cp = data;
    fprintf(fp, " - %s (%s)\n", cp->name, cp->code);
}
*/

static void print_deptname(const void *data, void *thunk)
{
    FILE *fp = thunk;
    const Department *dp = data;
    fprintf(fp, "Name: %s\n", dp->name);
    /*
    if (dp->courses != 0)
        printAL(dp->courses, print_courseinfo, thunk);
    */
}

int main(void)
{
    ArrayList al = { 0, 0, 0 };
    Department dl[] =
    {
        { "Engineering", 0 },
        { "Physics", 0 },
        { "Mathematics", 0 },
        { "Chemistry", 0 },
        { "Biology", 0 },
        { "English", 0 },
        { "Computational Astronomy and Universe-Scale Data Modelling", 0 },
        { "Economics", 0 },
    };
    enum { DL_SIZE = sizeof(dl) / sizeof(dl[0]) };
    for (size_t i = 0; i < DL_SIZE; i++)
        put(&al, &dl[i]);
    printAL(&al, print_deptname, stdout);
    return 0;
}

Sample output:示例输出:

Name: Engineering
Name: Physics
Name: Mathematics
Name: Chemistry
Name: Biology
Name: English
Name: Computational Astronomy and Universe-Scale Data Modelling
Name: Economics

You didn't document what the length and size members of the ArrayList represent.您没有记录ArrayListlengthsize成员代表什么。 I've annotated what I've assumed, but I had to change the printAL() function to iterate over length elements instead of size elements, so I may have inverted the meaning you intended.我已经注释了我假设的内容,但是我必须更改printAL()函数来迭代length元素而不是size元素,所以我可能颠倒了你想要的意思。 It's easy to reverse them.很容易逆转它们。 I tend to use names like max_elements and num_elements for the job;我倾向于使用max_elementsnum_elements类的名称作为作业; it is more obvious what they're for, perhaps, since length and size are ambiguous or even equivalent in many contexts.它们的用途更明显,也许,因为lengthsize在许多情况下是不明确的,甚至是等效的。

There's skeletal code in there to show how to handle the ArrayList of courses offered by each department.那里有骨架代码来展示如何处理每个部门提供的课程的ArrayList I couldn't be bothered to write code to initialize a separate ArrayList for each department, though it wouldn't be particularly hard to do.我懒得编写代码来为每个部门初始化一个单独的ArrayList ,尽管这不会特别难。

I still prefer the pre-standard notation (*funcptr)(arg1, arg2) notation for invoking a function designated by a function pointer — it was necessary when I learned C, and I still find it clearer than the alternative.我仍然更喜欢使用标准前的符号(*funcptr)(arg1, arg2)来调用由函数指针指定的函数——当我学习 C 时这是必要的,我仍然发现它比替代方法更清晰。 You're excused if you prefer funcptr(arg1, arg2) instead, though that can leave me wondering where funcptr is defined.如果您更喜欢funcptr(arg1, arg2) ,那您就可以原谅了,尽管这会让我想知道funcptr是在哪里定义的。

You can also find some code closely related to what you're doing in my SOQ (Stack Overflow Questions) repository on GitHub as files aomcopy.c , aomcopy.h , aommngd.c , aommngd.h , aomptr.c , aomptr.h , aoscopy.c , aoscopy.h , aosptr.c and aosptr.h in the src/libsoq sub-directory.您还可以在 GitHub 上的我的SOQ (堆栈溢出问题)存储库中找到一些与您正在做的事情密切相关的代码,作为文件aomcopy.caomcopy.haommngd.caommngd.haomptr.caomptr.h , aoscopy.c , aoscopy.h , aosptr.caosptr.hsrc/libsoq子目录中。

  • aomcopy.c , aomcopy.h : array of memory blocks, copied. aomcopy.c , aomcopy.h :复制的内存块数组。
  • aommngd.c , aommngd.h : array of memory blocks, managed. aommngd.c , aommngd.h :内存块数组,托管。
  • aomptr.c , aomptr.h : array of memory blocks, 'raw'. aomptr.c , aomptr.h :内存块数组,“原始”。
  • aoscopy.c , aoscopy.h : array of strings, copied. aoscopy.c , aoscopy.h :字符串数组,已复制。
  • aosptr.c . aosptr.c aosptr.h : array of strings, 'raw'. aosptr.h :字符串数组,“原始”。

The 'raw' versions simply take the pointer passed and store it. “原始”版本只是获取传递的指针并存储它。 The onus is on the user to ensure the data pointed at remains valid while the array lasts.用户有责任确保指向的数据在数组持续期间保持有效。 The 'copied' versions allocate a simple copy of the data passed to it; “复制”版本分配传递给它的数据的简单副本; it doesn't matter if the data passed is reused to store the next value.传递的数据是否被重用来存储下一个值并不重要。 The 'managed' version calls user-defined functions to create copies of the data structures. “托管”版本调用用户定义的函数来创建数据结构的副本。 This would be necessary if you have a complex structure (like a department) where you need a 'deep copy' of the data.如果您有一个复杂的结构(如部门),您需要数据的“深层副本”,那么这将是必要的。

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

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