cluhn

Wanted to check if a credit card number is valid or not


I wanted to check if a credit card number is valid or not but when i run the code, every number I give as input, the output comes as invalid.

The example given below is what I should i do.

Example with David’s Visa: 4003600000000014.

For the sake of discussion, let’s first underline every other digit, starting with the number’s second-to-last digit:

4003600000000014

  1. Okay, let’s multiply each of the underlined digits by 2:

1•2 + 0•2 + 0•2 + 0•2 + 0•2 + 6•2 + 0•2 + 4•2

That gives us:

2 + 0 + 0 + 0 + 0 + 12 + 0 + 8

  1. Now let’s add those products’ digits (i.e., not the products themselves) together:

2 + 0 + 0 + 0 + 0 + 1 + 2 + 0 + 8 = 13

  1. Now let’s add that sum (13) to the sum of the digits that weren’t multiplied by 2 (starting from the end):

13 + 4 + 0 + 0 + 0 + 0 + 0 + 3 + 0 = 20

  1. , the last digit in that sum (20) is a 0, so David’s card is legit!

#include <stdio.h>

int main()
{

    int no;
    printf("Visa number: ");`
    scanf("%d", &no);

    int d_1, d_2, d_3, d_4, d_5, d_6, d_7, d_8, d_9, d_10, d_11, d_12, d_13, d_14, d_15;

    d_15 = no%10;
    d_14 = ((no%100)/10)*2;
    d_13 = (no%1000)/100;
    d_12 = ((no%10000)/1000)*2;
    d_11 = (no%100000)/10000;
    d_10 = ((no%1000000)/100000)*2;
    d_9 = (no%10000000)/1000000;
    d_8 = ((no%100000000)/10000000)*2;
    d_7 = (no%1000000000)/100000000;
    d_6 = ((no%10000000000)/1000000000)*2;
    d_5 = (no%100000000000)/10000000000;
    d_4 = ((no%1000000000000)/100000000000)*2;
    d_3 = (no%10000000000000)/1000000000000;
    d_2 = ((no%100000000000000)/10000000000000)*2;
    d_1 = (no%1000000000000000)/100000000000000;

    int d[7] = {d_2, d_4, d_6, d_8, d_10, d_12, d_14};

    int n,add;

    for (n=1; n<=7; n++)
        if(d[n]>10)
        {
            d[n] = (d[n]%10);
            d[(15-n)+1] = ((d[n]%100)/10);
            int sum=0;
            for (int i=0; i<7; i++)
                sum += d[i];
        }
        else
        {
            add = d_14 + d_12 + d_10 + d_8 + d_6 + d_4 + d_2;
        }

    int sum = add + d_15 + d_13 + d_11 + d_9 + d_7 + d_5 + d_3 + d_1;

    if ((sum % 10) == 0)
    {
        printf("%s\n", "The card is valid");
    }
    else
    {
        printf("%s\n", "The card is invalid");
    }
}

Solution

  • every number I give as input, the output comes as invalid.

    Too big

    OP's int is likely 32-bit.

    Reading text input that would attempt to form an int outside the int range is undefined behavior. Rest of code is irrelevant.

    int no;
    scanf("%d", &no);  // attempt to read "4003600000000014" leads to UB.
    

    Consider reading user input into a string first and then process the characters. @Weather Vane

    char buf[100];
    
    if (fgets(buf, sizeof buf, stdin)) {
      int i;
      sum[2] = { 0, 0 };  // sums of even indexed digits and odd indexed digits.
      // Note: only 1 sum really needed, but using 2 sums to mimic OP's approach
    
      for (i = 0; isdigit((unsigned char) buf[i]); i++) {
        digit = buf[i] - '0';
        if (i%2 == 0) {
          digit *= 2;
          if (digit >= 10) {
            digit = (digit/10 + digit%10);  
          }
        } 
        sum[i%2] += digit;
      }
    
    
      // reject bad input: too long or missing expected end
      if (i > 16 || (buf[i] != '\n' && buf[i] != '\0')) {
        puts("Bad input");
      } else {
        // pseudo code to not give everything away.
        // do math on sum[0], sum[1]
        // if as expected --> success 
      }
    }