为何checkCS50判定我的pset1 credit代码未完全通过测试?
CS50 Pset1 Credit作业验证异常问题
我的Credit作业代码部分信用卡号码验证符合预期,但部分未通过checkCS50检测,被判定为INVALID而非正确卡种,具体检测结果如下:
:) credit.c exists :) credit.c compiles :( 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 :( identifies 4012888888881881 as VISA expected "VISA\n", not "INVALID\n" :) identifies 4222222222222 as VISA :) identifies 1234567890 as INVALID (invalid length, checksum, identifying digits) :) identifies 369421438430814 as INVALID (invalid identifying digits) :) identifies 4062901840 as INVALID (invalid length) :) identifies 5673598276138003 as INVALID (invalid identifying digits) :) identifies 4111111111111113 as INVALID (invalid checksum) :) identifies 4222222222223 as INVALID (invalid checksum) :) identifies 3400000000000620 as INVALID (AMEX identifying digits, VISA/Mastercard length) :) identifies 430000000000000 as INVALID (VISA identifying digits, AMEX length)
我的代码如下:
#include <cs50.h> #include <stdio.h> #include <string.h> int main(void) { long creditLong = get_long("What is your credit card number? "); // Get the number char creditArray[20]; // Convert to array snprintf(creditArray, sizeof(creditArray), "%ld", creditLong); long creditLength = strlen(creditArray); // Get length // printf("creditLength is %ld\n", creditLength); int sumFirst = 0; // Checksum variables int sumSecond = 0; for (int i = creditLength - 2; i >= 0; i -= 2) { // For loops to get sum int digit = creditArray[i] - '0'; // ASCII to Int value ('0' = 48 in ASCII) sumFirst += digit * 2; } for (int j = creditLength - 1; j >= 0; j -= 2) { int digit = creditArray[j] - '0'; sumSecond += digit; } int checkSum = sumFirst + sumSecond; char luhnTest[10]; // Convert to array snprintf(luhnTest, sizeof(luhnTest), "%d", checkSum); int testLength = strlen(luhnTest); // Get length of card number if (luhnTest[testLength - 1] == '0') { // Start of If Statement switch (creditLength) { case 15: if (creditArray[0] == '3' && (creditArray[1] == '4' || creditArray[1] == '7')) { printf("AMEX\n"); } else { printf("INVALID\n"); } break; case 13: if (creditArray[0] == '4') { printf("VISA\n"); } else { printf("INVALID\n"); } break; case 16: if (creditArray[0] == '4') { printf("VISA\n"); } else if (creditArray[0] == '5' && (creditArray[1] == '1' || creditArray[1] == '2' || creditArray[1] == '3' || creditArray[1] == '4' || creditArray[1] == '5')) { printf("MASTERCARD\n"); } else { printf("INVALID\n"); } break; default: printf("INVALID\n"); } } // End of IF Statement else { printf("INVALID\n"); } }
问题原因
核心错误出在Luhn算法的实现上:按照规则,需要将从右数第二位开始的数字乘2,然后把乘积的每一位数字相加,而非直接将乘积本身加入sumFirst。比如数字8乘2得16,应该加1+6=7,而代码里直接加了16,导致checksum计算错误,最终这些测试用例的Luhn验证不通过,返回INVALID。
修正后的代码
将sumFirst的计算逻辑修改为拆分乘积的各位数字相加,同时优化了checksum的验证方式:
#include <cs50.h> #include <stdio.h> #include <string.h> int main(void) { long creditLong = get_long("What is your credit card number? "); char creditArray[20]; snprintf(creditArray, sizeof(creditArray), "%ld", creditLong); long creditLength = strlen(creditArray); int sumFirst = 0; int sumSecond = 0; for (int i = creditLength - 2; i >= 0; i -= 2) { int digit = creditArray[i] - '0'; int product = digit * 2; // 拆分乘积的各位数字相加 sumFirst += (product / 10) + (product % 10); } for (int j = creditLength - 1; j >= 0; j -= 2) { int digit = creditArray[j] - '0'; sumSecond += digit; } int checkSum = sumFirst + sumSecond; // 直接判断checkSum是否能被10整除,无需转字符串 if (checkSum % 10 == 0) { switch (creditLength) { case 15: if (creditArray[0] == '3' && (creditArray[1] == '4' || creditArray[1] == '7')) { printf("AMEX\n"); } else { printf("INVALID\n"); } break; case 13: if (creditArray[0] == '4') { printf("VISA\n"); } else { printf("INVALID\n"); } break; case 16: if (creditArray[0] == '4') { printf("VISA\n"); } else if (creditArray[0] == '5' && (creditArray[1] >= '1' && creditArray[1] <= '5')) { printf("MASTERCARD\n"); } else { printf("INVALID\n"); } break; default: printf("INVALID\n"); } } else { printf("INVALID\n"); } }
内容的提问来源于stack exchange,提问作者Joseph F
相关产品推荐
相关产品推荐

