Question

I'm writing a program to validate credit card numbers and I have to use Luhn's Algorithm. Let me say beforehand, that I have just started to learn to program (we covered loops like last week), so there a lot of things I am unfamiliar with. I am having trouble with one of my functions that checks the arithmetic. Basically, it has to double every second digit from right to left and add everything together. But if you double a number, like 5, and you get 10, then you will have to add 1+0=1 to the total sum instead of 10. That's the part I'm stuck on. How can I put that in a program?

Sample code so far:

int 
doubleEvenSum(string creditCardNumber) {
  int evenSum; 
  int countPosition; 
  int doublePosition; 
  int length;

  length = creditCardNumber.length (); 
  countPosition = creditCardNumber.at(length - 2); 
  evenSum = 0; 
  while(countPosition>0) { 
    if ((2 * countPosition) < 10) { 
      doublePosition = 2 * countPosition; 
    } 
    else if ((2 * countPosition) > 9) { 
      ??? 
    } 
    evenSum = evenSum + doublePosition; 
  }
Was it helpful?

Solution

#include <stdio.h>
#include <string.h>
#include <ctype.h>

/*
    return the Luhn (MOD10) checksum for a sequence of digits.

    -1 is returned on error (a non-digit was in the sequence 

 */

int mod10( char const* s)
{
    int len = strlen(s);
    int sum = 0;

    int dbl = 0;

    while (len) {
        char digit;
        int val;

        --len;
        digit = s[len];

        if (!isdigit( (unsigned char) digit)) return -1;    // non digit in the sequence

        val = digit - '0';  // convert character to numeric value

        if (dbl) {
            // double the value
            val *= 2;

            // if the result is double-digits, add the digits together
            if (val > 9) {
                val = val - 10;
                val = val + 1;
            }
        }

        dbl = !dbl; // only double value every other time

        sum += val;
    }

    return sum % 10;
}

OTHER TIPS

Here is a different algorithm. I cut/pasted from a C# example; the second link discusses a number of optimization for Luhn.

Please study this example, and please run it through the debugger to study how the code behaves as it's executing. Understanding how code actually runs (as opposed to how you think it will run when you write it) is an essential skill. IMHO....

/*
 * Validate credit card with Luhn Algorithm
 *
 * REFERENCES:
 * - http://jlcoady.net/c-sharp/credit-card-validation-in-c-sharp
 * - http://orb-of-knowledge.blogspot.com/2009/08/extremely-fast-luhn-function-for-c.html
 */
#include <stdio.h>   // printf(), scanf(), etc
#include <string.h>  // strlen (), etc
#include <ctype.h>   // isdigit(), etc
#if !defined(FALSE)
  #define FALSE 0
  #define TRUE ~FALSE
#endif

/*
 * type definitions (should go in separate header)
 */
enum CardType {
  MASTERCARD=1, BANKCARD=2, VISA=3, AMEX=4, DISCOVER=5, DINERS=6, JCB=7
};

/*
 * function prototypes (should also go in header)
 */
int luhn (int number[], int len);
bool validate (CardType cardType, char *cardNumber);

/*
 * program main
 */
int
main (int argc, char *argv[])
{
  char cc_number[80];
  int cc_type;
  for ( ;; ) {
    printf ("Enter a credit card number and type (1, 2, 3, 4, 5. 6 or 7):\n");
    printf ("  MASTERCARD=1, BANKCARD=2, VISA=3, AMEX=4, DISCOVER=5, DINERS=6, JCB=7\n");
    int iret = scanf ("%s %d", cc_number, &cc_type);
    if (iret == 2)
      break;
    else
      printf ("Incorrect input: please enter a valid CC# and CC type\n");
  }
  if (validate ((CardType)cc_type, cc_number))
    printf ("Valid\n");
  else
    printf ("Invalid card type/number\n");
  return 0;
}


/*
 * validate card#
 */
bool
validate (CardType cardType, char *cardNumber)
{
  // 16 or fewer digits?
  int len = strlen(cardNumber);
  if (strlen (cardNumber) > 16)
    return false;

  // number to validate
  int number[16]; 
  for(int i = 0; i < (int)strlen (cardNumber); i++) {
    if(!isdigit(cardNumber[i]))
      return FALSE;
    number[i] = cardNumber[i] - '0';
  }

  // Validate based on card type, first if tests length, second tests prefix
  switch(cardType)  {
    case MASTERCARD:
      if(len != 16)
        return FALSE;
      if(number[0] != 5 || number[1] == 0 || number[1] > 5)
        return FALSE;
      break;

    case BANKCARD:
      if(len != 16)
        return FALSE;
      if(number[0] != 5 || number[1] != 6 || number[2] > 1)
        return FALSE;
      break;

    case VISA:
      if(len != 16 && len != 13)
        return FALSE;
      if(number[0] != 4)
        return FALSE;
      break;

    case AMEX:
      if(len != 15)
        return FALSE;
      if(number[0] != 3 || (number[1] != 4 && number[1] != 7))
        return FALSE;
      break;

    case DISCOVER:
      if(len != 16)
        return FALSE;
      if(number[0] != 6 || number[1] != 0 || number[2] != 1 || number[3] != 1)
        return FALSE;
      break;

    case DINERS:
      if(len != 14)
        return FALSE;
      if(number[0] != 3 || (number[1] != 0 && number[1] != 6 && number[1] != 8) || number[1] == 0 && number[2] > 5)
        return FALSE;
      break;

    case JCB:
      if(len != 16 && len != 15)
        return FALSE;
      if(number[0] != 3 || number[1] != 5)
        return FALSE;
      break;
    default:
      return FALSE;
  }

  int sum = luhn (number, len);
  return (sum % 10 == 0);
}


// Use Luhn Algorithm to validate
int luhn (int number[], int len)
{
  int sum = 0;
  for(int i = len - 1; i >= 0; i--)
  {
    if(i % 2 == len % 2)
    {
      int n = number[i] * 2;
      sum += (n / 10) + (n % 10);
    }
    else
      sum += number[i];
  }
  return sum;
}
int luhnCardValidator(char cardNumbers[]) {
    int sum = 0, nxtDigit, i;
    for (i = 0; cardNumbers[i] != NULL_TERMINATOR ; i++) {
         nxtDigit = cardNumbers[i] - START_OF_ASCII_NUMERIC;
        if (i % 2 == 0) 
          nxtDigit  = (nxtDigit > 4) ? (nxtDigit * 2 - 10) + 1 : nxtDigit * 2;
        sum += nxtDigit;
    }
    return (sum % 10);
}

This:

... (nxtDigit > 4) ? (nxtDigit * 2 - 10) + 1 : ...

is the clever bit. If the digit is greater than 4, then the doubling will be 10 or more. In that case, you take the doubled number and subtract 10 which will give you the ones-digit then you add 1 (the tens-digit).

Just subtract 9 from the double of the number then you will equivalent of the sum of the digits. For ex.

7= 7*2 = 14 = 1+4 = 5 OR 14-9 = 5

This is more efficient than writing code for adding both digits.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top