问题:C声明未知大小的整数数组



我需要使用scanf函数读取用户输入的未知数量的各种数字。这仅仅意味着各种整数的数量是由用户通过发送尽可能多的数字来确定的。请注意,我直接读取数字(我必须这样做),如下面的代码所述:

int main(void)
{
    int numbers[];
    int error = 0;
    int i = 0;
    while(scanf("%i", &numbers[i++]) == 1);
    for(int i = 0; i < sizeof(numbers) - 1; ++i) {
        if(numbers[i] < -10000 || numbers[i] > 10000)
        {
            printf("%i%s", numbers[i], ", ");
        }
        else
        {
            printf("%s", "bbnError: Error: Vstup je mimo interval!n");
            // Means "Input is out of range!".
            // We have to write exact output to terminal as stated in HW.
            i = sizeof(numbers);
            error = 1;
        }
    }
    ...
}

int error实际上是一个布尔值,但我懒得实现布尔库,所以我将其定义为整数:D

然而,问题在别处。编译器抛出错误:

main.c:7:9: error: array size missing in ‘numbers’
     int numbers[];
                ^

看起来C程序需要知道数组的可分配大小。我已经研究了一些其他人分享的代码,以找出我需要实现的基础知识,同时搜索数组大小问题,我发现了这个问题:

C -声明一个未定义值的数组

但是,对于直接输入未知数量的数字,它不能解决数组大小未知的问题。我没找到需要解决的问题。我试图定义数组的最大大小,以容纳最多999个数字,但随后编译器抛出了这个异常:

main.c:50:23: error: iteration 999u invokes undefined behavior [-Werror=aggressive-loop-optimizations]
             if(numbers[j] > 0)
                       ^
main.c:48:9: note: containing loop
         for(int j = 0; j < sizeof(numbers); ++j)
         ^

对于用于数字统计(总数,最大值,最小值,几率,偶数,正数,负数,它们的百分比和平均值)的每个循环都是一样的。这意味着数组的大小严格限制为999个数字,其余数字为零。我发现了一个malloc函数,但不明白它的用法:(

"I need read unknown amount of the users 's input using scanf function."是一个糟糕的设计目标。

任何允许外部接口输入任意输入量而不受限制的程序都是黑客利用的。

健壮的代码将用户输入限制在一个慷慨的,但相同的输入量。好的代码会将上界编码为常量或宏。

使用scanf()不是读取用户输入的最佳工具。
建议fgets()读取。(此处未显示)

#include <stdio.h>
#include <ctype.h>
// find the next character without consuming it.
int peek_ch(void) {
  unsigned char ch;
  if (scanf("%c", &ch) == 1) {
    ungetc(ch, stdin);
    return ch;
  }
  return EOF;
}
#define INPUT_N 1000
void foo(void) {
  int input[INPUT_N];
  size_t n = 0;
  // Read 1 _line_ of input using `scanf("%d", ....)` to read one `int` at a time
  for (n = 0; n < INPUT_N; n++) {
    int ch;
    while (((ch = peek_ch()) != 'n') && isspace(ch))
      ;
    // %d consume leading white-space including n, hence the above code to find it.
    if (scanf("%d", &input[n]) != 1) {
      break;
    }
  }
  // TBD: Add code to handle case when n == N
  for (size_t i = 0; i < n; i++) {
    printf("%zu: %dn", i, input[i]);
  }
}

根据您在评论中的描述,您将不得不使用malloc动态分配内存,并在必要时使用realloc扩展它。

下面是一个例子的基本框架:

#define INITIAL_SIZE 1024
#include <stdlib.h>
#include <stdio.h>
int main( void )
{
  size_t arraySize = 0;
  size_t i = 0;
  // initially allocate numbers array
  int *numbers = malloc( sizeof *numbers * INITIAL_SIZE );
  if ( !numbers )
  {
    fprintf( stderr, "Error allocating memory...exitingn" );
    exit( EXIT_FAILURE );
  }
  arraySize = INITIAL_SIZE;
  int input;
  while ( scanf( "%d", &input ) == 1 )
  { 
    if ( i == arraySize )
    {
      // double the size of the numbers array
      int *tmp = realloc( numbers, sizeof *numbers * (2 * arraySize) );
      if ( !tmp )
      {
        fprintf( stderr, "Could not extend array size...no more inputs allowedn" );
        break;
      }
      numbers = tmp;
      arraySize *= 2;
    }
    numbers[i++] = input;
  }
  // process numbers
  ...
  // clean up after ourselves
  free( numbers );

谢谢大家的帮助,我真的很感激。它帮助了我,虽然我真正需要的不是那一种解决方案,而是稍微不同的解决方案。正如上面的评论所述,我只需要满足作业输入和输出的要求。我联系了我的教授,他建议我去掉整数数组,并将初始数字列表输出和所有计算过程包含在while循环中。如果没有发生错误,则将百分比和平均求和的最终计算包装在if条件测试中,并完成所有最终输出。然而,这个答案不会被认为是一个解决问题的答案,因为它确实对我帮助很大。但是我标记为chux的答案,因为这是非常合乎逻辑的,任何程序都应该通过缓冲区溢出来防止恶意软件的利用。再次感谢大家的帮助,我真的很感激:)

最新更新