CS50 pset1 校验和计算中的信用错误

CS50 pset1 Credit error in checksum calculation

这是我第一次 post 在这里,所以如果我有任何错误请告诉我。我试图在这里找到我的问题的答案,但找不到合适的答案。

所以我的代码中有一个关于 CS50x 第 1 周 'Credit' 问题集的问题。 在问题集中,用户必须输入我们必须验证为 VISA、MASTERCARD 或 AMEX 的信用卡号码。否则输出应该是无效的。

验证应该像这样工作:

4 0 0 3 6 0 0 0 0 0 0 0 0 0 1 4

从倒数第二个数字(粗体数字)开始,每隔一个数字乘以 2 并相加。 但是,如果相乘的数字有 2 位数字,则将这两位数字分别相加,如:

2 * 6 = 12 so twelve will be 1 + 2

之后你取另一半数字(不相乘)并将它们加在一起所以最后你得到类似

的东西

8 + 0 + 1 + 2 + 0 + 0 + 0 + 0 + 2 = 13 (for the digits displayed in bold)

0 + 3 + 0 + 0 + 0 + 0 + 0 + 4 = 7 (for the other half of the digits)

将两者相加得到 20(在问题集中称为 校验和。如果计算的最后一位号码是 0 该卡是有效的,之后你只需要检查一些条件来判断它是 AMEX、VISA 还是 MASTERCARD。

不同信用卡的条件:

American Express = 15 Digits, starting with 34 or 37

VISA = 13 or 16 Digits, starting with 4

MasterCard = 16 Digits, starting with 51, 52, 53, 54 or 55

(抱歉介绍太长)

我试图为这个计算制定一个公式,但出于某种原因,它不适用于我们测试它的所有数字。我尝试了很多方法来更改代码末尾的计算和条件,但每次我解决一个问题时,都会出现另一个问题,现在感觉就像我以为自己掉进了一个兔子洞,所以也许我太盲目了看到显而易见的东西。

到目前为止,我们只使用库 - -

    long checkcredit = store;
    int sum1 = 0;
    int sum2;
    for (int duo = 0; checkcredit > 0; duo++, checkcredit /= 10)
    {
        if (duo % 2 == 0)
        {
            sum1 += (checkcredit % 10);
        }
        else
        {
            sum2 = (checkcredit % 10) * 2;
            if (sum2 >10)
            {
                sum2 = (checkcredit % 10) + 1;
            }
        }
    }
    sum1 +=sum2;
    sum1 = sum1 % 10;

这是我认为问题所在的部分,因为我打印了 sum1(长数字的计算验证数),有时输出错误。

store is the original value of the creditcard number (for example 4003600000000014)

checkcredit is just a duplication of store to work with without changing the original store value

sum1 is for the number is displayed in bold (the once that get multiplied by 2 before adding)

sum2 is for the other half of the number

duo is a digit counter for the calculation to see if i the current digit is multiplied or not (thanks to a coworker of mine who gave the hint that i could try it that way, my old version was like 4 times longer

最后我只是将 sum1sum2 加在一起得到 "Checksum"

没有任何编译器错误,只有 Check50 输出

Results for cs50/problems/2021/x/credit generated by check50 v3.2.2

:) 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 expected "VISA\n", not "INVALID\n"

:( identifies 4012888888881881 as VISA expected "VISA\n", not "INVALID\n"

:) identifies 4222222222222 as VISA

:) identifies 1234567890 as INVALID

:) identifies 369421438430814 as INVALID

:) identifies 4062901840 as INVALID

:) identifies 5673598276138003 as INVALID

:) identifies 4111111111111113 as INVALID

:) identifies 4222222222223 as INVALID

就像我说的,我认为我犯的错误是在这部分代码中(我什至认为它与 for 循环中的条件有关)但是我不知道那里出了什么问题。

以防万一整个代码在这里:

#include<cs50.h>
#include<stdio.h>
#include<math.h>

int main(void)
{
    //Ask user for credit card number
    long store;
    do
    {
        store = get_long("Number: ");
    }
    while (store < 0);

    //calculating the amount of digits 
    long cnumber = store;
    int digits;

    for (digits = 0 ; cnumber > 0 ; digits++)
    {
        cnumber/=10;
    }

    //calculating the checksum
    long checkcredit = store;
    int sum1 = 0;
    int sum2;
    for (int duo = 0; checkcredit > 0; duo++, checkcredit /= 10)
    {
        if (duo % 2 == 0)
        {
            sum1 += (checkcredit % 10);
        }
        else
        {
            sum2 = (checkcredit % 10) * 2;
            if (sum2 >10)
            {
                sum2 = (checkcredit % 10) + 1;
            }
            //sum1 += sum2;
        }
    }
    sum1 +=sum2;
    //printf("%i ", sum1);
    sum1 = sum1 % 10;

    //conditions for varification of the card
    if (sum1 == 0)
    {
        if (digits != 13 && digits != 15 && digits != 16)
        {
            printf("INVALID\n");
        }
        else if (digits == 16 || digits == 13)
        {
            if (digits == 16 && (store >= 51e14 && store <56e14))
            {
                printf("MASTERCARD\n");
            }
            else if ((digits == 13 || digits == 16) && ((store <= 4e13 && store < 5e13)||(store >= 4e15 && store < 5e15)))
            {
                printf("VISA\n");
            }
            else
            {
                printf("INVALID\n");
            }
        }    
        else if (digits == 15)
        {
            if((store >= 34e13 && store < 35e13)||(store >= 37e13 && store < 38e13))
            {
                printf("AMEX\n");
            }
            else
            {
                printf("INVALID\n");
            }
        }
    }
    else
    {
        printf("INVALID\n");
    }
}

请忽略最后的条件部分,我只是一起制作原型来检查它是否有效(如果我忽略校验和条件它会起作用)

很抱歉拖了这么久post,我真的很感谢所有花时间看这篇文章并帮助初学者从错误中吸取教训的人。

-Wannabree

sum2的处理是错误的,它没有总结什么,而是每次都覆盖sum2。一种可能的补救措施是初始化 int sum2 = 0; 并更改

        {
            sum2 = (checkcredit % 10) * 2;
            if (sum2 >10)
            {
                sum2 = (checkcredit % 10) + 1;
            }
        }

            sum2 += "[=11=]\x8\x9"[checkcredit % 10];