如何解决C 中的指针数组,易于迭代
最近我在思考这个问题:如何在 C 中更简单地迭代指针数组。
如果我在 C 中创建一个字符串数组,它应该看起来像这样吗?
int size = 5;
char ** strArr = (char **) malloc(sizeof(char *) * size);
if (strArr == NULL) return;
但问题是,当你出于某种原因想要遍历这个数组时(比如打印其中的所有值),你必须跟踪它的当前大小,存储在另一个变量中。
这不是问题,但是如果您创建了大量数组,则必须在代码中跟踪每个数组的大小。如果你把这个数组传递给另一个函数,你也必须传递它的大小。
void PrintValues (char ** arr,int size) {
for (int i = 0; i < size; i++)
printf("%s\n",arr[i]);
}
但是当迭代一个字符串时,情况就不同了。您有 '\0' 字符,它指定字符串的结尾。因此,您可以像这样遍历字符串,而无需保留其大小值:
char * str = (char *) malloc(sizeof(char) * 4);
str[0] = 'a';
str[1] = 'b';
str[2] = 'c';
str[3] = '\0';
for (int i = 0; str[i] != '\0'; i++)
printf("%c",str[i]);
printf("\n");
现在我的问题: 在指针数组中分配 +1 个单元以保持其尾部为 NULL 是否可以或在道德上是正确的?
char ** strArr = (char **) malloc(sizeof(char *) * (5 +1);
if (strArr == NULL) return;
strArr[0] = PseudoFunc_NewString("Car");
strArr[1] = PseudoFunc_NewString("Car#1");
strArr[2] = PseudoFunc_NewString("Car#2");
strArr[3] = PseudoFunc_NewString("Tree");
strArr[4] = PseudoFunc_NewString("Tree#1");
strArr[5] = NULL; // Stop iteration here as next element is not allocated
然后我可以使用 NULL 指针来控制迭代器:
void PrintValues (char ** arr) {
for (int i = 0; arr[i] != NULL; i++)
printf("%s\n",arr[i]);
}
这将帮助我保持代码更简洁,尽管它会消耗更多内存,因为指针大小大于整数大小。
此外,当使用基于事件的库(如 Gtk)进行编程时,大小值会在某个时候从堆栈中释放出来,因此我必须创建一个指针来动态存储大小值。
在这种情况下,可以这样做吗?还是被认为是坏事?
这种技术是否仅用于 char 指针,因为 char 类型的大小只有 1 个字节?
我怀念在 C 中使用 foreach 迭代器...
解决方法
现在我的问题是:在指针数组中分配 +1 个单元以保持其尾部为 NULL 是否可以或在道德上是正确的?
这没问题,最后的 NULL 称为 哨兵值,使用它是有点普遍的做法。当您出于某种原因甚至不知道数据的大小时,最常使用此方法。
然而,这不是最好的解决方案,因为您必须遍历所有数据才能找到大小。单独存储大小的解决方案要快得多。例如,在同一位置包含大小和数据的结构数组。
,现在我的问题是:在指针数组中分配 +1 个单元以保持其尾部为 NULL 是否可以或在道德上是正确的?
在 C 中,这是一个很常见的模式,它有一个名字。您只是在使用 sentinel value。
只要您的列表通常不能包含空指针,就可以了。总的来说,它有点容易出错,但话说回来,这对你来说是 C。
,没关系,是常用的模式。
作为替代,您可以使用 struct
,在那里您可以创建一个 size
变量,您可以在其中存储数组的当前大小,并将结构作为参数传递。优点是你不需要遍历整个数组来知道它的大小。
示例:
#include <stdlib.h>
#include <stdio.h>
typedef struct
{
char **strArr;
int size;
} MyStruct;
void PrintValues(MyStruct arr) //pass the struct as an argument
{
for (int i = 0; i < arr.size; i++) //use the size passed in the struct
printf("%s\n",arr.strArr[i]);
}
int main()
{
// using the variable to extract the size,to avoid silent errors
// also removed the cast for the same reason
char **strArr = malloc(sizeof *strArr * 5);
if (strArr == NULL) return EXIT_FAILURE;
strArr[0] = "Car";
strArr[1] = "Car#1";
strArr[2] = "Car#2";
strArr[3] = "Tree";
strArr[4] = "Tree#1";
MyStruct strt = { strArr,5 }; // initialize the struct
PrintValues(strt); //voila
free(strArr); // don't forget to free the allacated memory
return EXIT_SUCCESS;
}
这允许通过错误检查直接访问索引:
// here if the array index exists,it will be printed
// otherwise no,allows for O(1) access error free
if(arr.size > 6){
printf("%s\n",arr.strArr[6]);
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。