尝试在 C 中实现 Luhn 算法

Trying to implement Luhn's Algorithm in C

我正在尝试用C语言实现Luhn的算法来检查信用卡的有效性,对于那些不知道的人......就是这样:


为了实现它,我遍历了整个数字,如果我所在的数字的模数 2 等于 0,那么我将乘以 2 并添加到一个名为 totalEven 的变量中。

如果不是这种情况,我会将我所在的数字添加到 totalOdd 而无需乘法。

然后我会将位置递增 1 并检查其他数字,直到达到 16(卡片的最大位数)。

稍后我会添加两个变量并检查总模十是否等于 0。如果这意味着信用卡号码正确,否则它是错误的。

代码如下:

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

//list of variables

   //is the card valid
   bool isValid = true;
   // the creditcard number
   long input;
   //mod stands for modules, and is used to single out each number as seen later
   int mod = 10;
   //the location at which number I am checking
   int place = 1;
   //num is the number I am checking that has been singled out
   int num = 0;
   //total of numbers * 2 located at locations numbered with even numbers
   int totalEven = 0;
   //total of numbers located at locations numbered with odd numbers
   int totalOdd = 0;
     //gets input and stores it in well.. input
     input = get_long("Number: ");
      
      // a formula to single out a number, starting with the ones and then as you can see, mod is muliplied by 10 to go over the second number.

      num = ((input % mod) - (input % (mod /10))) / (mod/10);
      
      //loops 16 times
      for(int i = 0; i < 16; i++)
      {
          // if the place is even execute below
          if(place % 2 == 0)
          {
              totalEven = totalEven + num * 2;
          }   
          //else do this
          else if (place % 2 != 0)
          {
             totalOdd = totalOdd + num; 
          }
          //moves to the next number
          mod = mod * 10;
          place++;
      }
      
      //fufils the last step of the algorithm

      if((totalEven + totalOdd) % 10 == 0 )
      {
          isValid = true;
      }
      else
      {
          isValid = false;
      }

问题是这个代码块给我无效或 !isValid 即使信用卡号应该是正确的并且我检查了我的“公式”并且它工作得很好...

我完全不知道该怎么做...我是一个谦虚的爱好者所以请不要因为上面的怪物而烤我。

这里是代码的完整版本

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


long power();


int main(void)
{
    //AMERX 15 STRT 34 OR 37
    //MC 16 STRT 51, 52, 53, 54, 55
    //VZA 13 OR 16 STRT 4

   long input;
   bool isValid = true;
   string type;
   int mod = 10;
   int place = 1;
   int num = 0;
   int totalEven = 0;
   int totalOdd = 0;

   do
   {
      input = get_long("Number: ");
      

   }

   while(input < 0);
   
      
      for(int i = 0; i < 16; i++)
      {
          num = ((input % mod) - (input % (mod /10))) / (mod/10);
          if(place % 2 == 0)
          {
              totalEven = totalEven + num * 2;
          }
          else
          {
             totalOdd = totalOdd + num; 
          }
          
          mod = mod * 10;
          place++;
      }
      
      if((totalEven + totalOdd) % 10 == 0 )
      {
          isValid = true;
      }
      else
      {
          isValid = false;
          
          printf("%i , %i", totalEven, totalOdd);
      }
   if (isValid == true){
   if((input < (38 * power(10, 13)) && input >=(37 * power(10, 13))) || (input < (35 * power(10,13)) && input >= (34 * power(10, 13)))) 
   {
       type = "AMEX\n";
   }
   else if(input >= (51 * power(10, 14)) && input < (56 * power(10, 14)))
   {
       type = "MASTERCARD\n";
   }
   else if((input < (5 * power(10, 12)) && input >= (4 * power(10, 12))) || (input < (5 * power(10, 15)) && input >= (4 * power(10, 15))))
   {
       type = "VISA\n";
   } 
       else{
       type = "error\n";
   }
}
   else
   {
       type = "INVALID\n";
   }
   

    if((totalEven + totalOdd) % 10 == 0 )
    {
      isValid = true;
    }
    else
    {
      isValid = false;
    }
      
    printf("%s", type);

}





long power(int n, int p)
{
    long result = 1;
    for(int i = 0; i<p; i++)
    {
        result = result * n;
    }
    return result;

在查看您的代码时,我想指出一些错误。

  1. 您忘记了:#include <string.h> 因为您在代码中声明了 string type
  2. input = get_long("Number: "); 应该有自己的 do-while 循环,以防用户输入字母或不正确的数字。
  3. if(place % 2 == 0){ totalEven = totalEven + num * 2; } else if (place % 2 != 0){ totalEven = totalEven + num; } 第二部分应该 totalOdd = totalOdd + num
  4. totalEven = totalEven + num * 2 同时对错。它仅在数字乘以 2 小于 10 时有效。如果 num * 2 >= 10,假设 num = 6,则 6 * 2 为 12,则为 1 + 2 + totalEven。
  5. num = ((input % mod) - (input % (mod /10))) / (mod/10);这个应该在第一个for loop.
  6. #include <math.h> 中,有一个名为 pow 的幂函数,它与您的 power() 函数完全相同。

我不是 Luhn 算法的专家,但当我阅读 https://en.wikipedia.org/wiki/Luhn_algorithm 时,我觉得你做错了。

引自https://en.wikipedia.org/wiki/Luhn_algorithm

From the rightmost digit (excluding the check digit) and moving left, double the value of every second digit. The check digit is neither doubled nor included in this calculation; the first digit doubled is the digit located immediately left of the check digit. If the result of this doubling operation is greater than 9 (e.g., 8 × 2 = 16), then add the digits of the result (e.g., 16: 1 + 6 = 7, 18: 1 + 8 = 9) or, alternatively, the same final result can be found by subtracting 9 from that result (e.g., 16: 16 − 9 = 7, 18: 18 − 9 = 9).

我在您的代码中没有看到您处理粗体部分的任何地方。

而不是

totalEven = totalEven + num * 2;

我觉得你需要

int tmp = num * 2;
if (tmp > 9) tmp = tmp - 9;
totalEven = totalEven + tmp;

就是说 - 我认为通过将输入存储为数字,您的实现比需要的复杂得多。您可以使用数字数组代替数字。

即 - 而不是

long input = 1122334455667788

使用

int digits[] = {8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1};
// Notice that index zero is the rightmost digit

这样算法就简单多了:

// Double every second element and check for overflow
for (idx = 1; idx < 16; idx += 2)
{
    digits[idx] = 2 * digits[idx];
    if (digits[idx] > 9) digits[idx] = digits[idx] - 9;
}

// Calculate the sum
sum = 0;
for (idx = 0; idx < 16; ++idx)
{
    sum = sum + digits[idx];
}

如果您必须接收数字形式的输入,请首先调用一个将数字转换为数字数组的函数。您可以在 SO 上找到许多关于如何完成转换的示例。这里 Converting integer into array of digits 只是众多示例中的一个。

注意:我已经使用了 CS50X 库,因为这个问题似乎是同一个问题。

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

// Luhn's Algorithm

int main(void) 
{
    long cardNumber = get_long("Please, enter your card number: ");
    int sum1 = 0, num = 0, remainder = 0, sum2 = 0;
    long temp = cardNumber;
    
    while (temp > 0) 
    {
        num = ((temp / 10) % 10) * 2; // Multiplying every other digit by 2, starting with the number’s second-to-last digit
        while (num > 0) 
        {
            remainder = num % 10;
            sum1 += remainder; // Adding those products’ digits together
            num /= 10;
        }
        temp /= 100;
    }
    
    // So as to restore the initial values of remainder and temp for the use in next loop
    remainder = 0;
    temp = cardNumber;
    
    while (temp > 0) 
    {
        remainder = temp % 10;
        sum2 += remainder; // Sum of the digits that weren’t multiplied by 2
        temp /= 100;
    }
    
    ((sum1 + sum2) % 10) == 0 ? printf("Valid\n") : printf("Invalid\n");
    return 0;
}