3

我正在编写一个程序来验证信用卡号码,我必须使用 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

4 回答 4

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;
}
于 2012-10-20T05:38:23.790 回答
1

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

请研究此示例,并通过调试器运行它以研究代码在执行时的行为方式。了解代码的实际运行方式(而不是您在编写代码时认为它会如何运行)是一项基本技能。恕我直言....

/*
 * 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;
}
于 2012-10-20T19:54:54.427 回答
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(十位)。

于 2016-02-15T22:49:30.710 回答
0

只需从数字的双倍中减去 9,就等于数字的总和。例如。

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

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

于 2017-11-03T11:44:51.123 回答