You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CS50 Credit:10位卡号4062901840未判定为INVALID的问题排查

CS50 Credit 问题集故障排查

问题现象

完成CS50 credit问题集开发后,测试发现卡号4062901840无法通过校验:运行check50检测时,输入该10位卡号按规则应输出Invalid,但程序实际无有效输出。
已使用20组其他10位卡号完成测试,均能正确判定为无效。代码仅采用课程已讲授的语法实现,未使用数组或额外类库,需定位问题根因。

原有程序逻辑

程序首先提示用户输入卡号,按Luhn算法做校验:

  • 从卡号倒数第二位开始,每隔一位数字乘以2,将所有乘积的各位数字相加求和;
  • 将上述和值与所有未乘2的数位之和相加;
  • 若总和末位为0(即总和模10余0),则通过Luhn校验;
  • 通过Luhn校验后,进一步判定卡组织类型,不满足规则则输出invalid。

卡组织判定规则:

  • American Express(15位):开头为34或37
  • Mastercard(16位):开头为51、52、53、54或55
  • Visa(13位或16位):开头为4

问题代码

#include <cs50.h>
#include <stdio.h>

int main(void)
{
    long cnum, cnumClone;
    int count, first, tempo, sum = 0;

    do{
        printf("Enter card number\n");
        scanf("%ld", &cnum);
    } while(cnum == 0);

    // 复制卡号用于遍历计算
    cnumClone = cnum;
    // 统计卡号位数
    for(count = 1; cnumClone != 0; count++)
    {
        // 取最后一位
        tempo = cnumClone % 10;
        // 移除最后一位
        cnumClone /= 10;
        // 选中需要乘2的数位
        if(count % 2 == 0)
        {
            tempo *= 2;
            // 处理乘积为两位数的情况
            if (tempo >=10)
            {
                tempo = tempo % 10;
                tempo += 1;
                sum += tempo;
            }else{
                sum += tempo;
            }
        }else{
            // 不需要乘2的数位直接累加
            sum += tempo;
        }
    }
    // Luhn算法最后一步校验
    if (sum % 10 == 0)
    {
        // 循环计数从1开始,实际位数需要减1
        count -= 1;
        // 16位卡号判断是Mastercard还是Visa
        if(count == 16)
        {
            first = cnum / 100000000000000;
            if(first == 51 || first== 52 || first == 53 || first == 54 || first == 55)
            {
                printf("MASTERCARD\n");
            }else{
                first = first /10;
                if(first == 4)
                {
                    printf("VISA\n");
                }else{
                    printf("INVALID\n");
                }
            }
        }
        // 15位卡号判断是否为Amex
        if(count == 15)
        {
            first = cnum / 10000000000000;
            if(first == 34 || first == 37)
            {
                printf("AMEX\n");
            }else{
                printf("INVALID\n");
            }
        }
        // 13位卡号判断是否为Visa
        if (count == 13)
        {
            first = cnum / 1000000000000;
            if(first == 4)
            {
                printf("VISA\n");
            }
        }
    }else{
        // Luhn校验不通过直接输出无效
        printf("INVALID\n");
    }
}

根因定位

卡号4062901840无输出是两个逻辑漏洞共同导致的:

  1. 手动计算该卡号的Luhn校验和,模10结果恰好为0,程序会进入Luhn校验通过的分支,不会触发外层else的INVALID输出。
  2. 进入校验通过分支后,代码仅覆盖了16位、15位、13位三种合法长度的判断逻辑,该卡号是10位,三个判断分支全部不命中,没有任何对应输出语句,因此程序运行后无有效输出。

代码还存在一个同类隐藏bug:13位长度的判断分支中,若卡号开头不是4,没有写INVALID输出逻辑,遇到符合Luhn规则、13位但开头非4的卡号时,同样会出现无输出问题。

修复方案

两处调整即可覆盖所有异常场景:

  1. 补全13位Visa判断分支的else逻辑,开头不符合4时输出INVALID
  2. 在三个长度判断的末尾加兜底逻辑:只要长度不属于13/15/16三种合法长度,直接输出INVALID

修改后的对应代码段:

// 13位Visa判断部分
if (count == 13)
{
    first = cnum / 1000000000000;
    if(first == 4)
    {
        printf("VISA\n");
    }
    else
    {
        printf("INVALID\n");
    }
}
// 新增兜底长度判断
if (count < 13 || count > 16)
{
    printf("INVALID\n");
}

修改后重新编译测试,4062901840会正常输出INVALID,其他边界场景的无输出问题也会被一并解决。


内容的提问来源于stack exchange,提问作者LaResistance

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 11:48:28