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:使用字符串处理(更通用)
把信用卡号作为字符串输入,逐字符解析数字,彻底避免整数溢出问题,也适合含前导零的卡号场景:
- 用
get_string读取卡号字符串 - 遍历字符串计算长度和校验和
- 提取前1/2位判断卡类型
验证方法
若本地用GCC编译,可添加-m64强制64位编译:
gcc -m64 credit.c -o credit cs50.c
内容的提问来源于stack exchange,提问作者joyceljx
相关产品推荐
相关产品推荐

