C 编程分段错误



这是查找第 n 个斐波那契数的最后一位数字的代码

#include <stdio.h>
int main() {
long i, j, fib[1000];
fib[0] = 0;         
fib[1] = 1;         
scanf("%li", &j);     
for(i = 2; i != 1000; i++)     
{
fib[i] = (fib[i - 2] + fib[i - 1]) % 10;
}
printf("%li", fib[j]);
return 0;
}

它显示分段错误。我该如何解决它?

我能看到这不起作用的唯一原因是您输入的数字超出了0 <= j <= 999范围。这是由于数组变量的限制:long fib[1000]

可以通过以下两种方式之一解决此问题,具体取决于您的需要:

  1. 您可以添加检查以确保输入值j在范围内,如果不是,则要求输入另一个数字。
  2. 您可以停止使用数组变量,而只使用三个变量:一个用于存储当前值,另外两个用于存储前两个值。这些将在您计算时更新。此方法仍使用循环。

#1 是最容易实现的,如下所示:

while (1)
{
printf("j > ");
scanf(" %li", &j);
if (0 <= j <= 999)
{
break;
}
}

#2 有点复杂,但它有效地删除了j必须小于 1000 的任意限制(并更改限制,使j必须小于LONG_MAX):

// num_cache[0] is the number before the previous number
// num_cache[1] is the previous number to the current number
long num_cache[2] = { 0, 0 };
long current_fib = 1;
for (i = 2; i < j; i++)
{
// Push back the numbers
num_cache[0] = num_cache[1];
num_cache[1] = current_fib;
// Calculate the new number
current_fib = (num_cache[0] + num_cache[1]) % 10;
}

这些解决方案之一应该可以解决您的问题。

分割错误似乎是由于对输入值的检查不充分而发生的。

  1. 如果程序的输入不是有效的数字,则调用scanf()j的值将保持不变。由于此变量未初始化,因此当您尝试访问fib[]数组的第 j 个元素时,这将导致未定义的行为。

  2. 如果 j 的值小于零或大于 999,则在退出for()循环时,您将访问不存在的fib[]成员。在继续之前,代码应检查j是否有效。

下面是您的代码,其中包含一些修改以实现这些保护措施并将"幻数"1000 移动到 #defined 值。

#include <stdio.h>
#define FIBONACCI_LIMIT 1000L
int main(){
long i, j, fib[FIBONACCI_LIMIT];
fib[0] = 0;
fib[1] = 1;
if (scanf("%li", &j) != 1)
{
fprintf(stderr, "Invalid inputn");
return 1;
}
if (j<0 || j>=FIBONACCI_LIMIT)
{
fprintf(stderr, "Number must be in range 0 <= n < %lin", FIBONACCI_LIMIT);
return 2;
}
for(i=2; i!=1000; i++)
{
fib[i] = (fib[i-2] + fib[i-1])%10;
}
printf("%lin", fib[j]);
return 0;
}

可以通过完全删除fib[]数组来改进代码,因为当您只需要计算一个值时,不需要存储 1000 个值。此外,斐波那契数列中数字的最后一位数字形成了 60 个值的重复模式,因此您的第一步应该是将j替换为j % 60。下面是代码的改进版本,它将与任何能够适应long整数的非负输入一起使用:

#include <stdio.h>
int main() {
long i, j, t, f0=0, f1=1;
if (scanf("%li", &j) != 1)
{
fprintf(stderr, "Invalid inputn");
return 1;
}
if (j < 0)
{
fprintf(stderr, "Number must be non-negativen");
return 2;
}
j %= 60;
for (i=0; i<j; i++)
{
t = f0;
f0 = f1;
f1 = (f1 + t) % 10;
}
printf("%lin", f0);
return 0;
}

您没有显示输入的变量j的值。

考虑到下一个斐波那契数在循环中计算不正确。

如果使用整数类型unsigned long long则此类型的对象只能容纳 93 个斐波那契数。

该程序可能看起来像

#include <stdio.h>
#define N   100
int main(void) 
{
while ( 1 )
{
unsigned long long fib[N] = { 0, 1 };
unsigned int n;
printf( "Enter a sequantial number of a fibonacci number (0 - exit): " );
if ( scanf("%u", &n) != 1 || n == 0 ) break;
unsigned int i = 2;
for (; i < N && i <= n && fib[i-1] <= fib[i-2] + fib[i-1]; i++)
{
fib[i] = fib[i - 2] + fib[i - 1];
}
if (n < i)
{
printf("#%u: %llu %llun", n, fib[n], fib[n] % 10);
}
else
{
puts("Too big fibonacci number");
}
}
return 0;
}

它的输出可能看起来像

Enter a sequantial number of a fibonacci number (0 - exit): 1
#1: 1 1
Enter a sequantial number of a fibonacci number (0 - exit): 2
#2: 1 1
Enter a sequantial number of a fibonacci number (0 - exit): 3
#3: 2 2
Enter a sequantial number of a fibonacci number (0 - exit): 93
#93: 12200160415121876738 8
Enter a sequantial number of a fibonacci number (0 - exit): 94
Too big fibonacci number
Enter a sequantial number of a fibonacci number (0 - exit): 0

相关内容

  • 没有找到相关文章