Search code examples
calgorithmdebuggingcs50luhn

Excecuting Luhn's Algorithm in C - buggy code


I'm currently working through CS50x's 2018 programme and I'm completing the 'credit' part of pset1. We're supposed to be executing Luhn's algorithm, but I can't get it to work.

Luhn's algorithm is an algorithm that uses checksum to determine whether or not a credit card is valid. The input should be a credit card number, or something that could be a credit card number. It then takes the number, multiplies every other digit by 2 (or every even digit as implied in my code), sums them, then takes the remaining digits (the odd ones) and sums them with the first sum. The algorithm then states that if the last digit of the summed value is 0 then the number is valid (or if it divides by ten perfectly). If the answer isn't 0 then it should print "INVALID" to the user. If it is 0 the code should then analyse whether or not the number could be a valid card. We are supposed to use American Express, Visa and MasterCard as our potential cards. If it's AMEX it will be 15 digits and start with 34 or 37, MASTERCARD is 16 digits and starts with 51, 52, 53, 54 or 55, and VISA is either 13 or 16 digits and starts with 4. The expected output is either one of the card companies or "INVALID" if the number doesn't fit that criteria.

Instead of this, my code simply runs until overflow after a number is submitted. I know my logic must be flawed somewhere, but I have no idea where I've gone wrong. My code is as follows:

//Checks credit card no. to see if valid
#include <cs50.h>
#include <stdio.h>
#include <math.h>

int main(void)
{
    //Get card no. from user
    long long n;
    do
    {
        n = get_long_long("Card Number: ");
    }
    while (n < 0);

    //Define variables for checksum process
    int odd = 0;
    int even = 0;
    long long temp_n = n;
    int sum_a = 0;
    int sum_b = 0;
    int counter = 0;

    //Execute checksum until all of n assessed
    while (temp_n >= 0)
    {
        //Take final digit, add up, then update temp no., increase digit counter by 1
        odd = temp_n % 10;
        sum_b = sum_b + odd;
        temp_n = (temp_n - odd) / 10;
        counter++;

        //Take final digit (which is an even digit of n), multiply by 2 and add up, update temp no., increase counter by 1
        even = temp_n % 10;
        sum_a = sum_a + 2 * even;
        temp_n = (temp_n - even) / 10;
        counter++;

    }

    //Validate checksum
    int test = (sum_a + sum_b) % 10;

    //Return results
    if (test == 0)
    {
        if (counter == 16 && odd == 5 && (even == 1 || even == 2 || even == 3 || even == 4 || even == 5))
        {
            printf("MASTERCARD\n");
        }
        else if ((counter == 16 || counter == 13) && odd == 4)
        {
            printf("VISA\n");
        }
        else if (counter == 15 && odd == 3 && (even == 4 || even == 7))
        {
            printf("AMEX\n");
        }
        else
        {
            printf("INVALID\n");
        }
    }
    else
    {
        printf("INVALID\n");
    }

}

I would appreciate any help I can get about where I've gone wrong. Thank you in advance.


Solution

  • while (temp_n >= 0)
        {
            //Take final digit, add up, then update temp no., increase digit counter by 1
            odd = temp_n % 10;
            sum_b = sum_b + odd;
            temp_n = (temp_n - odd) / 10;
            counter++;
    
            //Take final digit (which is an even digit of n), multiply by 2 and add up, update temp no., increase counter by 1
            even = temp_n % 10;
            sum_a = sum_a + 2 * even;
            temp_n = (temp_n - even) / 10;
            counter++;
    
        }
    

    This assumes that input will always have even number of digits. Take a bool flag = true; and change it to:

    while (temp_n >= 0)
        {
            //Take final digit, add up, then update temp no., increase digit counter by 1
          if(flag){
            odd = temp_n % 10;
            sum_b = sum_b + odd;
            temp_n = (temp_n - odd) / 10;
            counter++;
            flag = !flag;}
    
            //Take final digit (which is an even digit of n), multiply by 2 and add up, update temp no., increase counter by 1
          else{
            even = temp_n % 10;
            sum_a = sum_a + 2 * even;
            temp_n = (temp_n - even) / 10;
            counter++;
            flag = !flag;}
    
        }