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
相关产品推荐
相关产品推荐

