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

CS50信用卡验证代码始终返回INVALID问题求助

CS50信用卡验证代码问题排查

我为CS50课程编写了信用卡验证代码,预期功能是判断输入卡号属于VISA、American Express、MasterCard中的一种,否则返回INVALID。代码采用Luhn算法进行卡号校验:

  • 从倒数第二位开始,每隔一位数字乘以2,再将乘积的各位数字相加;
  • 将上述结果与未乘2的数字之和相加;
  • 若总和末位为0(即总和模10等于0),则卡号有效。

我已验证校验和计算与位数统计均正确,例如测试卡号378282246310005(American Express)时,位数为15,总和为60,满足校验条件,但输入所有测试卡号(含VISA、MasterCard的有效卡号)均返回INVALID。作为编程新手,恳请协助排查问题。

我的代码如下:

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

int main(void) 
{ 
    long ccn;

    do 
    {
        ccn = get_long("Credit Card Number: ");
    }
    while (ccn < 0);

    int totalsum = 0;
    int digit = 0;
    while (ccn > 0)
    {
        if (digit % 2 == 1)
        {
            int ccn2 = ccn % 10 * 2;
            totalsum += (ccn2 % 10) + (ccn2 / 10);
        }
        else if (digit % 2 == 0)
        {
            totalsum += ccn % 10;
        }
        ccn /= 10;
        digit++;
    }

    if ((totalsum % 10) != 0)
    {
        printf("%s\n", "INVALID");
        return 0;
    }

    long visa = ccn;
    long americanexpress = ccn;
    long mastercard = ccn;

    while (americanexpress >= 10000000000000) 
    {
        americanexpress /= 10000000000000;
    }
    if (digit == 15 && (americanexpress == 34 || americanexpress == 37))
    {
        printf("%s\n", "AMEX");
        return 0;
    }

    while (mastercard >= 100000000000000)
    {
        mastercard /= 100000000000000;
    }
    if (digit == 16 && (mastercard >= 51 && mastercard <= 55))
    {
        printf("%s\n", "MASTERCARD");
        return 0;
    }

    while (visa > 10)
    {
        visa /= 10;
    }
    if (visa == 4 && (digit == 13 || digit == 16))
    { 
        printf("%s\n", "VISA");
        return 0;
    }
    else
    {
        printf("%s\n", "INVALID");
    }
    return 0;
}

问题根源

核心错误是Luhn校验的循环把原始卡号变量ccn修改成0了:在计算校验和的while (ccn > 0)循环里,每次都会执行ccn /= 10,直到ccn变为0。后续用来判断卡组织的visa、americanexpress、mastercard都是用ccn赋值的,所以它们的值全是0,根本无法匹配任何卡组织的前缀规则,最终只能返回INVALID。

修复方案

在进入Luhn校验循环前,先保存原始卡号的副本,后续判断卡组织时使用这个副本:

修改后的完整代码

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

int main(void) 
{ 
    long ccn;
    long original_ccn; // 保存原始卡号的变量

    do 
    {
        ccn = get_long("Credit Card Number: ");
        original_ccn = ccn; // 复制原始卡号
    }
    while (ccn < 0);

    int totalsum = 0;
    int digit = 0;
    while (ccn > 0)
    {
        if (digit % 2 == 1)
        {
            int ccn2 = ccn % 10 * 2;
            totalsum += (ccn2 % 10) + (ccn2 / 10);
        }
        else
        {
            totalsum += ccn % 10;
        }
        ccn /= 10;
        digit++;
    }

    if ((totalsum % 10) != 0)
    {
        printf("%s\n", "INVALID");
        return 0;
    }

    long americanexpress = original_ccn;
    while (americanexpress >= 10000000000000) 
    {
        americanexpress /= 10000000000000;
    }
    if (digit == 15 && (americanexpress == 34 || americanexpress == 37))
    {
        printf("%s\n", "AMEX");
        return 0;
    }

    long mastercard = original_ccn;
    while (mastercard >= 100000000000000)
    {
        mastercard /= 100000000000000;
    }
    if (digit == 16 && (mastercard >= 51 && mastercard <= 55))
    {
        printf("%s\n", "MASTERCARD");
        return 0;
    }

    long visa = original_ccn;
    while (visa > 10)
    {
        visa /= 10;
    }
    if (visa == 4 && (digit == 13 || digit == 16))
    { 
        printf("%s\n", "VISA");
        return 0;
    }

    printf("%s\n", "INVALID");
    return 0;
}

额外优化点

  • 去掉了冗余的else if (digit % 2 == 0),直接用else即可,因为digit要么是奇数要么是偶数;
  • 最后统一输出INVALID,避免else分支嵌套。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 03:09:53