-1

Task: the user enters the card number and needs to determine whether the card is valid and, if so, determine the type of card (Visa, MasterCard, American Express). We have [https://cs50.harvard.edu/college/2021/spring/psets/1/credit/#luhns-algorithm][Luhn's Algorithm] to determine the validation of card number.

Problem: sometimes programm identifies invalid card as Visa(for example: 4111111111111113, 4222222222223). I really don't know how to solve this problem( I've already seen other solutions of this CS50 Credit task, but since I'm a beginner, I want to know what's wrong exactly with this code. I would be grateful for any hints on this problem and the code as a whole. Appreciate your help!

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

int main(void)
{
    long credit;
    do
    {
        credit = get_long("Number of card:\n");
    }
    while (credit < 0);
    long number = credit;
    int digits;
    for (digits = 0; number > 0; digits++)
    {
        number /= 10;
    }
    int checksum = 0;
    int i;
    for (i = 0; number > 0; i++, number /= 10)
    {
        if (i % 2 == 0)
        {
            checksum += (number % 10);
        }
        else
        {
            int n = (number % 10) * 2;
            if (n > 9)
            {
                n = (n / 10) + (n % 10);
            }
            checksum += n;
        }
    }
    checksum = checksum % 10;
    
    if ((checksum == 0) && ((credit >= 34e13 && credit < 35e13) || (credit >= 37e13 && credit < 38e13)))
    {
        printf("AMEX\n");
    }
    else if ((checksum == 0) && (credit >= 51e14 && credit < 56e14))
    {
        printf("MASTERCARD\n");
    }
    else if ((checksum == 0) && ((credit >= 4e12 && credit < 5e12) || (credit >= 4e15 && credit < 5e15)))
    {
        printf("VISA\n");
    }
    else
    {
        printf("INVALID\n");
    }
}
dbush
  • 205,898
  • 23
  • 218
  • 273
  • After the loop that counts the digits, `number` is 0, but you still use it in the subsequent code. – Paul Hankin Mar 05 '21 at 13:11
  • 2
    If you had stepped through some examples in a debugger, you might have been able to notice that `checksum` was always 0 and figured out the problem. – Paul Hankin Mar 05 '21 at 13:13
  • Note `5e15` is a `double` and so `credit < 5e15` is done by first converting `number` to a `double`. Code is approach the limits of `double` as a integer exactness. Avoid round off issues and use integer constants for an integer problem. Keep in mind [reasons not to use 5000 * 1000 * 1000 * 1000 * 1000](https://stackoverflow.com/a/40637622/2410359) – chux - Reinstate Monica Mar 05 '21 at 13:29
  • `long` is not certainly wide enough, Use `long long`. – chux - Reinstate Monica Mar 05 '21 at 13:31
  • 1
    If an answer addressed your question, consider [accepting it](https://stackoverflow.com/help/accepted-answer) as opposed to putting "closed" in the title. Also, "closed" has a specific meaning that doesn't apply here. – dbush Mar 05 '21 at 17:47

1 Answers1

0

Code changes number

for (digits = 0; number > 0; digits++) {
    number /= 10;
}
int checksum = 0;
int i;

Consider the value of number after the above loop. Certainly 0. Next loop does not iterate.

for (i = 0; number > 0; i++, number /= 10)

Code needs to preserve number.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256