C 语言实战:数组实现斐波那契数列(格式化输出 + 边界校验)

65 阅读5分钟

C 语言实战:数组实现斐波那契数列(格式化输出 + 边界校验)

斐波那契数列是编程入门的经典案例,其 “前两项之和等于后一项” 的规律,适合练习数组存储、循环逻辑与格式化输出。本文以 “输出斐波那契数列前 n 项,每行显示 5 个且对齐” 为例,拆解数组实现思路、边界校验逻辑与格式化输出技巧,同时优化代码规范性,帮助新手掌握数列生成与格式控制的核心方法。

一、斐波那契数列核心规则

斐波那契数列定义:

  • 第 1 项、第 2 项固定为 1;
  • 从第 3 项开始,每一项 = 前两项之和(如:1,1,2,3,5,8,13...);
  • 核心需求:用户输入项数 n,输出前 n 项,每行显示 5 个,数字右对齐保证格式整洁。

二、优化后完整代码(规范 + 无 BUG)

/******************************
*文件名称:Fibonacci.c
*作者:czy
*邮箱:caozhiyang_0613@163.com
*创建日期:2025/12/25
*修改日期:2025/12/25
*文件功能:利用数组实现斐波那契数列的前n项,格式化对齐且每行输出5个数
*核心规则:斐波那契数列:1 1 2 3 5 8 13 21……
*****************************/

#include<stdio.h>

int main()
{
    int n;
    printf("输入斐波那契数列项数:");
    scanf("%d",&n);
    
    // 边界校验:项数必须为正整数,非法输入直接退出
    if(n<=0)
    {
        printf("错误:必须输入正整数!\n");
        return 1; // 返回非0值表示程序异常退出
    }
    
    // 定义数组存储斐波那契数列(变长数组,C99及以上支持)
    int a[n];
    int i;
    
    // 初始化前两项
    a[0] = 1;
    if(n >= 2)
    {
        a[1] = 1;
    }
    
    // 生成第3项到第n项
    for(i=2; i<n; i++)
    {
        a[i] = a[i-1] + a[i-2];
    }
    
    // 格式化输出:每行5个,右对齐占10个字符宽度
    printf("前%d项斐波那契数列:\n", n);
    for(i=0; i<n; i++)
    {
        printf("%10d", a[i]); // %10d:右对齐,不足10位补空格
        // 每输出5个数字换行
        if((i+1) % 5 == 0)
        {
            printf("\n");
        }
    }
    // 最后一行不足5个时,补充换行(避免输出卡在行尾)
    if(n % 5 != 0)
    {
        printf("\n");
    }
    
    return 0; // 程序正常退出
}

三、代码核心逻辑拆解

1. 边界校验:避免非法输入

c

运行

if(n<=0)
{
    printf("错误:必须输入正整数!\n");
    return 1;
}
  • 若用户输入 0、负数(如 - 5、0),直接提示错误并退出程序,避免后续数组越界或逻辑错误;
  • return 1:区别于正常退出的return 0,明确标记程序因非法输入终止。

2. 数组初始化与数列生成

c

运行

// 初始化前两项
a[0] = 1;
if(n >= 2)
{
    a[1] = 1;
}
// 生成后续项
for(i=2; i<n; i++)
{
    a[i] = a[i-1] + a[i-2];
}
  • 斐波那契数列前两项固定为 1,需单独初始化;
  • 若用户仅输入 n=1,无需初始化 a [1],避免数组越界;
  • 循环从 i=2 开始(第 3 项),通过a[i] = a[i-1] + a[i-2]递推生成所有项。

3. 格式化输出:对齐 + 分行

c

运行

printf("%10d", a[i]); // 右对齐,占10个字符宽度
if((i+1) % 5 == 0) // 每输出5个数字换行(i从0开始,i+1为项数)
{
    printf("\n");
}
// 最后一行不足5个时补换行
if(n % 5 != 0)
{
    printf("\n");
}
  • %10d:数字右对齐,不足 10 位时左侧补空格,保证不同位数的数字(如 1、13、233)对齐,视觉整洁;
  • (i+1)%5==0:i 从 0 开始,第 1 项是 i=0(i+1=1),第 5 项是 i=4(i+1=5),满足条件时换行;
  • 最后补充换行:若 n=7(输出 2 行,第 2 行仅 2 个数字),避免输出停在行尾,提升格式美观度。

四、原代码问题优化说明

对比原始代码中的注释版本,优化点如下:

  1. 冗余换行修复:原注释版将if(n%5!=0)写在输出循环内,导致每输出一个数字都判断一次,产生大量多余换行,优化后移到循环外,仅判断一次;
  2. 边界校验增强:原代码非法输入仅提示但不退出,仍会执行后续代码(如定义长度≤0 的数组),优化后直接return 1终止;
  3. 用户体验优化:输入提示、错误提示更清晰,输出格式统一(%10d替代%6d,适配更大的斐波那契数);
  4. 代码整洁度:删除冗余注释代码,逻辑分层更清晰(输入→校验→生成→输出)。

五、运行结果示例

示例 1:输入 n=8

plaintext

输入斐波那契数列项数:8
前8项斐波那契数列:
         1         1         2         3         5
         8        13        21

示例 2:输入 n=5

plaintext

输入斐波那契数列项数:5
前5项斐波那契数列:
         1         1         2         3         5

示例 3:输入 n=-3(非法输入)

plaintext

输入斐波那契数列项数:-3
错误:必须输入正整数!

六、扩展优化思路

1. 适配 C89 标准(无变长数组)

C89 不支持int a[n],可改用固定大小数组或动态内存分配:

c

运行

// 动态内存分配(最大支持100项)
int max_n = 100;
int *a = (int*)malloc(max_n * sizeof(int));
if(a == NULL) // 内存分配失败校验
{
    printf("内存分配失败!\n");
    return 1;
}
// 使用完释放内存
free(a);

2. 避免数组存储(节省内存)

无需存储所有项,仅用两个变量递推:

c

运行

int prev1=1, prev2=1, curr;
printf("%10d%10d", prev1, prev2); // 输出前两项
for(i=2; i<n; i++)
{
    curr = prev1 + prev2;
    printf("%10d", curr);
    if((i+1)%5==0) printf("\n");
    // 更新前两项
    prev1 = prev2;
    prev2 = curr;
}

七、新手避坑指南

  1. 数组越界:n=1 时,若直接赋值a[1]=1,会访问数组不存在的下标,必须加if(n>=2)判断;
  2. 格式化换行错误:换行判断用i+1而非i(i 从 0 开始,i+1 才是实际项数);
  3. 变长数组兼容性:部分老旧编译器不支持int a[n],需改用动态内存分配;
  4. 输出格式混乱:小宽度(如%6d)在斐波那契数变大后(如第 20 项 6765)会挤在一起,建议用%10d%12d