为了在 Luhn 算法中获得正确的数字,我的 C 代码中缺少什么?

What am i missing in my C code in order to achieve the right number in Luhn’s Algorithm?

我是 C 语言编程的新手,我正在尝试解决 CS50 的 pset1 问题,Luhn 的算法来检查信用卡是否有效。 我用来测试的示例是这张卡 Visa:4003600000000014.

As referred in the problem, first underline every other digit, starting with the number’s second-to-last digit:

[4] 0 [0] 3 [6] 0 [0] 0 [0] 0 [0] 0 [0] 0 [1] 4

Multiply the underlined digits by 2:

1•2 + 0•2 + 0•2 + 0•2 + 0•2 + 6•2 + 0•2 + 4•2

That gives:

2 + 0 + 0 + 0 + 0 + 12 + 0 + 8

Add those products’ digits (i.e., not the products themselves) together:

2 + 0 + 0 + 0 + 0 + 1 + 2 + 0 + 8 = 13
#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main(void)
{

    // Variable assignment
    long card;
    int case1, case2, mod, mod2;

    // Get input from user
    do
    {
        card = get_long("Card: ");
    }
    while (card <= 0);

    // Case 1
        for (long checksum = card; checksum > 0; checksum = checksum / 10)
    {

        mod = remainder(checksum, 10) * 2;
        if (mod >= 10)
        {
            mod2 = remainder (mod, 10);
            case1 = case1 + mod2;
            mod = mod / 10;
            case1 = case1 + mod;
        }
        else
        {
            case1 = case1 + mod;
        }
        checksum = checksum / 10;
        printf("\n%d", case1);
    }
}

我的输出:

~/pset1/credit/ $ ./credit 
Card: 4003600000000014

8
8
8
8
8
8
14
14

打印出来的数字应该是13,不知道为什么我打印出来的数字是14。 尽管我得到 2 和 -6 的输出,但我已尝试更改代码。也试过 CS50 调试工具,但没有成功。 为了输出 13,我的代码缺少什么?

您从 最后 位而不是倒数第二位开始,因此您使用的是错误的一组数字。

您需要从数字 / 10 开始才能获取倒数第二个数字。

for (long checksum = card / 10; checksum > 0; checksum = checksum / 10)
  1. 这不是 minimal reproducible exampleget_long 不是标准的 C 函数,因此您必须包含另一个头文件才能编译此代码。请求调试帮助时,请始终提供完整示例。

  2. case1 未初始化。将其初始化为零。

  3. checksum 被初始化为 card,并且循环检查从最后一位开始的每隔一个数字。所以它对你不想以这种方式添加的数字进行操作。更改循环,使 checksumcard/10.

    开头
  4. remainder 是一个 double 函数。混合使用浮点运算和整数运算通常是不明智的,尤其是当您不熟悉浮点运算时。调用 remainder 会将其操作数转换为 double,这可能会导致舍入错误,在这种情况下会产生不需要的结果。

  5. remainder 提供对称余数;它 returns [−y/2, +y/2] 中的一个值,其中 y 是第二个操作数。您不想要负值。请改用整数余数运算符 %

  6. 避免对信用卡“号码”使用整数类型。信用卡“号码”更恰当地是数字串的标识符——它们的数值与其目的无关(例如,它们不是发行卡的数量),并且在某些 C 实现中, long 类型不够宽,无法表示整个“数字”。字符数组就足够了,尽管您必须将数字字符(“0”到“9”)转换为数字值(“0”到“9”),这可以通过减去字符常量 '0' 来自数字字符代码。

不要打印 "\n%d"。将您的输出安排为将换行符放在最后,除非您即将接受输入并希望提示与输入在同一行,或者您故意不希望文本必须输出。通常,终端(物理或虚拟)的标准输出是行缓冲的,这意味着在发送换行符、缓冲区已满、请求输入或手动刷新缓冲区之前,输出不会出现在用户面前。