ccs50luhn

Trying to implement luhn's algorithm for cs50 pset: but when testing the value isn't coming out to be correct


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

int main(void)
{
    long num = get_long("What's your card number: " );
    long countNum = num;
    int count = 0;
    while (countNum != 0)
    {
        countNum /= 10;
        count++;
    }
    printf("%i", count);
    int sum = 0;
    long tempNum = num;
    if (count == 13)
    {
        for (int i = 0; i < 7; i ++)
        {
            int n = i;
            while (n != 0)
            {
                tempNum /= 100;
                n--;
            }

            if (2 * (tempNum % 10) > 10) //should not matter if correct or incorrect in this case
            {
                sum = sum + ((2 * (tempNum % 10)) / 10) + ((2 * (tempNum % 10)) % 10);
            }
            else
            {
                sum += 2 * (tempNum % 10);
            }
            tempNum = num;
        }

        printf("%i", sum);
    }
}

I am just making this part of the algorithm for 13 digit numbers and when i test: 4222222222222 (which supposedly should work) I get a value back of 1332. Can anyone tell me where I am going wrong in my code? - I suspect something is probably wrong in the loop at the bottom.


Solution

  • Seeing as this issue is still open, I thought I would go ahead and highlight the main issue with the code in that it is not including all of the digits in the hash total check. With that following is a refactored version of your program that includes the addition of the other digits to the hash total.

    #include <stdio.h>
    
    int main(void)
    {
        /*  long num = get_long("What's your card number: " ); Do not have CS50 installed - using conventional input method */
        long num;
        printf("What's your card number: ");
        scanf("%ld", &num);
    
        long countNum = num;
        int count = 0;
        while (countNum != 0)
        {
            countNum /= 10;
            count++;
        }
        printf("%i\n", count);
        int sum = 0;
        long tempNum = num;
        if (count == 13)
        {
            for (int i = 0; i < 13; i++)    /* Evaluate every digit of the card number  */
            {
                tempNum = num % 10;
                printf("Digit is: %ld", tempNum);
                if (i % 2 != 0)             /* Parity checking - every other digit gets doubled and checked if over "9" */
                {
                    tempNum *= 2;
                    if (tempNum > 9)
                        tempNum -= 9;
                }
                sum += tempNum;
                printf("  Value after parity check: %ld  Running hash total: %d\n", tempNum, sum);
                num /= 10;
            }
    
            printf("%i ", sum);
    
            if ((sum % 10) == 0)
                printf("Hash total is divisible by \"10\" and therefore is valid\n");
            else
                printf("Hash total is not divisible by \"10\" so is invalid\n");
        }
    }
    

    The key bits to note are as follows:

    Additional print statements were added just for debugging and illustration purposes. With that following is a test of the refactored code.

    craig@Vera:~/C_Programs/Console/CCLuhn/bin/Release$ ./CCLuhn 
    What's your card number: 4222222222222
    13
    Digit is: 2  Value after parity check: 2  Running hash total: 2
    Digit is: 2  Value after parity check: 4  Running hash total: 6
    Digit is: 2  Value after parity check: 2  Running hash total: 8
    Digit is: 2  Value after parity check: 4  Running hash total: 12
    Digit is: 2  Value after parity check: 2  Running hash total: 14
    Digit is: 2  Value after parity check: 4  Running hash total: 18
    Digit is: 2  Value after parity check: 2  Running hash total: 20
    Digit is: 2  Value after parity check: 4  Running hash total: 24
    Digit is: 2  Value after parity check: 2  Running hash total: 26
    Digit is: 2  Value after parity check: 4  Running hash total: 30
    Digit is: 2  Value after parity check: 2  Running hash total: 32
    Digit is: 2  Value after parity check: 4  Running hash total: 36
    Digit is: 4  Value after parity check: 4  Running hash total: 40
    40 Hash total is divisible by "10" and therefore is valid
    

    As an additional bit of information, you might want to refer to the following Wikipedia link about the Luhn algorithm:

    "https://en.wikipedia.org/wiki/Luhn_algorithm"

    That might be helpful in making the card testing more generic as credit card numbers can be lengths other than thirteen digits.