尝试用 C 语言实现 Luhn 算法

som*_*864 5 c luhn cs50

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

\n
    \n
  • 从数字\xe2\x80\x99s\n倒数第二个数字开始,每隔一个数字乘以 2,然后将这些乘积\xe2\x80\x99 数字相加。

    \n
  • \n
  • 将总和添加到 \xe2\x80\x99t 乘以 2 的数字之和。

    \n
  • \n
  • 如果总计 \xe2\x80\x99s 最后一位数字为 0(或者,更正式地说,如果总计
    \n模 10 与 0 全等),则该数字有效!

    \n
  • \n
\n
\n

为了实现这一点,我循环遍历整个数字,如果我所在的数字位置的模 2 等于 0,那么我将乘以 2 并添加到一个名为totalEven

\n

如果不是这种情况,我会将我所在的号码添加到totalOdd而不进行乘法。

\n

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

\n

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

\n

这是代码:

\n
#include <stdio.h>\n#include <cs50.h>\n\n//list of variables\n\n   //is the card valid\n   bool isValid = true;\n   // the creditcard number\n   long input;\n   //mod stands for modules, and is used to single out each number as seen later\n   int mod = 10;\n   //the location at which number I am checking\n   int place = 1;\n   //num is the number I am checking that has been singled out\n   int num = 0;\n   //total of numbers * 2 located at locations numbered with even numbers\n   int totalEven = 0;\n   //total of numbers located at locations numbered with odd numbers\n   int totalOdd = 0;\n
Run Code Online (Sandbox Code Playgroud)\n
     //gets input and stores it in well.. input\n     input = get_long("Number: ");\n      \n      // 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.\n\n      num = ((input % mod) - (input % (mod /10))) / (mod/10);\n      \n      //loops 16 times\n      for(int i = 0; i < 16; i++)\n      {\n          // if the place is even execute below\n          if(place % 2 == 0)\n          {\n              totalEven = totalEven + num * 2;\n          }   \n          //else do this\n          else if (place % 2 != 0)\n          {\n             totalOdd = totalOdd + num; \n          }\n          //moves to the next number\n          mod = mod * 10;\n          place++;\n      }\n      \n      //fufils the last step of the algorithm\n\n      if((totalEven + totalOdd) % 10 == 0 )\n      {\n          isValid = true;\n      }\n      else\n      {\n          isValid = false;\n      }\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

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

\n

这是代码的完整版本

\n
#include <stdio.h>\n#include <cs50.h>\n\n\nlong power();\n\n\nint main(void)\n{\n    //AMERX 15 STRT 34 OR 37\n    //MC 16 STRT 51, 52, 53, 54, 55\n    //VZA 13 OR 16 STRT 4\n\n   long input;\n   bool isValid = true;\n   string type;\n   int mod = 10;\n   int place = 1;\n   int num = 0;\n   int totalEven = 0;\n   int totalOdd = 0;\n\n   do\n   {\n      input = get_long("Number: ");\n      \n\n   }\n\n   while(input < 0);\n   \n      \n      for(int i = 0; i < 16; i++)\n      {\n          num = ((input % mod) - (input % (mod /10))) / (mod/10);\n          if(place % 2 == 0)\n          {\n              totalEven = totalEven + num * 2;\n          }\n          else\n          {\n             totalOdd = totalOdd + num; \n          }\n          \n          mod = mod * 10;\n          place++;\n      }\n      \n      if((totalEven + totalOdd) % 10 == 0 )\n      {\n          isValid = true;\n      }\n      else\n      {\n          isValid = false;\n          \n          printf("%i , %i", totalEven, totalOdd);\n      }\n   if (isValid == true){\n   if((input < (38 * power(10, 13)) && input >=(37 * power(10, 13))) || (input < (35 * power(10,13)) && input >= (34 * power(10, 13)))) \n   {\n       type = "AMEX\\n";\n   }\n   else if(input >= (51 * power(10, 14)) && input < (56 * power(10, 14)))\n   {\n       type = "MASTERCARD\\n";\n   }\n   else if((input < (5 * power(10, 12)) && input >= (4 * power(10, 12))) || (input < (5 * power(10, 15)) && input >= (4 * power(10, 15))))\n   {\n       type = "VISA\\n";\n   } \n       else{\n       type = "error\\n";\n   }\n}\n   else\n   {\n       type = "INVALID\\n";\n   }\n   \n\n    if((totalEven + totalOdd) % 10 == 0 )\n    {\n      isValid = true;\n    }\n    else\n    {\n      isValid = false;\n    }\n      \n    printf("%s", type);\n\n}\n\n\n\n\n\nlong power(int n, int p)\n{\n    long result = 1;\n    for(int i = 0; i<p; i++)\n    {\n        result = result * n;\n    }\n    return result;\n\n
Run Code Online (Sandbox Code Playgroud)\n

438*_*427 1

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

\n

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

\n
\n

从最右边的数字(不包括校验位)开始向左移动,每隔两个数字的值加倍。校验位既不加倍也不包含在该计算中;第一个加倍的数字是紧邻校验位左侧的数字。如果此加倍运算的结果大于 9(例如,8 \xc3\x97 2 = 16),则将结果的数字相加(例如,16: 1 + 6 = 7, 18: 1 + 8 = 9)或者,也可以通过从结果中减去 9 得到相同的最终结果(例如,16: 16 \xe2\x88\x92 9 = 7、18: 18 \xe2\x88\x92 9 = 9)。

\n
\n

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

\n

代替

\n
totalEven = totalEven + num * 2;\n
Run Code Online (Sandbox Code Playgroud)\n

我想你需要

\n
int tmp = num * 2;\nif (tmp > 9) tmp = tmp - 9;\ntotalEven = totalEven + tmp;\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

那就是 - 而不是

\n
long input = 1122334455667788\n
Run Code Online (Sandbox Code Playgroud)\n

使用

\n
int digits[] = {8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1};\n// Notice that index zero is the rightmost digit\n
Run Code Online (Sandbox Code Playgroud)\n

这样算法就简单多了:

\n
// Double every second element and check for overflow\nfor (idx = 1; idx < 16; idx += 2)\n{\n    digits[idx] = 2 * digits[idx];\n    if (digits[idx] > 9) digits[idx] = digits[idx] - 9;\n}\n\n// Calculate the sum\nsum = 0;\nfor (idx = 0; idx < 16; ++idx)\n{\n    sum = sum + digits[idx];\n}\n
Run Code Online (Sandbox Code Playgroud)\n

如果您必须接收数字形式的输入,请首先调用将数字转换为数字数组的函数。您可以在 SO 上找到很多很多如何完成转换的示例。这里将整数转换为数字数组只是众多示例之一。

\n