CS50第1周信用卡检测代码问题:无法识别有效卡种
CS50 2023第1周信用卡检测作业问题排查
在完成CS50 2023第1周信用卡检测作业时,代码可识别无效案例,但无法正确识别AMEX、MASTERCARD、VISA的有效测试用例,怀疑问题出在calculate_sum函数,附上代码及报错信息,请求排查。
代码实现
#include <cs50.h> #include <stdio.h> long get_card_number(void); int get_length(long cardno); int calculate_sum(long cardno); void printtype(int sum, int length_cardno, long cardno); int main(void) { long cardno = get_card_number(); // Get card number from user int length_cardno = get_length(cardno); // Calculate length of the card number int sum = calculate_sum(cardno); // To calculate total = sum_digit + alt_digit + last_digit printtype(sum, length_cardno, cardno); // To check what type of credit card it is, based on the different parameters } long get_card_number(void) // Function to get the card number from the user { long cardno; do { cardno = get_long("Number: "); } while(cardno < 0); return cardno; } int get_length(long cardno) // Function to get the length of the card and to get the length of altdigit*2 { int i; for(i = 0; cardno != 0; i++) { cardno = cardno/10; } return i; } int calculate_sum(long cardno) // Function to get sum of the digits { int alt_digit = 0; int alt_sum = 0; int digit = 0; int sum = 0; int total = 0; int last_digit = cardno % 10; cardno = cardno/10; // To get rid of the last digit bool Alternate_number = true; // To start with 2nd last digit while(cardno > 0) { if(Alternate_number == true) // Alt digits are the 2nd last digit, 4th last digit, 6th last digit and so on (even) { alt_digit = cardno % 10; alt_digit = alt_digit*2; if(alt_digit >= 10) // To add the first and second digits of the 2 digit alt product separately { int first_alt_digit = alt_digit/100; int second_alt_digit = alt_digit/10; alt_sum += first_alt_digit + second_alt_digit; } else { alt_sum += alt_digit; } cardno = cardno/10; } else // Digits are the 3rd last digit, 5th last digit, 7th last digit and so on (odd) { digit = cardno % 10; sum += digit; cardno = cardno/10; } Alternate_number = !Alternate_number; // To keep alternating } total = alt_sum + sum + last_digit; // Adding both of them together along with the last digit we removed at the start return total; } void printtype(int sum, int length_cardno, long cardno) // Function to know the type of card { int zero_or_not = sum % 10; // To only look at the unit's place to see if sum ends with 0 int first_digit = 0; int second_digit = 0; if(length_cardno == 13) // If statement to know the first two digits of the credit card number { first_digit = cardno/10^13; } else if(length_cardno == 15) { first_digit = cardno/10^15; second_digit = cardno/10^14; } else if(length_cardno == 16) { first_digit = cardno/10^16; second_digit = cardno/10^15; } if((length_cardno == 13 || length_cardno == 15 || length_cardno == 16) && (zero_or_not == 0)) // If statement to print the card type based on length, and the first and second digits { if((length_cardno == 15) && (first_digit == 3) && (second_digit == 4 || second_digit == 7)) { printf("AMEX\n"); } else if(length_cardno == 16 && (first_digit == 5) && (second_digit == 1 || second_digit == 2 || second_digit == 3 || second_digit == 4 || second_digit == 5)) { printf("MASTERCARD\n"); } else if((length_cardno == 13 || length_cardno == 16) && (first_digit == 4)) { printf("VISA\n"); } else { printf("INVALID\n"); } } else { printf("INVALID\n"); } }
测试报错信息
:( identifies 378282246310005 as AMEX expected "AMEX\n", not "INVALID\n" :( identifies 371449635398431 as AMEX expected "AMEX\n", not "INVALID\n" :( identifies 5555555555554444 as MASTERCARD expected "MASTERCARD\n", not "INVALID\n" :( identifies 5105105105105100 as MASTERCARD expected "MASTERCARD\n", not "INVALID\n" :( identifies 4111111111111111 as VISA expected "VISA\n", not "INVALID\n" :( identifies 4012888888881881 as VISA expected "VISA\n", not "INVALID\n" :( identifies 4222222222222 as VISA expected "VISA\n", not "INVALID\n"
已做修改
- 将first_digit改为first_alt_digit,second_digit改为second_alt_digit
- 补充alt_digit = first_alt_digit + second_alt_digit中的加号
- 移除检查alt_digit长度的函数,改用alt_digit >= 10判断
问题排查与修复
代码存在两处关键错误:
1. calculate_sum函数的数字拆分错误
当alt_digit是两位数时,原代码用alt_digit/100获取十位数字,这会得到0(因为两位数除以100结果为0),导致计算的和错误。正确的拆分方式应该是用alt_digit/10取十位,alt_digit%10取个位,两者相加。
修改后的calculate_sum对应代码块:
if(alt_digit >= 10) { alt_sum += (alt_digit / 10) + (alt_digit % 10); } else { alt_sum += alt_digit; }
2. printtype函数的首位数字获取错误
C语言中^是位异或运算符,不是幂运算符,原代码中cardno/10^13的计算逻辑完全错误,无法正确提取卡号的首位数字。正确的做法是先计算10的(卡号长度-1)次方作为除数,再用卡号除以该除数得到首位数字;第二位数字则用卡号除以(除数/10)后取模10。
修改后的printtype中获取首位数字的代码:
int zero_or_not = sum % 10; int first_digit = 0; int second_digit = 0; // 计算用于提取首位数字的除数 long divisor = 1; for (int i = 1; i < length_cardno; i++) { divisor *= 10; } first_digit = cardno / divisor; if (length_cardno >= 2) { second_digit = (cardno / (divisor / 10)) % 10; }
修复这两处错误后,即可正确识别所有有效信用卡测试用例。
内容的提问来源于stack exchange,提问作者King Brain
相关产品推荐
相关产品推荐

