需要反馈:信用 (Pset1- CS50x)

Need Feedback : Credit (Pset1- CS50x)

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

int main(void) {
    long int number;
    int count = 0;  // starting the count counter
    do {
        number = get_long("Please enter your 13-16 digit credit card number: \n"); //getting input from the user
    } while (number <= 0);

    int d1 = number % 10;                                           //separating digit number 1
    int d2 = ((number % 100) / 10);                                 //separating digit number 2
    int d3 = ((number % 1000) / 100);                               //separating digit number 3
    int d4 = ((number % 10000) / 1000);                             //separating digit number 4
    int d5 = ((number % 100000) / 10000);                           //separating digit number 5
    int d6 = ((number % 1000000) / 100000);                         //separating digit number 6
    int d7 = ((number % 10000000) / 1000000);                       //separating digit number 7
    int d8 = ((number % 100000000) / 10000000);                     //separating digit number 8
    int d9 = ((number % 1000000000) / 100000000);                   //separating digit number 9
    int d10 = ((number % 10000000000) / 1000000000);                //separating digit number 10
    int d11 = ((number % 100000000000) / 10000000000);              //separating digit number 11
    int d12 = ((number % 1000000000000) / 100000000000);            //separating digit number 12
    int d13 = ((number % 10000000000000) / 1000000000000);          //separating digit number 13
    int d14 = ((number % 100000000000000) / 10000000000000);        //separating digit number 14
    int d15 = ((number % 1000000000000000) / 100000000000000);      //separating digit number 15
    int d16 = ((number % 10000000000000000) / 1000000000000000);    //separating digit number 16
    int last13 = number / 1000000000000;        //finding the last one digit of 13 digit VISA
    int last15 = number / 10000000000000;       //finding the last two digit of 15 digit AMEX
    int last16v = number / 1000000000000000;    //finding the last one digit of 16 digit VISA
    int last16m = number / 100000000000000;     //finding the last two digit of 16 digit MASTERCARD
    int a2 = (d2 * 2);
    int a4 = (d4 * 2);
    int a6 = (d6 * 2);
    int a8 = (d8 * 2);
    int a10 = (d10 * 2);
    int a12 = (d12 * 2);
    int a14 = (d14 * 2);
    int a16 = (d16 * 2);
    if (a2 >= 10) {             // separating the digits of the multiple
        int a11a = (a2 % 100) / 10;
        int a12a = (a2 % 10);
        a2 = a11a + a12a;
    }
    if (a4 >= 10) {           // separating the digits of the multiple
        int a31 = (a4 % 100)  / 10;
        int a32 = (a4 % 10);
        a4 = a31 + a32;
    }
    if (a6 >= 10) {             // separating the digits of the multiple
        int a51 = (a6 % 100) / 10;
        int a52 = (a6 % 10);
        a6 = a51 + a52;
    }
    if (a8 >= 10) {              // separating the digits of the multiple
        int a71 = (a8 % 100) / 10;
        int a72 = (a8 % 10);
        a8 = a71 + a72;
    }
    if (a10 >= 10) {        // separating the digits of the multiple
        int a91 = (a10 % 100) / 10;
        int a92 = (a10 % 10);
        a10 = a91 + a92;
    }
    if (a12 >= 10) {              // separating the digits of the multiple
        int a111 = (a12 % 100) / 10;
        int a112 = (a12 % 10);
        a12 = a111 + a112;
    }
    if (a14 >= 10) {               // separating the digits of the multiple
        int a131 = (a14 % 100) / 10;
        int a132 = (a14 % 10);
        a14 = a131 + a132;
    }
    if (a16 >= 10) {              // separating the digits of the multiple
        int a151 = (a16 % 100) / 10;
        int a152 = (a16 % 10);
        a16 = a151 + a152;
    }
    int b = d1 + d3 + d5 + d7 + d9 + d11 + d13 + d15;
    int c = a2 + a4 + a6 + a8 + a10 + a12 + a14 + a16;
    int l = b + c;
    int j = a2 + a4 + a6 + a8 + a10 + a12;
    int k =  d1 + d3 + d5 + d7 + d9 + d11 + d13;
    int m = j + k;
    int e = d1 + d3 + d5 + d7 + d9 + d11 + d13 + d15;
    int x = a2 + a4 + a6 + a8 + a10 + a12 + a14;
    int n = x + e;
    printf("%i", n);
    if (l % 10 == 0) {                     //checking if the checksum is valid
        for (int i = number; number != 0; i++) {   // counting the credit card number
            number /= 10;
            count++;
        }
        if (count == 16) {
            if (last16m == 51) {             // checking the last two digit of credit card
                printf("MASTERCARD\n");   // printing the result based on last two digits
            } else
            if (last16m == 52) {       // checking the last two digit of credit card
                printf("MASTERCARD\n");   // printing the result based on last two digits
            } else
            if (last16m == 53) {        // checking the last two digit of credit card
                printf("MASTERCARD\n");     // printing the result based on last two digits
            } else
            if (last16m == 54) {            // checking the last two digit of credit card
                printf("MASTERCARD\n");          //// printing the result based on last two digits
            } else
            if (last16m == 55) {               // checking the last two digit of credit card
                printf("MASTERCARD\n");         // printing the result based on last two digits
            } else
            if (last16v == 4) {                // checking the last two digit of credit card
                printf("VISA\n");              // printing the result based on last two digits
            } else {
                printf("INVALID\n");
            }
            if (count != 16) {
                printf("INVALID\n");
            }
        } else {
            printf("INVALID\n");
        }
    }

    if (m % 10 == 0) {                    //checking if the checksum is valid
        for (int i = number; number != 0; i++) {       // counting the credit card number
            number /= 10;
            count++;
        }
        if (count == 13) {
            if (last13 == 4) {   // checking the last one digit of credit card
                printf("VISA\n");       // printing the result based on last one digit
            } else {
                printf("INVALID\n");
            }
        } else {
            printf("INVALID\n");
        }
    }
    if (n % 10 == 0) {                  //checking if the checksum is valid
        for (int i = number; number != 0; i++) {        // counting the credit card number
            number /= 10;
            count++;
        }

        if (count == 15) {
            if (last15 == 34) {     // checking the last two digit of credit card
                printf("AMEX\n");         // printing the result based on last two digits
            } else
            if (last15 == 37) {      // checking the last two digit of credit card
                printf("AMEX\n");        // printing the result based on last two digits
            } else {
                printf("INVALID\n");
            }

            if (count != 15) {
                printf("INVALID\n");
            }
        } else {
            printf("INVALID\n");
        }
    }
}

我尝试使用 4003600000000014,它给出了正确的输出。取 4222222222222,它 returns INVALID。它也不适用于 AMEX 号码(15 位数字)。它不会响应 4111111111111113 作为输入(它应该 return 0)。请告诉我出了什么问题,我是编程新手。这是它通过 check50 https://submit.cs50.io/check50/44370b403c33f9b47d462e3278458901599d16e1.

检查时给出的结果

代码中存在多个问题:

  • number 的类型应该是 unsigned long long 以确保它足够大以处理 16 位数字。 unsigned long 在某些平台上可能足够大,例如 64 位 linux 和 OS/X,但在其他平台上则不够大,例如 Windows.

    的所有版本
  • 计算冗长繁琐,使用数字值数组可读性更好

  • 不清楚您是计算 count 一次还是多次。循环修改 number 并且没有显式初始化 count (并且变量 i 没有用)。如果 运行 多次,它会巧合地工作,因为 number 从第一个 运行 开始已经是 0。您应该使用具有正确类型的临时变量并只计算一次 count

  • 不同卡号长度的测试可能会出现误报:例如如果m % 10 == 0且卡号不是13位数字,您将打印错误INVALID。测试应该首先是位数,然后是校验和。

  • 将初始数字称为最后数字是非常令人困惑的。

这是一个使用数组的更简单的版本:

#include <stdio.h>
#include <stdlib.h>

// emulate cs50 get_long_long()
static long long get_long_long(const char *prompt) {
    for (;;) {
        long long n;
        int c;

        printf("%s", prompt);
        if (scanf("%llu", &n) == 1)
            return n;
        printf("Invalid input, try again\n");
        // flush the rest of the input line
        while ((c = getchar()) != EOF && c != '\n')
            continue;
        if (c == EOF)
            exit(1);
    }
}

int main(void) {
    long long int number, num;
    int digit[16] = { 0 };
    int count;
    for (;;) {        //getting input from the user
        number = get_long_long("Please enter your 13-16 digit credit card number: \n");
        if (number > 0)
            break;
    }
    // only accept numbers with 13 to 16 digits
    if (number < 1000000000000 || number > 9999999999999999) {
        printf("INVALID\n");
        return 1;
    }
    for (count = 0, num = number; num != 0; count++) {
        digit[count] = num % 10;
        num = num / 10;
    }
    // compute checksum
    int checksum = 0;
    for (int i = 0; i < 16; i += 2) {
        int a1 = digit[i];
        int a2 = digit[i + 1] * 2;
        if (a2 >= 10)
            a2 -= 9;
        checksum += a1 + a2;
    }        
    //printf("checksum: %d, ", checksum);

    int first = digit[count - 1];
    int first2 = 10 * digit[count - 1] + digit[count - 2];

    if (checksum % 10 == 0) {
        if (count == 16) {
            if (first2 >= 51 && first2 <= 55) {
                printf("MASTERCARD\n");
                return 0;
            } else
            if (first == 4) {
                printf("VISA\n");
                return 0;
            }
        } else
        if (count == 13) {
            if (first == 4) {
                printf("VISA\n");
                return 0;
            }
        } else
        if (count == 15) {
            if (first2 == 34 || first2 == 37) {
                printf("AMEX\n");
                return 0;
            }
        }
    }
    printf("INVALID\n");
    return 1;
}