checksc50 说我的代码在 pset1 信用中没有 100% 工作是有原因的吗?

Is there a reason checksc50 is saying my code isn't working 100% in pset1 credit?

提问人:Joseph F 提问时间:11/17/2023 最后编辑:Craig EsteyJoseph F 更新时间:11/17/2023 访问量:66

问:

因此,出于某种原因,有些信用卡号按预期工作,有些则没有(至少在 CS50 的眼中)对我来说一切看起来都很好。checkCS50 是这样说的:

:) 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");
}
}
c 计算机科学 CS50

评论

3赞 Retired Ninja 11/17/2023
是的,这是有原因的。你的代码中有错误。好消息是,您确切地知道失败的原因,因为它向您展示了测试用例。从中找出什么不起作用应该不会太难。
1赞 Barmar 11/17/2023
不要将信用卡号读取为数字。只需将其直接读取为字符串即可。
1赞 Barmar 11/17/2023
你的 Luhn 算法显然是错误的。对于第一个失败的数字,它计算的是 69。
1赞 Joseph F 11/17/2023
@RetiredNinja你是对的!如果说其中一个产品是 14,我需要添加 1 + 4......谢谢!!我的问题是误读了算法,而不是实现。不过,我会将输入更改为字符串,以使代码更简洁且语义正确
1赞 Weather Vane 11/17/2023
@JosephF你怎么知道呢?您可能会错误地使用不是前导数字的卡片类型数字。卡和电话“数字”不是整数。它们是数字字符串。

答:

0赞 NoDakker 12/16/2023 #1

我没有仔细阅读所有评论,但您问题的要点在于计算偶数的哈希总量。

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;
}

如果您通读 Luhn 算法的方法,您会注意到,如果被加倍的数字的乘积大于“9”,则应该从双倍数字中减去“9”的值。

仅供参考,以下是维基百科对该算法的讨论的链接。

“https://en.wikipedia.org/wiki/Luhn_algorithm”

接下来是重构的代码块。

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)
    if (digit > 4)                      /* As per the Luhn algorithm specs  */
        sumFirst += (digit * 2 - 9);
    else
        sumFirst += digit * 2;
}

通过一些重构,以下是对一些示例的测试。

craig@Vera:~/C_Programs/Console/CheckLuhn/bin/Release$ ./CheckLuhn 
What is your credit card number? 378282246310005
AMEX
craig@Vera:~/C_Programs/Console/CheckLuhn/bin/Release$ ./CheckLuhn 
What is your credit card number? 5555555555554444
MASTERCARD
craig@Vera:~/C_Programs/Console/CheckLuhn/bin/Release$ ./CheckLuhn 
What is your credit card number? 4012888888881881
VISA

您的校验和算法没有正确处理任何“5”或更高数字的条件倍增过程,这就是为什么许多测试错误地失败的原因,但“4111111111111111”示例通过,因为所有数字都是“4”或更少。

这里的要点是,在构建代码时要彻底审查测试算法,以便代码与测试一致。