0

I've been trying to fix this on my own for a bit but I wasn't able to find an answer online. My credit program passes all check50 test's except for the last two (identifies 4111111111111113 as INVALID and identifies 4222222222223 as INVALID). In my own terminal, I get the same results as check50 but what's strange to me is that the portion responsible returns the correct result when executed on its own. The check50 command used: check50 cs50/problems/2021/x/credit

Output:

Results for cs50/problems/2021/x/credit generated by check50 v3.1.2
:) credit.c exists
:) credit.c compiles
:) identifies 378282246310005 as AMEX
:) identifies 371449635398431 as AMEX
:) identifies 5555555555554444 as MASTERCARD
:) identifies 5105105105105100 as MASTERCARD
:) identifies 4111111111111111 as VISA
:) identifies 4012888888881881 as VISA
:) identifies 4222222222222 as VISA
:) identifies 1234567890 as INVALID
:) identifies 369421438430814 as INVALID
:) identifies 4062901840 as INVALID
:) identifies 5673598276138003 as INVALID
:( identifies 4111111111111113 as INVALID
    expected "INVALID\n", not "VISA\n"
:( identifies 4222222222223 as INVALID
    expected "INVALID\n", not "VISA\n"

Here is the program:

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

int check_sum(long);
long get_card(void);

int main(void) //main func that prints a result based on card type/check_sum
{

    int valid = 0;
    int final = 0;
    long c = 0;
    do //I'm sure there was another way to do this but it works I guess. prints results based on card number
    {
        c = get_card();
        if (c < 4000000000000)
        {
            printf("INVALID\n");
            valid = 1;
        }
        else if ((c > 3999999999999) && (c < 5000000000000))
        {
            final = check_sum(c);
            if ((final = 1))
            {
                printf("VISA\n");
                valid = 1;
            }
            else
            {
                printf("INVALID\n");
                valid = 1;
            }
        }
        else if ((c > 3999999999999999) && (c < 5000000000000000))
        {
            final = check_sum(c);
            if ((final = 1))
            {
                printf("VISA\n");
                valid = 1;
            }
            else
            {
                printf("INVALID\n");
                valid = 1;
            }
        }
        else if ((c > 5099999999999999) && (c < 5600000000000000))
        {
            final = check_sum(c);
            if ((final = 1))
            {
                printf("MASTERCARD\n");
                valid = 1;
            }
            else
            {
                printf("INVALID\n");
                valid = 1;
            }
        }
        else if ((c > 339999999999999) && (c < 350000000000000))
        {
            final = check_sum(c);
            if ((final = 1))
            {
                printf("AMEX\n");
                valid = 1;
            }
            else
            {
                printf("INVALID\n");
                valid = 1;
            }
        }
        else if ((c > 369999999999999) && (c < 380000000000000))
        {
            final = check_sum(c);
            if ((final = 1))
            {
                printf("AMEX\n");
                valid = 1;
            }
            else
            {
                printf("INVALID\n");
                valid = 1;
            }
        }
        else
        {
            printf("INVALID\n");
            valid = 1;
        }
    }
    while (valid == 0);
}

int check_sum() //function that returns a result based on Luhn's Alg
{
    long x;
    long set1 = 0;
    long set2 = 0;
    long y = 0;
    long d = 0; //variable used incase of y value greater than 5 which would cause Luhn's algo to be incorrect
    long f = 0; //sets y back to the digit before loop
    long z = 0;
    int check = 0;
    for (long i = 0; i < 16; i++)
    {
        // loop iterates card number, takes %, adds it to a set, subtracts % from original then / 10 for 2 sets with their own formulas. repeats til 16 digits.
        y = x % 10;
        set1 = y + set1; //digits that arent muliplied
        z = (x - y) / 10;
        x = z;
        y = x % 10;
        if (y < 5) //digits that are multiplied and under 5 dont need to be seperated
        {
            set2 = (y * 2) + set2;
        }
        else if (y > 4) //products of digits that are > 5 need to be added separately to fit the alg
        {
            d = (y * 2) % 10;
            set2 = d + set2;
            f = ((y * 2) - d) % 10 + 1;
            set2 = f + set2;
        }
        z = (x - y) / 10;
        x = z;
    }
    if ((set1 + set2) % 10 == 0)
    {
        check = 1;
    }
    else
    {
        check = 0;
    }
    return check;
}

long get_card(void) //makes sure input is long and non-negative because my loop game isn't the best
{
    long card = 0;
    do
    {
        card = get_long("Number: ");
    }
    while (card < 1);
    return card;
}

Instead of taking inputs I wanted to see if it works on its own so I placed the numbers that failed the test in place of user input. This is it below:

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

int main(void)
{
    long x = 4111111111111113;
    long set1 = 0;
    long set2 = 0;
    long y = 0;
    long d = 0; //variable used incase of y value greater than 5 which would cause Luhn's algo to be incorrect
    long f = 0; //sets y back to the digit before loop
    long z = 0;
    int check = 0;
    for (long i = 0; i < 16; i++)
    {
        y = x % 10;
        set1 = y + set1;
        z = (x - y) / 10;
        x = z;
        y = x % 10;
        if (y < 5)
        {
            set2 = (y * 2) + set2;
        }
        else if (y > 4)
        {
            d = (y * 2) % 10;
            set2 = d + set2;
            f = ((y * 2) - d) % 10 + 1;
            set2 = f + set2;
        }
        z = (x - y) / 10;
        x = z;
    }
    if ((set1 + set2) % 10 == 0)
    {
        check = 1;
        printf("valid\n");
    }
    else
    {
        check = 0;
        printf(" invalid\n");
    }
}
1

This is one of, if not the most common error made by new programmers. ;-)

Look at the following:

        if ((final = 1))

Note the single = sign. This is an assignment, not a comparison. It is assigning 1 to final. An assignment in an if statement always evaluates as true, no matter what numbers are assigned. (An assignment statement returns a value that represents true, indicating that the assignment was successful.) That's why the code was saying that the checksum was correct. In reality, any number of the correct length would have passed.

If you want to compare two values, you must use two equal signs, ==. Also, to make this pass the compiler, one set of parentheses needs to be removed. It should look like this:

        if (final == 1)

If this answers your question, please click on the check mark to accept. Let's keep up on forum maintenance. ;-)

1
  • Thanks for the response and while I've fixed that portion the issues remains. However now the program returns INVALID when the numbers used in the test are input manually. I've fixed it by assigning a global variable for the result of the get_card() and having the program first check if the card number is valid with check_sum, then passing it to the main function which sorts it by card type. I'll update my main post.
    – parapuffer
    Feb 13 at 6:43
0

I guess I was running into an issue with how the program passed the variable assigned to the card number. I fixed it by moving that variable into global scope and moving the order that the functions were called.

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

int check_sum(void);
long get_card(void);
long card = 0; // assigns global value for card number so it can be accessed from either function.

int main(void) //main func that prints a result based on card type/check_sum
{

    int valid = 0;
    int final = 0;
    long c = 0;
    do //I'm sure there was another way to do this but it works I guess. prints results based on card number
    {
        final = check_sum(); // calls check_sum which calls get_card. After card number is validated, passes check 1 or 0 to final
        c = card; // assigns card number to c which is used in the do while loop
        if (c < 4000000000000)
        {
            printf("INVALID\n");
            valid = 1;
        }
        else if ((c > 3999999999999) && (c < 5000000000000))
        {
            if (final == 1)
            {
                printf("VISA\n");
                valid = 1;
            }
            else
            {
                printf("INVALID\n");
                valid = 1;
            }
        }
        else if ((c > 3999999999999999) && (c < 5000000000000000))
        {
            if (final == 1)
            {
                printf("VISA\n");
                valid = 1;
            }
            else
            {
                printf("INVALID\n");
                valid = 1;
            }
        }
        else if ((c > 5099999999999999) && (c < 5600000000000000))
        {
            if (final == 1)
            {
                printf("MASTERCARD\n");
                valid = 1;
            }
            else
            {
                printf("INVALID\n");
                valid = 1;
            }
        }
        else if ((c > 339999999999999) && (c < 350000000000000))
        {
            if (final == 1)
            {
                printf("AMEX\n");
                valid = 1;
            }
            else
            {
                printf("INVALID\n");
                valid = 1;
            }
        }
        else if ((c > 369999999999999) && (c < 380000000000000))
        {
            if (final == 1)
            {
                printf("AMEX\n");
                valid = 1;
            }
            else
            {
                printf("INVALID\n");
                valid = 1;
            }
        }
        else
        {
            printf("INVALID\n");
            valid = 1;
        }
    }
    while (valid == 0);
}

int check_sum(void) //function that returns a result based on Luhn's Alg
{
    long x = get_card(); // takes number from user and then assigns it to x which is used for the checksum % 10 = 0
    long set1 = 0;
    long set2 = 0;
    long y = 0;
    long d = 0; //variable used incase of y value greater than 5 which would cause Luhn's algo to be incorrect
    long f = 0; //sets y back to the digit before loop
    long z = 0;
    int check = 0;
    for (long i = 0; i < 16; i++)
    {
        // loop iterates card number, takes %, adds it to a set, subtracts % from original then / 10 for 2 sets with their own formulas. repeats til 16 digits.
        y = x % 10;
        set1 = y + set1; //digits that arent muliplied
        z = (x - y) / 10;
        x = z;
        y = x % 10;
        if (y < 5) //digits that are multiplied and under 5 dont need to be seperated
        {
            set2 = (y * 2) + set2;
        }
        else if (y > 4) //products of digits that are > 5 need to be added separately to fit the alg
        {
            d = (y * 2) % 10;
            set2 = d + set2;
            f = ((y * 2) - d) % 10 + 1;
            set2 = f + set2;
        }
        z = (x - y) / 10;
        x = z;
    }
    if ((set1 + set2) % 10 == 0)
    {
        check = 1;
    }
    else
    {
        check = 0;
    }
    return check;
}

long get_card(void) //makes sure input is long and non-negative because my loop game isn't the best
{
    //long card = 0; // assigning the variable here causes issues with bounded extent(I think?) since I need to use the card number in not just the function tha calls this one, but the function that calls that one.
    do
    {
        card = get_long("Number: ");
    }
    while (card < 1);
    return card;
}

output:

Results for cs50/problems/2021/x/credit generated by check50 v3.1.2
:) credit.c exists
:) credit.c compiles
:) identifies 378282246310005 as AMEX
:) identifies 371449635398431 as AMEX
:) identifies 5555555555554444 as MASTERCARD
:) identifies 5105105105105100 as MASTERCARD
:) identifies 4111111111111111 as VISA
:) identifies 4012888888881881 as VISA
:) identifies 4222222222222 as VISA
:) identifies 1234567890 as INVALID
:) identifies 369421438430814 as INVALID
:) identifies 4062901840 as INVALID
:) identifies 5673598276138003 as INVALID
:) identifies 4111111111111113 as INVALID
:) identifies 4222222222223 as INVALID

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .