如何声明一个具有任意大小的数组

4

好的,这是一个关于C编程作业的问题。但我真的被卡住了。

我要求用户输入单词,然后将输入插入到数组中,但我无法控制用户输入的单词数量。

我想问的是如何在C中声明一个数组,而不声明它的长度,也不询问用户应该设置什么长度。

我知道这与malloc有关,但如果您能给我一些如何做到这一点的示例,我会非常感激。


这个 char a[]="somename" ; 怎么样?可以代替 malloc 吗? - niko
4个回答

5
你可以使用malloc申请一块足够大的内存来存储特定数量的数组项。
然后,在超出该数量之前,您可以使用realloc来扩展内存块大小。
这里是一段C代码,演示了在整数数组不足以容纳下一个整数时重新分配内存的过程。
#include <stdio.h>
#include <stdlib.h>

int main (void) {
    int *xyzzy = NULL;   // Initially NULL so first realloc is a malloc.
    int currsz = 0;      // Current capacity.
    int i;

    // Add ten integers.

    for (i = 0; i < 10; i++) {
        // If this one will exceed capacity.

        if (i >= currsz) {
            // Increase capacity by four and re-allocate.

            currsz += 4;
            xyzzy = realloc (xyzzy, sizeof(int) * currsz);
                // Should really check for failure here.
        }

        // Store number.

        xyzzy[i] = 100 + i;
    }

    // Output capacity and values.

    printf ("CurrSz = %d, values =", currsz);
    for (i = 0; i < 10; i++) {
        printf (" %d", xyzzy[i]);
    }
    printf ("\n");

    return 0;
}

谢谢,但我该怎么做呢? - Nu Gnoj Mik
为了获得更好的速度,从 currsz = 4 开始,然后每次重新分配时将 currsz 加倍,这将给您带来摊销常数时间,而不是线性时间。 - Daniel
错误,@Dani,那肯定是O(log N)时间,对吧?不过在回答的上下文中并不重要,它只是展示如何使用realloc :-) - paxdiablo
@paxdiablo:嗯,既然你要进行分块,我展示了一种进一步的优化。而且它是O(1)而不是O(log n) - Daniel
每个人都说每次加倍是最好的,但我不太明白为什么。每次只增加一个元素的容量肯定不好,但是否有折中的方法呢? - sudo

3
您可以每次像这样重新分配它:
int size = 0;
char **array = malloc(0);
while(/* something */)
{
    char *string = // get input
    size++;
    array = realloc(array, size * sizeof(char*));
    array[size - 1] = string;
}

如果你关心速度,也可以分块处理。

4
调用malloc(0)是浪费时间的 - 行为在实现中被定义,要么分配一个您无法使用的块,要么返回NULL(参见C99 7.20.3)。 相比之下,直接将其设置为NULL更好,这可以被realloc使用并且可以节省函数调用。 - paxdiablo
2
@Carey:这就像是说“如果你讨厌甲壳虫汽车,那么你就讨厌所有汽车”——编程有很多方面。 - Daniel
不,它不是。C语言是一种低级语言。它是相对简单的编程本质(我猜你没有上过汇编课)。如果你讨厌C语言(没有接触过其他语言),那么你就是讨厌编程。 - Carey Gregory
Java只是更容易学习。它没有考虑效率,因为它是高级语言,并且在浪费资源的JVM中运行其代码。我首先学习了Java,但现在转向C,他们应该首先教我们C。 - sudo
@MarlonBrando Java的“可扩展数组”很容易声明,因为您正在使用Java库ArrayList。我相信有C库可以做到这一点,但这样会浪费时间。 - sudo
显示剩余5条评论

0

但是他在运行时甚至不知道大小。 - Daniel
malloc仍然适用,正如@pax所指出的那样,你只需使用realloc。 - logancautrell

-1

0) 显然你需要多个缓冲区,因此你需要一个类似列表的结构:可能是一个记录,包含100个字符的char数组和指向下一个结构的指针。 1) 你需要逐个字符捕获单词并将它们存储在你的缓冲区中。 2) 一旦缓冲区已满,你就会分配另一个记录,将其链接到前一个记录,并继续进行,直到你没有内存或进程结束。

这应该比realloc函数更好的性能。我相信malloc试图给出连续的内存块。因此,类似列表的结构将更快,效果更好。


如果用户输入的单词超过100个字符怎么办?为什么要在大多数用户输入的单词上浪费95个字符?realloc()中有比你意识到的更高的性能。 - Carey Gregory
Malloc看起来会给出一个连续的内存块,但由于虚拟内存的原因,它并不是连续的,可能会被分割成碎片。这意味着realloc甚至可能不会调用复制。 - Daniel
@gregory 100字节只是一个例子。realloc的C版本没有智能功能。如果你在谈论一些花哨的实现,请说明你心中有哪个。 - Deian
@dani 我在谈论普通的C语言malloc。它只能使用连续的内存块。现在大多数操作系统都比这更智能,提供更动态的行为。然而,这个人正在上学,我相信他的老师想要教/展示基本的内存结构,如链表等。而不是花哨的alloc/realloc函数。 - Deian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接