【问题标题】:How to iterate through a structs array which has null items?如何遍历具有空项的结构数组?
【发布时间】:2014-11-09 04:20:17
【问题描述】:

我有一个大小为 10 的结构数组,其中只分配了几个项目,我如何知道我正在迭代的项目是否为 NULL?

struct child
{
    char *father;
    char *mother;
};

struct child cont[10];
int i = 0;

memset(cont, 0, sizeof cont);

for (i = 0; i < 10; i++)
{
    if (cont[i] == NULL) break; // Error
    else //do something....
}

以上代码抛出错误:used struct type value where scalar is required!

【问题讨论】:

  • cont[i] 不是指针,因此不能是 NULL...
  • 所以我应该改用&amp;cont[i] 吗?
  • 结构数组不能有 NULL 项。没有 NULL 结构。
  • 您需要一些其他机制来判断数组位置是否正在使用中。就像一个名为 int in_use; 的成员,当您分配给它时您设置为 1,当您不再使用它时设置为 0。这个问题之前已经被问过很多次了。这里有一个类似的:stackoverflow.com/questions/22736057/…
  • 使用struct child cont[10] = { 0 }; 将指针初始化为空指针(memset 可能不会这样做)

标签: c arrays struct


【解决方案1】:

如 cmets 中所述,初始化指向 NULL 的指针允许您按照您的尝试测试值。下面是一个使用while 循环来测试father &amp; mother 字符串值的示例:

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

struct child
{
    char *father;
    char *mother;
};

int main () {

    struct child cont[10] = {{0}};
    int i = 0;

    memset(cont, 0, sizeof cont);

    cont[0].father = strdup ("Mark");
    cont[0].mother = strdup ("Lisa");

    cont[1].father = strdup ("Tom");
    cont[1].mother = strdup ("Fran");

    while (cont[i].father && cont[i].mother)
    {
        printf ("cont[%d]\n  father: %s\n  mother: %s\n\n", 
                i, cont[i].father, cont[i].mother);
        i++;
    }

    /* free memory allocated by strdup here */

    return 0;
}

输出:

$ ./bin/structptr

cont[0]
  father: Mark
  mother: Lisa

cont[1]
  father: Tom
  mother: Fran

指向结构的指针数组

是的,您可以创建一个指向 struct 的指针数组,然后根据需要分配内存。这允许您测试if (cont[i])。本质上你在做同样的事情,但在第一种情况下,你声明了 10 个结构。在这种情况下,你永远不能只测试cont[i],因为它不是一个指针(更不用说它总是有一个地址,无论字符串是否填充)。

在这种情况下,您创建了 10 个指向所有设置为 NULL 的结构的指针(通过使用 calloc 而不是 malloc 来初始化它们)。当您实际使用 10 中的一个时,您为结构分配内存,给它一个在它之前为 NULL 的地址。这使您可以遍历 10 个指针以找出正在使用的指针。这是一种非常灵活的技术,可以应用于大量不同的数据结构。我希望它有所帮助。这是一个示例(相同的输出):

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

#define MAXS 10

struct child
{
    char *father;
    char *mother;
};

int main () {

    /* create MAXS (10) pointers to child set to NULL */
    struct child **cont = calloc (MAXS, sizeof(struct child*));
    int i = 0;

    cont[0] = malloc (sizeof(struct child));  /* allocate as needed */
    cont[0]-> father = strdup ("Mark");
    cont[0]-> mother = strdup ("Lisa");

    cont[1] = malloc (sizeof(struct child));  /* allocate as needed */
    cont[1]-> father = strdup ("Tom");
    cont[1]-> mother = strdup ("Fran");

    while (cont[i])     /* now simply test if pointer is not NULL   */
    {
        /* you can check father/mother individually if desired
           here we simply rely on printf outputting (null) if
           either father or mother does not point to a string */

        printf ("\ncont[%d]\n  father: %s\n  mother: %s\n", 
                i, cont[i]-> father, cont[i]-> mother);
        i++;
    }

    /* free memory allocated to cont & by strdup here */

    return 0;
}

【讨论】:

  • 感谢详细的回答,我仍然是 c 的菜鸟,但我觉得这样做是多余的。还有其他方法可以让我使用指针并执行if (cont[i] != NULL)if (ptr != NULL) 之类的操作吗?
  • 当然,看看我的第二个例子。 注意:使用calloc来初始化指向NULL的指针。
  • 一个菜鸟问题,为什么cont[i] 周围有大括号,它不是指向子结构的指针吗?我可以不只是做cont[i]-&gt;father吗?
  • 既然是指针,不做任何解引用,实在没必要​​。在其他情况下,您将使用括号( ) 来防止运算符优先级导致问题。只需在此处删除它们。
  • 很高兴我能帮上忙。将此技巧保存在您的 C 工具箱中。你最终会一遍又一遍地使用它。
【解决方案2】:

在您的代码中,cont 不是指针,因此针对 NULL 进行检查是不对的。 正如您可能知道的那样,一旦您在代码中创建了一个数组,您就已经为您的结构变量分配了内存,即使您可能会或可能不会使用它。 所以你的问题是“我怎么知道我正在迭代的项目是否为 NULL?”没有意义。 如果你想检查你是否已经为你的 struct members are not 填充了值,那么在你的结构中再添加一个字段来通知 struct members 是否被填充。

struct child
{
    boolean is_valid;
    char *father;
    char *mother;
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多