CS50 Pset1 Credit求助:分函数实现程序失效原因及正确方案
CS50 Pset1 Credit问题分函数实现故障排查与修复
代码失效原因分析
- Luhn算法逻辑完全错误:
- 第一个循环错误使用原始卡号
cn取模,而非当前迭代的ccn,导致累加的始终是卡号最后一位; - 第一个循环结束后
ccn已变为0,执行ccn = ccn/10后仍为0,处理乘2位的第二个循环根本不会执行; - checksum函数内部直接输出
INVALID,会与main函数中的输出重复。
- 第一个循环错误使用原始卡号
- 卡号长度计算死循环:
- 计算长度时用
ccn = ccn % 10,导致ccn始终等于卡号最后一位(非0时),循环无限执行。
- 计算长度时用
- 首位数字提取逻辑错误:
- 长度计算错误导致
divisor值错误,且ccn在长度计算后已被破坏,无法正确提取首位数字。
- 长度计算错误导致
- MasterCard校验条件错误:
- 条件
first_twodigit > 50 && first_twodigit == 56永远不成立,正确范围应为51-55。
- 条件
- VISA输出格式错误:
- 输出
VISA时缺少换行符,不符合题目要求。
- 输出
分函数实现的正确方案
将功能拆分为输入、校验、长度计算、首位提取等独立函数,每个函数职责单一:
#include <cs50.h> #include <stdio.h> // 函数声明 long get_credit_number(void); int calculate_checksum(long card_num); int get_card_length(long card_num); int get_first_two_digits(long card_num, int length); int get_first_digit(long card_num, int length); int main(void) { long card_num = get_credit_number(); // 先校验Luhn算法 if (!calculate_checksum(card_num)) { printf("INVALID\n"); return 0; } int length = get_card_length(card_num); int first_two = get_first_two_digits(card_num, length); int first = get_first_digit(card_num, length); // 判断卡类型 if (length == 15 && (first_two == 34 || first_two == 37)) { printf("AMEX\n"); } else if (length == 16 && (first_two >= 51 && first_two <= 55)) { printf("MASTERCARD\n"); } else if ((length == 13 || length == 16) && first == 4) { printf("VISA\n"); } else { printf("INVALID\n"); } return 0; } // 获取合法的信用卡号输入 long get_credit_number(void) { long num; do { num = get_long("Number: "); } while (num <= 0); return num; } // 实现Luhn算法校验 int calculate_checksum(long card_num) { int sum = 0; long temp = card_num; int is_second = 0; // 标记是否是从右数第二位(需要乘2的位) while (temp > 0) { int digit = temp % 10; if (is_second) { digit *= 2; sum += digit / 10 + digit % 10; } else { sum += digit; } is_second = !is_second; temp /= 10; } return (sum % 10 == 0); } // 计算卡号长度 int get_card_length(long card_num) { int length = 0; long temp = card_num; while (temp > 0) { length++; temp /= 10; } return length; } // 获取卡号前两位数字 int get_first_two_digits(long card_num, int length) { long divisor = 1; for (int i = 0; i < length - 2; i++) { divisor *= 10; } return card_num / divisor; } // 获取卡号第一位数字 int get_first_digit(long card_num, int length) { long divisor = 1; for (int i = 0; i < length - 1; i++) { divisor *= 10; } return card_num / divisor; }
代码说明
get_credit_number:负责获取用户输入,确保输入为正整数;calculate_checksum:正确实现Luhn算法,从右往左遍历每一位,交替处理乘2和直接累加的逻辑;get_card_length:通过不断除以10计算卡号位数;get_first_two_digits和get_first_digit:根据卡号长度计算除数,提取对应首位数字;- main函数仅负责调用各功能函数,判断最终卡类型,逻辑清晰。
内容的提问来源于stack exchange,提问作者smbhav
相关产品推荐
相关产品推荐

