我该如何处理信用卡号验证算法?

时间:2012-10-20 05:19:04

标签: c++ luhn

我正在编写一个程序来验证信用卡号码,我必须使用Luhn的算法。让我先说一下,我刚开始学习编程(我们覆盖了上周的循环),所以有很多我不熟悉的东西。我在检查算术的一个函数上遇到了问题。基本上,它必须从右到左加倍每秒,并将所有内容加在一起。但是如果你加倍数,比如5,你得到10,那么你将不得不将1 + 0 = 1加到总和而不是10.这就是我坚持的部分。我怎么能把它放在程序中?

到目前为止的示例代码:

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; 
  }

4 个答案:

答案 0 :(得分:1)

#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;
}

答案 1 :(得分:1)

这是一种不同的算法。我剪切/粘贴了一个C#例子;第二个链接讨论了Luhn的一些优化。

请研究这个例子,并通过调试器运行它来研究代码在执行时的行为方式。了解代码实际的运行方式(与您在编写代码时认为的运行方式相反)是一种必要的技能。 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;
}

答案 2 :(得分:0)

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);
}

此:

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

是聪明的一点。如果数字大于4,则加倍将为10或更多。在这种情况下,你取双倍数并减去10,这将给你一位数,然后你加1(十位数)。

答案 3 :(得分:0)

只需从数字的两倍中减去9即可,相当于数字的总和。 对于前。

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

这比编写用于添加两个数字的代码更有效。