Search code examples
cloopscs50luhn

Sort every digit of a string


I'm trying to implement Luhn's algorithm in C. My problem is that my loop doesn't work at all.

I try to divide it by 10 to sort numbers in different variables. For the number 378282246310005 in the example below, I need to get: 5+0+1+6+2+8+8+3 = 33 (total_odd_numbers).

Then I multiply all the other ones by 2 (which gives me 0+0+6+8+4+4+14) and add all their digits: 0+0+6+8+4+4+1+4=27 (total_even_numbers).

And finally I add up even and odd numbers and divide the total by 10. In this case, 33+27=60, so my next test ((60%10) != 0) passes.

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

// Provides the length of credit card number
int length_ccn(long long credit_card_number)
{
    int length = 0;
    while (credit_card_number > 0)
    {
        length++;
        credit_card_number /= 10 ;
    }
    return length;
}


char Luhn_check(long long credit_card_number)
{
    int total_even_numbers = 0;
    int total_odd_numbers = 0;
    int even_number = 0;
    printf("Line 43 worked\n");
    int odd_number = 0;
    int Luhn_sum = 0;
    char Luhn_check = 0;
    char Luhn_validity = 0;
    printf("line 49 executed\n");
    for(int check_digit_basis=credit_card_number ; check_digit_basis > 0 ; check_digit_basis /= 10)
    {
        if ((check_digit_basis % 2) > 0)
        {
            printf("line 53 worked\n");
            odd_number = (check_digit_basis % 10);
            total_odd_numbers = total_odd_numbers + odd_number;
        }
        else
        {
            even_number = (check_digit_basis % 10);
            if(even_number >= 5)
            {
                total_even_numbers = total_even_numbers + ((( 2 * even_number) % 10) + 10 );
                printf("%i", even_number);
            }
            else
            {
                total_even_numbers = total_even_numbers + (2 * even_number);
            }
        }
    }
    Luhn_sum = total_even_numbers + total_odd_numbers;
    if ((Luhn_sum % 10 ) == 0 )
    {
        Luhn_validity = 1;
    }
    else
    {
        Luhn_validity = 0;
    }
    return Luhn_check;
}



int main(void)
{
    printf("Provide your credit card number:\n");
    long long credit_card_number = get_long_long();
    int length = length_ccn(credit_card_number);
    printf("%i\n", length);
    char Luhn_validity = Luhn_check(credit_card_number);
    if(Luhn_validity)
    {
        printf("pass\n");
    }
    else
    {
        printf("INVALID\n");
    }
}

I just get:

Provide your credit card number:
378282246310005
15
Line 43 worked
line 49 executed
INVALID

Can someone tell me why "line 53 worked" isn't displayed?

EDIT: I changed a couple of things and total_odd_numbers seems to be correct but total_even_number isn't.

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

// Provides the length of credit card number
int length_ccn(long long credit_card_number)
{
    int length = 0;
    while (credit_card_number > 0)
    {
        length++;
        credit_card_number /= 10 ;
    }
    return length;
}


char Luhn_check(long long credit_card_number)
{
    int total_even_numbers = 0;
    int total_odd_numbers = 0;
    int even_number = 0;
    printf("Line 43 worked\n");
    int odd_number = 0;
    int Luhn_sum = 0;
    char Luhn_check = 0;
    char Luhn_validity = 0;
    printf("line 49 executed\n");
    long long check_digit_basis = credit_card_number;
    for(int i =1 ; check_digit_basis > 0 ; i++)
    {
        if ((i % 2) > 0)
        {
            printf("line 53 worked\n");
            odd_number = (check_digit_basis % 10);
            total_odd_numbers = total_odd_numbers + odd_number;
            printf("%i total odd\n", total_odd_numbers);
        }
        else
        {
            even_number = (check_digit_basis % 10);
            if(even_number >= 5)
            {
                total_even_numbers = total_even_numbers + ((( 2 * even_number) % 10) + 10 );
                printf("%i test total even\n", total_even_numbers);
            }
            else
            {
                total_even_numbers = total_even_numbers + (2 * even_number);
                printf("%i test total even\n", total_even_numbers);
            }
        }
        check_digit_basis = (check_digit_basis / 10);

    }
    Luhn_sum = total_even_numbers + total_odd_numbers;
    if ((Luhn_sum % 10 ) == 0 )
    {
        Luhn_validity = 1;
    }
    else
    {
        Luhn_validity = 0;
    }
    return Luhn_check;
}



int main(void)
{
    printf("Provide your credit card number:\n");
    long long credit_card_number = get_long_long();

    int length = length_ccn(credit_card_number);
    printf("%i\n", length);
    char Luhn_validity = Luhn_check(credit_card_number);
    if(Luhn_validity)
    {
        printf("pass\n");
    }
    else
    {
        printf("INVALID\n");
    }
}

I get:

Provide your credit card number:
378282246310005
15
Line 43 worked
line 49 executed
line 53 worked
5 total odd
0 test total even
line 53 worked
5 total odd
0 test total even
line 53 worked
6 total odd
6 test total even
line 53 worked
12 total odd
14 test total even
line 53 worked
14 total odd
18 test total even
line 53 worked
22 total odd
22 test total even
line 53 worked
30 total odd
36 test total even
line 53 worked
33 total odd
INVALID

It's way more satisfying since total_odd_numbers seems correct but I'm wondering what's wrong in my total_even_number formula.

I ran another test (to get every individual value even_number takes while making output clearer), I saw that the program sees my even numbers (0, 0, 3, 4, 2, 2, 7) but addition isn't correct...

The problem is in this line:

total_even_numbers = total_even_numbers + ((( 2 * even_number) % 10) + 10 );

I can't seem to separate numbers to make 22+1+5 instead of the 22+14 that I get.

Edit 2:

After running a couple of tests, I managed to see where my problem was. Here, I can't see what I'm doing wrong since I give a value to Luhn_validity and it still wants it to be equal to 60.

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

// Provides the length of credit card number
int length_ccn(long long credit_card_number)
{
    int length = 0;
    while (credit_card_number > 0)
    {
        length++;
        credit_card_number /= 10 ;
    }
    return length;
}


char Luhn_check(long long credit_card_number)
{

    int total_even_numbers = 0;
    int total_odd_numbers = 0;
    int even_number = 0;
    printf("Line 43 worked\n");
    int odd_number = 0;
    int Luhn_sum = 0;
    char Luhn_check = 0;
    char Luhn_validity = 0;
    printf("line 49 executed\n");
    long long check_digit_basis = credit_card_number;
    for(int i =1 ; check_digit_basis > 0 ; i++)
    {
        if ((i % 2) > 0)
        {
            odd_number = (check_digit_basis % 10);
            total_odd_numbers = total_odd_numbers + odd_number;
        }
        else
        {
            even_number = (check_digit_basis % 10);
            if(even_number >= 5)
            {
                printf("%i >5\n", even_number);
                int testouille = (( 2 * even_number) % 10);
                printf("%i testouille\n", testouille);
                total_even_numbers = total_even_numbers + ((( 2 * even_number) % 10) + 1 );
                printf("%i test total even\n", total_even_numbers);
            }
            else
            {
                printf("%i <5\n", even_number);
                total_even_numbers = total_even_numbers + (2 * even_number);
                printf("%i test total even\n", total_even_numbers);
            }
        }
        check_digit_basis = (check_digit_basis / 10);
    }
    Luhn_sum = total_even_numbers + total_odd_numbers;
    printf("%i", Luhn_sum);
    if ((Luhn_sum % 10 ) == 0 )
    {
        Luhn_validity = 1;
        printf("%c\n", Luhn_validity);
    }
    else
    {
        Luhn_validity = 0;
    }
    return Luhn_check;
}

int main(void)
{
    printf("Provide your credit card number:\n");
    long long credit_card_number = get_long_long();
    int length = length_ccn(credit_card_number);
    printf("%i\n", length);
    char Luhn_validity = Luhn_check(credit_card_number);
    if(Luhn_validity)
    {
        printf("pass\n");
    }
    else
    {
        printf("INVALID\n");
    }
}

Thanks in advance.


Solution

  • You are trying to fit a long long into an int. That will not fit in this case. Try changing the for on line 32:

    for (long long check_digit_basis=credit_card_number ; check_digit_basis > 0 ; check_digit_basis /= 10)
    

    check_digit_basis = (int)(378282246310005LL) may be negative (-1293252491) on my system in which case (check_digit_basis % 2) will be negative.