【问题标题】:local and global arrays and segmentation fault局部和全局数组和分段错误
【发布时间】:2020-12-01 07:57:20
【问题描述】:

我遇到以下问题:我想获取一个大数字(大约 15 位数字)并将其转换为单个数字并将它们存储在一个数组中。我将在代码中进一步需要这些数字。问题是,如果我在 while 循环之外声明数组,它会存储前四个值,但随后会出现分段错误。如果我在循环中声明它,代码会按我的意愿工作,但是我不知道如何将数组移出该循环,以便我可以进一步使用它。我该如何解决这个问题?这是我编译的:

unsigned long long card_num;
printf("Enter your credit card number:\n");
scanf("%llu", &card_num);
int count = 0;
    
while (card_num != 0)
{
   int digits[count]; //declaring array into which digits will be stored
   digits[count] = card_num%10; // get last digit, store it in array
   card_num = card_num/10; //remove last digit
   printf("Digit[%i] = %i\n", count, digits[count]);
   printf("Number of digits: %i\n", count);
   count ++;
}

【问题讨论】:

  • int digits[count]; ..开始时count的值是多少?
  • digits[count] = card_number%10; 正在数组外写入。数组索引从0count-1
  • 声明具有最大可能大小的数组。信用卡号码最多为 16 位。
  • 另外,如果您从末尾到开头抓取数字,您需要索引从 count-1 down 变为零,递减而不是递增.
  • 这个问题被问了太多次了。它在 first 行开始错误。 首先不要将信用卡号输入到无符号长长中。

标签: arrays c scope


【解决方案1】:

在您的代码中,第一次迭代

 int digits[count]; 

count0,这违反了规范中提到的约束。根据C11,第 6.7.5.2 章,

除了可选的类型限定符和关键字static[] 可以分隔表达式或*。如果它们界定了一个表达式(它指定了一个数组的大小),则该表达式应为整数类型。如果表达式是常量表达式,它的值应大于零。 [....]

如果大小是一个不是整数常量表达式的表达式:如果它出现在函数原型范围的声明中,则将其视为被*替换;否则,每次对其进行评估时,它的值都应大于零

所以,这不是一个有效的代码。

【讨论】:

    【解决方案2】:

    如前所述,您所做的是完全错误的。
    有几种方法可以解决这个问题。最简单的方法是在程序的开头分配一个数组,为所有用例分配足够的空间,例如:

    #define MAX_DIGIT 50
    int digits[MAX_DIGIT];
    

    然后你只需要通过检查count < MAX_DIGIT来检查你没有遍历这个数组。

    另一种方法是使用 int 指针 int *digitsmalloc (我让你用谷歌搜索)进行动态内存分配,一旦你知道你需要的数组的大小。在开始获取数字之前,您必须更改一些代码以了解位数,因为您需要在开始存储数字之前分配内存。
    您可以使用realloc 来保留与您已有的代码相似的代码,但我不建议这样做,因为为您添加的每个值重新分配内存效率不高。

    【讨论】:

    • 试图查看此答案为问题添加了哪些附加信息。
    【解决方案3】:

    你的逻辑很好。

    问题是你试图增加固定长度数组的长度,而迭代这是不允许的。

    您应该永远不要在程序中的任何位置更改固定长度数组的长度。

    但是,如果您想在运行时更改数组的长度,则必须使用 mallocrealloc 函数。

    看看这个例子

    //declarations
    int *storeNum;
    storeNum = (int *)malloc(1 * sizeof(int));
    
    //logic
    while(num != 0) {
        if(i > 0) 
           storeNum = realloc(storeNum, (i+1) * sizeof(int));
        storeNum[i] = num % 10;
        num = num/10;
        ++i;
    }
    

    首先我将数组大小最初声明为 1,然后随后使用 realloc 函数将其递增

    您还将数组大小存储在 i 中,您可以稍后在循环中的代码中使用它。

    但请记住,数字将以相反的顺序存储在您的数组中。

    此外,您不应在循环中声明数组

    由于您已经“声明”了数组,因此每次编译器在迭代时进入循环时都会将数组声明视为新数组。仅此而已。

    【讨论】:

      猜你喜欢
      • 2017-03-04
      • 1970-01-01
      • 2020-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多