-2

I first attempted the code myself, then tweaked it after watching Deliberate Think's video on Youtube. While my code can be compiled, all credit card number inputs return "INVALID" e.g. when using the testing AMEX number on PayPal (378282246310005), check50 says that: "identifies 378282246310005 as AMEX expected "AMEX\n", not "INVALID\n". I think there may be a problem under //implementing Luhn's algorithm.

Below is my code:

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

int find_length(long long ccn);
bool check_luhn(long long ccn);
bool check_validity(long long ccn);
void print_card_brand(long long ccn);

//prompt user for credit card number; if invalid prompts again
int main(void)
{
    long long ccn;
    do
    {
        ccn = get_long_long("Credit Card Number: ");
    }
    while (ccn < 0);

    if (check_validity(ccn))
        print_card_brand(ccn);
    else
        printf("INVALID\n");
}

//find the length of the credit card number
int find_length(long long ccn)
{
    int length;
    for (length = 0; ccn!= 0; ccn /=10);
    length++;
    return length;
}

//implementing Luhn's algorithm
bool check_luhn(long long ccn)
{
    int sum = 0;
    for (int i = 0; ccn != 0; i++, ccn /= 10)
    {
        if (i % 2 == 0)
            sum += ccn % 10;
        else
        {
            int digit = 2 * (ccn % 10);
            sum += digit / 10 + digit % 10;
        }
    }
    return (sum % 10) == 0;
}

//check length and Luhn's algorithm
bool check_validity(long long ccn)
{
    int length = find_length(ccn);
    return (length == 13 || length == 15 || length == 16) && check_luhn(ccn);
}

//print credit card brand
void print_card_brand(long long ccn)
{
    if ( (ccn >= 34e13 && ccn < 35e13) || (ccn >= 37e13 && ccn < 38e13) )
        printf("AMEX\n");
    else if (ccn >= 51e14 && ccn < 56e14)
        printf("MASTERCARD\n");
    else if ( (ccn >= 4e12 && ccn < 5e12) || (ccn >= 4e15 && ccn < 5e15) )
        printf("VISA\n");
    else
        printf("INVALID\n");
}

Thank you all in advance for your help, I've been stuck on this for so many days. Having never done coding before, I have no idea what went wrong.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • 2
    Have you attempted to debug your program? Usual way is to run the program in a debugger and/or add more debug print statements to trace the program execution to find where things start going wrong. – kaylum May 24 '20 at 08:26
  • 1
    In `find_length`, you have a semicolon after the `for` loop head, which means the loop's body is empty and `length is incremented unconditionally only once. Your length will always be 1. – M Oehm May 24 '20 at 08:26
  • @ everyone else who stumbles upon this post: the problem was fixed after I removed the rogue semi-colon as mentioned by user M Oehm. Thank you all for the help and it was on hindsight a silly mistake – belugawhale May 25 '20 at 15:48

1 Answers1

0

You have a few bugs in there, one pointed out in the comments above is a rogue semicolon. Your implementation of luhn wasn't quite right so I've tried to fix it. I tried to fix this whilst making minimal changes. I didn't have access to CS50.h, so I addded stdbool and a dodgy scanf. I would undo those two changes.

#include <stdio.h>
#include <stdbool.h>

int find_length(long long ccn);
bool check_luhn(long long ccn);
bool check_validity(long long ccn);
void print_card_brand(long long ccn);

//prompt user for credit card number; if invalid prompts again
int main(void)
{
    long long ccn;
    do
    {
        scanf("Credit card number: %lld", &ccn);
    }
    while (ccn < 0);

    if (check_validity(ccn))
        print_card_brand(ccn);
    else
        printf("INVALID\n");
}

//find the length of the credit card number
int find_length(long long ccn)
{
    int length;
    for (length = 0; ccn!= 0; ccn /=10)
      length++;

    return length;
}

//implementing Luhn's algorithm
bool check_luhn(long long ccn)
{
    int sum = 0;
    long long temp_ccn = ccn;
    int length = find_length(ccn);

    for (int i = 1; i <= find_length(ccn); i++)
    {
        int rightDigit = temp_ccn % 10LL;

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

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

        sum += rightDigit;
        temp_ccn /= 10LL;
    }

    return (sum % 10) == 0;
}

//check length and Luhn's algorithm
bool check_validity(long long ccn)
{
    int length = find_length(ccn);
    return (length == 13 || length == 15 || length == 16) && check_luhn(ccn);
}

//print credit card brand
void print_card_brand(long long ccn)
{
    if ( (ccn >= 34e13 && ccn < 35e13) || (ccn >= 37e13 && ccn < 38e13) )
        printf("AMEX\n");
    else if (ccn >= 51e14 && ccn < 56e14)
        printf("MASTERCARD\n");
    else if ( (ccn >= 4e12 && ccn < 5e12) || (ccn >= 4e15 && ccn < 5e15) )
        printf("VISA\n");
    else
        printf("INVALID\n");
}
CodeWash
  • 155
  • 6