#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char** argv)
{
/* declare a pointer do an integer */
int *data;
/* we also have to keep track of how big our array is - I use 50 as an example*/
const int datacount = 50;
data = malloc(sizeof(int) * datacount); /* allocate memory for 50 int's */
if (!data) { /* If data == 0 after the call to malloc, allocation failed for some reason */
perror("Error allocating memory");
abort();
}
/* at this point, we know that data points to a valid block of memory.
Remember, however, that this memory is not initialized in any way -- it contains garbage.
Let's start by clearing it. */
memset(data, 0, sizeof(int)*datacount);
/* now our array contains all zeroes. */
data[0] = 1;
data[2] = 15;
data[49] = 66; /* the last element in our array, since we start counting from 0 */
/* Loop through the array, printing out the values (mostly zeroes, but even so) */
for(int i = 0; i < datacount; ++i) {
printf("Element %d: %d\n", i, data[i]);
}
}
而已 . 接下来是一个更为复杂的解释为什么这个工作:)
我不知道你对C指针的了解程度如何,但C中的数组访问(如 array[2] )实际上是通过指针访问内存的简写 . 要访问 data 指向的内存,请编写 *data . 这称为解除引用指针 . 由于 data 的类型为 int * ,因此 *data 的类型为 int . 现在来看一条重要的信息: (data + 2) 表示“将2个字节的字节大小添加到 data 指向的地址” .
这是一个示例程序,它将 stdin 读入一个根据需要增长的内存缓冲区 . 在实际程序中,'s simple enough that it should give some insight in how you might handle this kind of thing. One thing that'可能会有不同的做法,即每次分配时数组必须如何增长 - 如果你想在调试器中逐步完成,我会在这里保持较小的数据以帮助保持简单 . 一个真正的程序可能会使用一个更大的分配增量(通常,分配大小加倍,但如果你在某个合理的大小上限 - 增加 - 当你进入数百兆字节时加倍分配可能没有意义) .
此外,我在这里使用了对缓冲区的索引访问作为示例,但在实际程序中我可能不会这样做 .
#include <stdlib.h>
#include <stdio.h>
void fatal_error(void);
int main( int argc, char** argv)
{
int buf_size = 0;
int buf_used = 0;
char* buf = NULL;
char* tmp = NULL;
char c;
int i = 0;
while ((c = getchar()) != EOF) {
if (buf_used == buf_size) {
//need more space in the array
buf_size += 20;
tmp = realloc(buf, buf_size); // get a new larger array
if (!tmp) fatal_error();
buf = tmp;
}
buf[buf_used] = c; // pointer can be indexed like an array
++buf_used;
}
puts("\n\n*** Dump of stdin ***\n");
for (i = 0; i < buf_used; ++i) {
putchar(buf[i]);
}
free(buf);
return 0;
}
void fatal_error(void)
{
fputs("fatal error - out of memory\n", stderr);
exit(1);
}
此示例与其他答案中的示例相结合,可以让您了解如何在较低级别处理此类事物 .
12
我可以想象的一种方法是使用链表来实现这样的场景,如果你需要在用户输入指示循环终止的东西之前输入的所有数字 . (作为第一个选项发布,因为从来没有为用户输入做过这个,它似乎很有趣. Wasteful but artistic )
另一种方法是进行缓冲输入 . 如果循环继续,则分配缓冲区,填充,重新分配( not elegant, but the most rational for the given use-case ) .
7 回答
malloc()
(及其朋友free()
和realloc()
)是用C做到这一点的方法 .这可以通过使用指针,并使用
malloc
在堆上分配内存来完成 . 请注意,以后无法询问内存块有多大 . 您必须自己跟踪阵列大小 .而已 . 接下来是一个更为复杂的解释为什么这个工作:)
我不知道你对C指针的了解程度如何,但C中的数组访问(如
array[2]
)实际上是通过指针访问内存的简写 . 要访问data
指向的内存,请编写*data
. 这称为解除引用指针 . 由于data
的类型为int *
,因此*data
的类型为int
. 现在来看一条重要的信息:(data + 2)
表示“将2个字节的字节大小添加到data
指向的地址” .C中的数组只是相邻内存中的一系列值 .
array[1]
紧挨着array[0]
. 因此,当我们分配一大块内存并希望将其用作数组时,我们需要一种简单的方法来获取内部每个元素的直接地址 . 幸运的是,C允许我们在指针上使用数组表示法 .data[0]
表示与*(data+0)
相同的内容,即“访问data
指向的内存” .data[2]
表示*(data+2)
,并访问内存块中的第三个int
.它经常做的方式如下:
分配一些初始(相当小)的数组;
读入此数组,跟踪您已阅读的元素数量;
一旦数组已满,重新分配,大小加倍并保留(即复制)内容;
重复直到完成 .
我发现这种模式经常出现 .
这个方法的有趣之处在于它允许人们在摊销的
O(N)
时间内逐个将N
元素插入到一个空数组中而不事先知道N
.现代C,又名C99,有variable length arrays,VLA . 不幸的是,并非所有的编译器都支持这一点,但如果你的确支持这一点,那么这将是另
这是一个示例程序,它将
stdin
读入一个根据需要增长的内存缓冲区 . 在实际程序中,'s simple enough that it should give some insight in how you might handle this kind of thing. One thing that'可能会有不同的做法,即每次分配时数组必须如何增长 - 如果你想在调试器中逐步完成,我会在这里保持较小的数据以帮助保持简单 . 一个真正的程序可能会使用一个更大的分配增量(通常,分配大小加倍,但如果你在某个合理的大小上限 - 增加 - 当你进入数百兆字节时加倍分配可能没有意义) .此外,我在这里使用了对缓冲区的索引访问作为示例,但在实际程序中我可能不会这样做 .
此示例与其他答案中的示例相结合,可以让您了解如何在较低级别处理此类事物 .
我可以想象的一种方法是使用链表来实现这样的场景,如果你需要在用户输入指示循环终止的东西之前输入的所有数字 . (作为第一个选项发布,因为从来没有为用户输入做过这个,它似乎很有趣. Wasteful but artistic )
另一种方法是进行缓冲输入 . 如果循环继续,则分配缓冲区,填充,重新分配( not elegant, but the most rational for the given use-case ) .
我不认为所描述的是优雅的 . 可能,我会更改用例( the most rational ) .
尝试实现动态数据结构,例如linked list