用C编写一个程序来应用Luhn算法进行信用卡验证

时间:2016-10-12 18:36:53

标签: c algorithm cs50 luhn

我对C(以及所有形式的编程......)完全陌生,并且今年遵循CS50课程。我正在编写一个使用Luhn算法测试信用卡号有效性的简单程序。

我需要我的程序提示用户输入并在输入不符合信用卡格式的情况下重新提示(例如:负数或字母等...)然后应用算法查看如果该号码是有效的信用卡号码,如果是,则是Visa,MasterCard还是AmEx。

我知道这个问题已经在这个网站上用不同的代码回答了,我发誓我读了一些我可能找到的东西(在这个网站和网上的其他地方),但我很难理解C语法,我想尝试自己提出一些东西,而不是从其他答案中复制我不理解的代码。如果有人可以帮助我,看看到目前为止我做了什么,告诉我我做错了什么,我真的很感激。此外,任何可以帮助我更好地理解C语法逻辑的提示都将非常受欢迎,同样,我是一个完全和完全新手(在自定进度的基础上学习编程3周......)。

我的程序正在编译,但是当我运行它时,它以一种非常奇怪的方式表现:当我输入输入时,它会说它无效(即使它是有效的数字),有时它也不会返回任何东西在我按下回车键后,无论多少次按下返回键,都不会停止运行。

到目前为止,这是我的代码:

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

int main(void)
{
    printf("Please give me your credit card number:\n") ;

    long long card_num ;

    do
    {
        card_num = GetLongLong() ;
    }
    while (card_num < 1 || card_num > 9999999999999999) ;

    // Make a copy of the card number to be used and modified throughout the process.

    long long temp_num = card_num ;
    int digit = 0 ;
    int count = 0 ;
    int sum_a = 0 ;
    int sum_b = 0 ;

    // Isolate every digit from the credit card number using a loop and the variable 'digit'.
    // Keep track of the amount and position of each digit using variable 'count'.

    while (card_num >= 0)
    {
        digit = card_num % 10 ;
        count++ ;
        temp_num = (card_num - digit) / 10 ;
        break ;


     // Apply Luhn's algorithm using two different 'for' loops depending on the position of each digit.

        for (count = 0 ; count % 2 == 0 ; count++)
        {
            sum_a = sum_a + ((card_num % 10) * 2) ;

            while ((card_num % 10) * 2 >= 10)
            {
                sum_a = (sum_a % 10) + 1 ;
            } 
        }

        for (count = 0 ; count % 2 != 0 ; count++)
        {
            sum_b = sum_b + digit ;
        }

        return sum_a ;
        return sum_b ;
        return count ;
    }

    // Checking the validity of the number according to Luhn's algorithm

    int total_sum = sum_a + sum_b ;

    if (total_sum % 10 != 0)
    {
       printf("This is an invalid number.\n") ; 
    }

// If the number entered doesn't have the right amount of digits according
// to variable 'count', declare the number as invalid.

    if (count != 13 || count != 15 || count != 16)
    {
        printf("This is an invalid number.\n") ;
    }

// Reset value of variable 'temp_num' and apply calculations that will isolate the first two digits. 
// Store the results in a variable 'company_id'.

    temp_num = card_num ;
    int company_id ;

    while (temp_num > 100)
    {
        temp_num = card_num - (card_num % 10) ;
        company_id = temp_num / 10 ;
    }

    return company_id ;

// Print the type of credit card depending on the company ID and amount of digits.

    if (company_id > 50 && company_id < 56 && count == 16)
    {
        printf("MASTERCARD\n") ;
    }
    else if ((company_id == 4) && (count == 13 || count == 16))
    {
        printf("VISA\n") ;
    }
    else if ((company_id == 34 || company_id == 37) && (count == 15)) 
    {
        printf("AMEX\n") ;
    }
    else
    {
        printf("This is an invalid number.\n") ;
    }

    return 0 ;

}

2 个答案:

答案 0 :(得分:0)

你的答案是一个无序的模板,其中的部分不能从前一个逻辑上遵循。

具体问题:

这个逻辑:

if (count != 13 || count != 15 || count != 16)

使每张卡无效, s(||)应为 s(&amp;&amp;)才能生效。

这个循环毫无意义:

while (card_num >= 0)
{
    digit = card_num % 10 ;
    count++ ;
    temp_num = (card_num - digit) / 10 ;
    break ;
    ...
}

break是无条件的,因此退出循环并忽略接下来的20行。

当您拨打return五次时,您似乎已在其他地方的子程序中进行拼接,只有最后一次有效:

return sum_a ;
return sum_b ;
return count ;
return company_id ;
return 0 ;

在您应该使用card_num时,在多个地方使用temp_num

一旦您知道该卡无效,您就无法退出程序 - 而是继续进行测试。您无法确认卡何时有效。

您计算卡号中的位数,但等到您在测试之前运行其他检查后该数字计数是否有效。

以下是我对代码的修改,以解决上述问题和一些风格问题:

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

int main(void)
{
    printf("Please give me your credit card number: ") ;

    long long card_num = 0LL;

    while (card_num < 1LL || card_num > 9999999999999999LL)
    {
        card_num = GetLongLong();
    }

    // Make a copy of the card number to be used and modified throughout the process.

    long long temp_num = card_num;

    // Isolate every digit from the credit card number using a loop and the variable 'digit'.
    // Keep track of the amount and position of each digit using variable 'count'.

    int count = 0;

    while (temp_num > 0LL)
    {
        temp_num = temp_num / 10LL;
        count++;
    }

    // If the number entered doesn't have the right amount of digits according
    // to variable 'count', declare the number as invalid.

    if (count != 13 && count != 15 && count != 16)
    {
        printf("This is an invalid number (# of digits).\n");
        return 1;
    }

    // Reset value of variable 'temp_num' and apply calculations that will isolate the first two digits. 
    // Store the results in a variable 'company_id'.

    temp_num = card_num;

    while (temp_num > 100LL)
    {
        temp_num = temp_num / 10LL;
    }

    int company_id = temp_num;

    // Print the type of credit card depending on the company ID and amount of digits.

    if (company_id > 50 && company_id < 56 && count == 16)
    {
        printf("MASTERCARD\n") ;
    }
    else if ((company_id == 34 || company_id == 37) && (count == 15)) 
    {
        printf("AMEX\n") ;
    }
    else if ((company_id / 10 == 4) && (count == 13 || count == 16 || count == 19))
    {
        printf("VISA\n") ;
    }
    else
    {
        printf("This card was issued by an unknown company.\n");
    }

    // Apply Luhn's algorithm.

    int sum = 0;

    temp_num = card_num;

    for (int i = 1; i <= count; i++)
    {
        int digit = temp_num % 10LL;

        if (i % 2 == 0)
        {
            digit *= 2;

            if (digit > 9)
            {
                digit -= 9;
            }
        }

        sum += digit;

        temp_num /= 10LL;
    }

    // Checking the validity of the number according to Luhn's algorithm

    if (sum % 10 != 0)
    {
        printf("This is an invalid number (Luhn's algorithm).\n");
        return 1; 
    }

    printf("This is a valid number.\n");

    return 0;
} 

这不是一个已完成的程序 - 需要进行错误检查和其他详细信息。当加倍的卡号大于9时,我使用了更简单的减去9的方法,而不是将数字相加。

答案 1 :(得分:0)

在我的解决方案中,此方法收到了var long信用卡号,希望对您有所帮助。

void check_card(long n)

{
    long temp_n = n;
    int count = 2;
    while(temp_n > 100)
    {
        temp_n = temp_n / 10;
        count ++;
    }

    long temp_n2 = n;
    int sum = 0;

    for (int i = 1; i <= count; i++)
    {
        int digit = temp_n2 % 10;
        if (i%2 == 0)
        {
            if (digit * 2 > 9)
            {
                sum += (digit * 2) - 9;
            }
            else
            {
                sum += digit * 2;
            }
        }
        else
        {
             sum += digit;
        }  
        temp_n2 /= 10;
    }

    bool flag = (sum % 10 == 0) ? true : false;

    if (count == 15 && (temp_n == 34 || temp_n == 37) && flag)
    {
        printf("AMEX\n");
    }
    else if(count == 16 && (temp_n > 50 && temp_n < 56) && flag)
    {
        printf("MASTERCARD\n");
    }
    else if((count == 13 || count == 16) && (temp_n / 10 ==4) && flag)
    {
        printf("VISA\n");
    }
    else
    {
        printf("INVALID\n");
    }