CS50信用卡验证代码部分卡号无法运行问题求助
CS50信用卡验证代码问题排查与修复
你的代码存在多个导致部分卡号验证失败的问题,以下是具体问题和修复方案:
核心问题分析
1. 未声明变量引发的未定义行为
main函数中的valid、length、digits、digit_visa未声明,check_sum函数中的sec_to_last、double_sec_to_last、first_dig、sec_dig、first_sum、second_sum也未声明。这些未定义的变量会随机取值,直接导致校验逻辑混乱。
2. 参数类型不匹配
check_sum的参数是int类型,但传入的是long类型的卡号。当卡号数值超过int的范围(大于2147483647)时,会发生数值截断,导致校验完全错误。
3. Luhn校验算法逻辑错误
check_sum的第二个循环while (num2 >= 10)中,num2未做除法操作,会陷入无限循环;同时算法本身没有正确实现Luhn规则:未按要求从右往左交替处理数字,而是错误地截取两位数操作。
4. 数据类型范围不足
- 32位
long类型的最大值为2147483647,无法存储部分16位信用卡卡号(如4999999999999999),必须使用long long类型才能覆盖所有合法卡号。
5. 长度计算的浮点误差
- 使用
floor(log10(labs(num))) + 1计算卡号长度时,浮点运算可能存在精度误差,导致长度判断错误,改用循环计数更可靠。
修复后的完整代码
#include <stdio.h> #include <cs50.h> bool check_sum(long long num); int check_length(long long num); long long get_first_digits(long long num); long long get_cc_number(void); int main(void) { // 获取信用卡卡号 long long num = get_cc_number(); // 校验Luhn规则 bool valid = check_sum(num); // 获取卡号长度 int length = check_length(num); // 获取前两位数字(用于判断卡组织) long long digits = get_first_digits(num); int digit_visa = digits / 10; // 判断卡组织 if (valid) { if (length == 16) { if (digits >= 51 && digits <= 55) { printf("MASTERCARD\n"); } else if (digit_visa == 4) { printf("VISA\n"); } else { printf("INVALID\n"); } } else if (length == 15) { if (digits == 34 || digits == 37) { printf("AMEX\n"); } else { printf("INVALID\n"); } } else if (length == 13) { if (digit_visa == 4) { printf("VISA\n"); } else { printf("INVALID\n"); } } else { printf("INVALID\n"); } } else { printf("INVALID\n"); } } long long get_cc_number(void) { long long cc_number; cc_number = get_long("Credit Card Number: "); return cc_number; } bool check_sum(long long num) { int sum = 0; bool alternate = false; while (num > 0) { int digit = num % 10; // 从右往左交替乘以2 if (alternate) { digit *= 2; // 拆分两位数求和 sum += digit / 10 + digit % 10; } else { sum += digit; } alternate = !alternate; num /= 10; } return sum % 10 == 0; } int check_length(long long num) { int length = 0; while (num > 0) { length++; num /= 10; } return length; } long long get_first_digits(long long num) { while (num >= 100) { num /= 10; } return num; }
修复说明
- 所有涉及卡号的变量统一改为
long long类型,避免数值溢出; - 修正Luhn校验算法,按标准规则从右往左交替处理数字;
- 改用循环计数计算卡号长度,消除浮点误差;
- 补全所有变量声明,避免未定义行为;
- 调整
main函数中的分支逻辑,增加对非法长度的直接判断。
内容的提问来源于stack exchange,提问作者antoniomcoelho
相关产品推荐
相关产品推荐

