【问题标题】:How to iterate over of an array of structures如何迭代结构数组
【发布时间】:2013-09-25 17:38:24
【问题描述】:

在我的应用程序中,我使用了一个结构数组,我需要遍历该数组。正确的方法是什么?如何检查是否已到达数组末尾?

// structure
struct MyData {
  int count;
  char name[20];
  float average;
}

我试过这样迭代,但是我的应用程序崩溃了:

struct MyData data[2] = { {3, "name1", 1.0}, {5, "name2", 2.5} };
struct MyData* ptr = data;

while (*ptr != NULL) {
  // print the contents, works ok for 2 elements

  ptr++; // increment the pointer
}

【问题讨论】:

    标签: c arrays struct iteration boundary


    【解决方案1】:

    结构数组是如何分配的

    在您的情况下,MyData[2] 数组在内存中如下所示:

    | count | name | average | count | name | average |
    ^ -- your ptr points here 
    

    这是一个大小为2 * sizeof (struct MyData)的单个连续空间。

    每当您执行ptr++ 操作时,指针都会移动到数组中的下一个结构,这意味着它会考虑单个struct MyData 的大小。

    | count | name | average | count | name | average |
                             ^ -- after ptr++ your ptr points here
    

    在另一个ptr++ 之后,您的指针将指向内存就在您的数组之后

    | count | name | average | count | name | average | 
                                                      ^ -- another ptr++ and your ptr points here
    

    当您取消引用 ptr 指针时,您访问的内存尚未使用甚至未分配。这是未定义的行为,因此您的应用程序会崩溃。

    如何迭代?

    有几种方法可以做到这一点。请注意,并非所有方法都适用于所有情况。

    一个简单的

    我们通常只知道数组的大小。然后我们可以使用普通的for 循环来迭代内容。

    int len = 2;
    struct MyData data[len] = { {3, "name1", 1.0}, {5, "name2", 2.5} };
    struct MyData* ptr = data;
    for (int i=0; i<len; i++, ptr++ ) {
       // do your thing with the ptr
       // and note that ptr gets increased inside for
    }
    

    使用 sizeof 确定数组长度

    struct MyData data[2] = { {3, "name1", 1.0}, {5, "name2", 2.5} };
    struct MyData* ptr = data;
    struct MyData* endPtr = data + sizeof(data)/sizeof(data[0]);
    while ( ptr < endPtr ){
       // do your thing with the ptr
       ptr++;
    }
    

    sizeof(data)/sizeof(data[0]) 计算元素的数量:获取数组的总大小,然后除以单个元素的大小。

    这种方法有其缺点。数组声明为指针时不能使用!例如,当我们将数组作为参数传递给函数时,它通常会转换为指针 - 然后我们无法确定数组的大小。

    【讨论】:

      【解决方案2】:

      如果您无法控制数组的大小,甚至无法请求,您可以尝试重新组织您的代码,而不是使用 MyData 数组,而是使用 指针数组强>到MyData。 然后,您的数组必须长一个插槽才能存储具有 NULL 值的守卫。

      您的迭代看起来就像您作为示例编写的那样。

      // N is the number of MyData instances you have
      MyData* vData[N+1];
      // vData[i] is filled, and vData[N] = NULL
      
      // ...
      
      MyData* vPtr = vData[0];
      while(vPtr) {
          // ...
      }
      

      但这涉及将数组的类型从MyData[] 更改为MyData*[]。如果你不能,你应该按照 Dariusz 的回答。

      【讨论】:

      • 但是while(vPtr) 不应该是while(vPtr++),因为它会导致无限循环,内部也应该有边界检查,因为如果结构已满,则条件永远不会满足 NULL 值
      猜你喜欢
      • 2016-08-26
      • 2019-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-05
      • 2019-08-06
      • 2023-04-05
      • 1970-01-01
      相关资源
      最近更新 更多