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

C编程(CS50):本地机器中long类型无法处理信用卡号的问题咨询

问题原因与解决办法

核心问题:long类型的平台位数差异

CS50 Codespace基于64位Linux环境,long类型占8字节(64位),能存储的最大值为9223372036854775807(约9e18),完全容纳16位信用卡号。但你的本地机器大概率是Windows环境,使用的编译器(如MSVC)中long仅为4字节(32位),最大值仅为2147483647(10位数字)。当输入超过10位的信用卡号时,long会溢出,导致get_long返回错误值(如-1),触发你的do-while循环(因card < 0),所以会持续提示输入。

其他可能原因

  • 本地CS50库版本不一致:确保本地安装的CS50库支持正确的输入处理,但核心问题还是类型位数限制。
  • 编译器参数问题:若本地用GCC,未指定64位编译选项(如-m64),可能导致long被当作32位处理。

解决方案

方案1:改用long long类型

long long是标准64位整数类型,在所有主流平台(32/64位)都能存储到9e18,完全覆盖信用卡号长度。修改后的代码如下:

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

// gcc credit.c -o credit cs50.c
// .\credit

int main(void)
{
    /* GET CARD NUMBER > 0 */
    long long card;
    do
    {
        card = get_long_long("Enter card number: ");
    }
    while (card < 0);

    /* COUNT LENGTH */
    long long cardlength = card;
    int count = 0;
    while (cardlength > 1)
    {
        cardlength = cardlength / 10;
        count++;
    }

    /* CALCULATE CHECKSUM */
    long long cardnumber = card;
    int singlesum = 0;
    int doubledsum = 0;
    int last = 0;
    int last2nd = 0;
    int last2ndL = 0;
    int last2ndR = 0;
    int totalsum = 0;

    while (cardnumber > 0)
    {
        // 取最后一位加入单数字和
        last = cardnumber % 10;
        cardnumber /= 10;
        singlesum += last;

        // 若剩余数字为空,退出循环(处理奇数位数的卡号)
        if (cardnumber == 0) break;

        // 取倒数第二位翻倍后拆分数字加入双数字和
        last2nd = (cardnumber % 10) * 2;
        cardnumber /= 10;
        last2ndR = last2nd % 10;
        last2ndL = last2nd / 10;
        doubledsum += last2ndR + last2ndL;
    }

    totalsum = singlesum + doubledsum;

    /* 校验Luhn算法 */
    if (totalsum % 10 != 0)
    {
        printf("INVALID\n");
        return 0;
    }

    /* 获取前两位数字 */
    long long firsttwo = card;
    while (firsttwo > 100)
    {
        firsttwo = firsttwo / 10;
    }

    /* 判断卡类型 */
    if ((firsttwo / 10 == 3) && (firsttwo % 10 == 4 || firsttwo % 10 == 7) && (count == 15))
    {
        printf("AMEX\n");
    }
    else if ((firsttwo / 10 == 5) && (firsttwo % 10 > 0 && firsttwo % 10 < 6) && (count == 16))
    {
        printf("MASTERCARD\n");
    }
    else if ((firsttwo / 10 == 4) && (count == 16 || count == 13))
    {
        printf("VISA\n");
    }
    else
    {
        printf("INVALID\n");
    }

    return 0;
}

// amex = 15 digits, start with 34 or 37
// mastercard = 16 digits, start with 51, 52, 53, 54, 55
// visa = 13 or 16 digits, starts with 4

关键修改点:

  • 所有long替换为long long
  • 用get_long_long替代get_long读取输入
  • 增加判断if (cardnumber == 0) break;避免奇数位数卡号的错误计算

方案2:使用字符串处理(更通用)

把信用卡号作为字符串输入,逐字符解析数字,彻底避免整数溢出问题,也适合含前导零的卡号场景:

  1. 用get_string读取卡号字符串
  2. 遍历字符串计算长度和校验和
  3. 提取前1/2位判断卡类型

验证方法

若本地用GCC编译,可添加-m64强制64位编译:

gcc -m64 credit.c -o credit cs50.c

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 21:47:06