Using C to Identify Valid Credit Card Numbers

Problem

Create a program that uses Luhn’s Algorithm to identify if the input number is a valid credit card number for AMEX, MASTERCARD, and VISA.

Breaking Down the Problem

Basic Characteristics of Credit Card Numbers

1. The numbers have specific **digits** (AMEX: 15, MASTER: 16, VISA: 13 or 16 )

2. The **first two digits** of the number are also specific (AMEX: 34 or 37, MASTER: 51~55, VISA: 40~49)

Luhn’s Algorithm

Not only does the number have to fit the requirements above, it also needs to be validated through Luhn’s Algorithm which is as follows:

Step 1. Multiply every other digit by 2, starting with the number’s second-to-last digit, and then add those products’ digits together.

Step 2. Add the sum to the sum of the digits that weren’t multiplied by 2.

Step 3. If the total’s last digit is 0 (or, put more formally, if the total modulo 10 is congruent to 0), the number is valid.

My Solution

Logical Steps

Get input Number from User (only receive valid integers) > Copy the Card Number twice to perform loops for Step 1 and 2 > Loop Step 1 > Loop Step 2 > Calculate digit of number > Check if it passes all requirements > Use switch/case to identify which card

1. Receive input

Receive input long integers from user using get_long from cs50.h library. Only allow positive integers.

long card_no;
    do
    {
        card_no = get_long("Number: ");
    }
    while (card_no < 1);

2. Initiate Copy of the Card Numbers

I copied the card number twice, so that even though I use these numbers to run the Algorithm, the original card number stays unchanged, which will be used later on to find out the first two digits.

long copy_for_step_1 = card_no / 10;
long copy_for_step_2 = card_no;

The first copy is divided by 10, because the initial value that we are trying to get is the second to last number of the whole number.

3. Checksum Step 1

In order to find out every other digit starting from the second to last value, I used modulo 10, which will provide me with the value of one's digit. And then I multiplied each value by 2, and checked if it was a two digit or one digit number. If it was a single digit, the number was simply added to the sum. If it was a two digit number, I added the value divided by 10 and modulo 10, so that the value of both one’s digit and ten’s digit could be added to the sum. To proceed the loop, I divided the copied card number by 10, moving to two digits forwards. The Loop ended when the copied number was a single digit.

long sum = 0;
do
{
    long num =  copy_for_step_1 % 10;
    long timesTwo = num * 2;
    if (timesTwo > 9)
    {
        sum += (timesTwo / 10) + (timesTwo % 10);
    }
    else
    {
        sum += timesTwo;
    }
    copy_for_step_1 /= 100;
}
while (copy_for_step_1 > 1);

4. Checksum Step 2

Using the same pattern as step 1, this time, I just added every other value starting from the very end.

do
{
    long num =  copy_for_step_2 % 10;
    sum += num;
    copy_for_step_2 /= 100;
}
while (copy_for_step_2 > 1);

5. Getting the Length of the Number

In order to get the digit of the number to find out if the digits were 13, 15, or 16, I looped through the number, dividing by 10 and counting a digit in every loop.

int digits = 1;
long copy_for_dig = card_no;
while (copy_for_dig > 10)
{
    digits ++;
    copy_for_dig /= 10;
}

6. Finding out the First Two Digits of the number

Using the same logic as above, I stopped the loop when the value was below hundred, to find the very first two digits of the number.

long first_two_digits = card_no;
while (first_two_digits > 100)
{
    first_two_digits /= 10;
};

7. Final Validation

If the sum calculated in Step 4 modulo 10 is 0: Check Length of Number > Check First Two Digits > Print the Corresponding Card Name

If the sum calculated in Step 4 modulo 10 is NOT 0: Print Invalid

If the length of the number isn't 13, 15, or 16: Print Invalid

If the first two digits doesn't match any of the criteria: Print Invalid

if (sum % 10 == 0)
{
    // Check digit of input
    switch (digits)
    {
        // Check for VISA with 13 digits
        case 13:
            if (first_two_digits > 39 && first_two_digits < 50)
            {
                printf("VISA\n");
                break;
            }
            else
            {
                printf("INVALID\n");
                break;
            }
        // Check for AMEX with 15 digits
        case 15:
            if (first_two_digits == 34 || first_two_digits == 37)
            {
                printf("AMEX\n");
                break;
            }
            else
            {
                printf("INVALID\n");
                break;
            }
        // Check for VISA or MASTERCARD with 16 digits
        case 16:
            if (first_two_digits > 39 && first_two_digits < 50)
            {
                printf("VISA\n");
                break;
            }
            if (first_two_digits > 50 && first_two_digits < 56)
            {
                printf("MASTERCARD\n");
                break;
            }
            else
            {
                printf("INVALID\n");
                break;
            }
        // If the digits aren't 13, 15, or 16, print invalid
        default:
            printf("INVALID\n");
    }
}
// If the sum's modulo 10 isn't congruent to 0, print invalid
else
{
    printf("INVALID\n");
}