【问题标题】:Can you define the size of an array at runtime in C你能在 C 运行时定义数组的大小吗
【发布时间】:2010-12-08 04:46:07
【问题描述】:

C 新手,非常感谢您的帮助。

是否可以在 C 中定义一个数组而不指定其大小或初始化它。

例如,我可以提示用户输入数字并将它们存储在 int 数组中吗?我不知道他们会预先输入多少个数字。

我现在能想到的唯一方法就是定义一个最大尺寸,这不是一个理想的解决方案......

【问题讨论】:

    标签: c malloc dynamic-memory-allocation


    【解决方案1】:

    嗯,你可以动态分配大小:

    #include <stdio.h>
    
    int main(int argc, char *argv[])
    {
      int *array;
      int cnt;
      int i;
    
      /* In the real world, you should do a lot more error checking than this */
      printf("enter the amount\n");
      scanf("%d", &cnt);
    
      array = malloc(cnt * sizeof(int));
    
      /* do stuff with it */
      for(i=0; i < cnt; i++)
        array[i] = 10*i;
    
      for(i=0; i < cnt; i++)
        printf("array[%d] = %d\n", i, array[i]);
    
      free(array);
    
      return 0;
    }
    

    【讨论】:

    • 当然,您需要知道每次运行时要添加的许多数字。 realloc 否则。
    • 感谢您的帮助。我想我在第一篇文章中没有明确提出这个问题。问题是我们不知道用户将输入多少个数字,而用户也不知道。假设我们要求用户输入任意数量的数字,然后我们为他计算平均值。他需要做的就是输入数字,回车,输入另一个数字……完成后输入 Q。如何在不询问用户告诉我他打算输入多少个数字的情况下将这些数字保存在一个数组中?这将是 C++ 中的简单向量用法 ...
    • 对不起,平均值是一个不好的例子,因为我们只需要求和,假设我们需要保存所有数字来进行一些花哨的计算......
    • @Bobby - 说到拼写错误,“动态”中没有“o”。但这不是一个严重的问题。
    • 在 C++ 中,“vector”类在超出大小时会动态重新分配内存。在 C 中,没有内置机制可以做到这一点;您要么需要自己实现它(使用 realloc),要么使用在 C 中实现向量或链表的第三方库。
    【解决方案2】:

    大概是这样的:

    #include <stdio.h>
    #include <stdlib.h>
    
    /* An arbitrary starting size. 
       Should be close to what you expect to use, but not really that important */
    #define INIT_ARRAY_SIZE 8
    
    int array_size = INIT_ARRAY_SIZE;
    int array_index = 0;
    array = malloc(array_size * sizeof(int));
    
    void array_push(int value) {
      array[array_index] = value;
      array_index++;
      if(array_index >= array_size) {
        array_size *= 2;
        array = realloc(array, array_size * sizeof(int));
      }
    }
    
    int main(int argc, char *argv[]) {
      int shouldBreak = 0;
      int val;
      while (!shouldBreak) {
        scanf("%d", &val);
        shouldBreak = (val == 0);
        array_push(val);
      }
    }
    

    这将提示输入数字并将它们存储在一个数组中,如您所要求的。给定 0 时,它将终止。

    您创建了一个访问器函数array_push 用于添加到您的数组中,当您用完空间时,您可以使用此函数调用realloc。每次都将分配的空间量加倍。最多你会分配双倍你需要的内存,最坏的情况你会调用realloc log n 次,其中 n 是最终预期的数组大小。

    您可能还想在调用 malloc 和 realloc 后检查失败。我没有在上面这样做。

    【讨论】:

    • 在另一条评论中,您提到您希望程序在用户提供“q”时停止询问数字。通过使用 %s 而不是 %d 调用 scanf 来做到这一点。然后你将角色与“q”进行比较并决定是否退出。然后你需要通过调用 atoi 将其转换为 int
    • 非常感谢,这很聪明,让我对这个问题有了不同的思考方式:不必精确,先近似,然后再扩展。我可能会研究如何在 C++ 中实现向量,我认为这将为此类问题提供一些见解。
    【解决方案3】:

    根据定义,数组是固定大小的内存结构。你想要一个向量。由于标准 C 没有定义向量,您可以尝试寻找一个库,或者自己动手制作。

    您需要进行动态分配:您需要一个指向未知大小的内存地址的指针。阅读mallocrealloc

    【讨论】:

    • 另外,补充一点,一种流行的执行 realloc() 方法是,每当您需要重新分配(因为空间不足)时,将数组大小加倍;这样你就可以尽可能少地调用 realloc。
    • 在每次重新分配时将大小加倍并不是为了最大限度地减少realloc 调用的数量,而是为了保持良好的渐近效率。如果在每次重新分配时向向量添加一个恒定增量,则推入 n 元素需要 O(n^2) 时间。如果在重新分配时将大小乘以 >1 的某个因子,则每次推送都需要摊销的常数时间,整个过程需要 O(n) 时间。
    【解决方案4】:

    如果您只需要一个可以动态更改其大小的数据结构,那么您可以选择的最佳选择是链表。您可以将数据添加到列表中,为其动态分配内存,这会容易得多!

    【讨论】:

    • +1,考虑到问题中的信息,一个简单的链表听起来是最好的选择。如果 OP 能够在阅读完这些信息后阐明他将如何处理这些信息,我们或许可以提出一个更合适的数据结构。
    【解决方案5】:

    是的,当然。 C99 引入了 VLA 或可变长度数组。 一些简单的代码是这样的:

    #include <stdio.h>
    
    int main (void) {
    
        int arraysize;
        printf("How bid do you want your array to be?\n");
        scanf("%d",&arraysize);
        int ar[arraysize];  
        return 0;
    }
    

    【讨论】:

    • 代码块 := 缩进四个空格。一个快捷方式是:突出显示块并按 CTL-k。 HTH。
    【解决方案6】:

    您可以使用malloc 动态分配内存(即直到运行时才知道大小)。

    C 是一种低级语言:使用后必须手动释放内存;否则,您的程序将遭受内存泄漏。

    更新

    只需阅读您对另一个答案的评论。

    您需要一个大小动态变化的数组。

    嗯,C 没有语言/句法工具可以做到这一点;您要么必须自己实现它,要么使用已经实现它的库。

    看到这个问题:Is there an auto-resizing array/dynamic array implementation for C that comes with glibc?

    【讨论】:

      【解决方案7】:

      对于这样的事情,您可能需要研究以下数据结构: 链接列表(适合这种情况) 各种树(二叉树、堆等) 堆栈和队列

      但至于实例化一个可变大小的数组,这是不可能的。

      最接近动态数组的是使用 malloc 及其相关命令(delete、realloc 等)。

      但是在这种情况下,使用 malloc 之类的命令可能会导致需要扩展数组,这是一项昂贵的操作,您需要初始化另一个数组,然后将旧数组复制到该数组中。列表和其他数据类型通常更擅长调整大小。

      【讨论】:

        【解决方案8】:

        如果您正在寻找阵列设施并且不想自己推出,请尝试以下方法:

        1. Glib
        2. Apache APR
        3. NSPR

        【讨论】:

          【解决方案9】:

          如果您是初学者,也许您还不想处理mallocfree。因此,如果您使用 GCC,则可以在堆栈上分配可变大小的数组,只需将大小指定为表达式。

          例如:

          #include <stdio.h>
          void dyn_array(const unsigned int n) {
                  int array[n];
                  int i;
          
                  for(i=0; i<n;i++) {
                          array[i]=i*i;
                  }
                  for(i=0; i<n;i++) {
                          printf("%d\n",array[i]);
                  }
          }
          int main(int argc, char **argv) {
                  dyn_array(argc);
                  return 0;
          }
          

          但请记住,这是一个非标准扩展,因此如果可移植性很重要,您不应该指望它。

          【讨论】:

          • 这不是“非标准表达”——在写出答案时,这已经是 10 年的国际标准了。问题在于来自微软等无能公司的许多真正非标准的编译器,它们甚至不支持已有 10 年历史的标准。
          【解决方案10】:

          上面给出的答案是正确的,但有一个更正,函数 malloc() 保留一块指定大小的内存并返回一个 void* 类型的指针,它可以转换为任何形式的指针。 语法:ptr = (cast-type*) malloc(byte-size)

          #include<stdio.h>
          #include<cstdlib>
          int main(int argc,char* argv[]){
          int *arraySize,length;
          scanf("%d",&length);
          arraySize = (int*)malloc(length*sizeof(int));
          for(int i=0;i<length;i++)
              arraySize[i] = i*2;
          for(int i=0;i<length;i++)
              printf("arrayAt[%d]=%d\n",i,arraySize[i]);
          free(arraySize);
          }
          

          【讨论】:

            猜你喜欢
            • 2011-02-02
            • 2010-12-13
            • 1970-01-01
            • 1970-01-01
            • 2013-12-04
            • 1970-01-01
            • 2015-11-19
            • 1970-01-01
            • 2016-12-20
            相关资源
            最近更新 更多