【问题标题】:Why is my PSET1 Credit working in sandbox but not Check50?为什么我的 PSET1 Credit 可以在沙盒中工作,但不能在 Check50 中工作?
【发布时间】:2020-01-22 20:15:00
【问题描述】:

我的 PSET1 信用计划在 CS50 沙盒中运行的位置有问题,并且能够根据卡的长度和 Luhn 算法确定卡是 MasterCard、AMEX 还是 VISA。但是,当我将代码提交给 Check50 时,它确定所有输入都是无效的。

更新:如果数字不符合 Luhn 的算法,而不是打印“INVALID”,我将其更改为打印“nope”,并发现 check50 检查的所有数字都会输出“nope”,所以我知道该错误位于程序的该部分中。和以前一样,它仍然可以在沙盒中运行。

我已经在这里和其他地方寻找过类似的问题和解决方案。

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

int main(void)
{
    //Ask user to input number.
    long card_num;
    do
    {
        card_num = get_long("Number: ");   
    }
    //Check if card number is greater than zero.
    while (card_num < 0);

    //Starting with the second to last digit, multiply each digit by 2.
    //Add the products' digits together.
    int digit, prod, sum1, dig1, dig2;
    long holder = card_num;
    while (holder > 0)
    {
        digit = (holder / 10) % 10;
        prod = digit * 2;
        if (prod >= 10)
        {
            dig1 = (prod % 100 - (prod % 10)) / 10;
            dig2 = prod % 10;
            prod = dig1 + dig2;
        }
        sum1 = sum1 + prod;
        holder = holder / 100;
    }

    //Add sum1 to product of the other digits in the card number
    long holder1 = card_num;
    int dig3, sum2;
    while (holder1 > 0)
    {
        dig3 = holder1 % 10;
        sum2 = sum2 + dig3;
        holder1 = holder1 / 100;
    }

    //Check if the sum of the first and second sums has a final digit of 0.
    int last_sum = sum1 + sum2;
    if (last_sum % 10 != 0)
    {
        printf("INVALID\n");
    }
    else
    {
        //Calculate number of digits
    int num_digits = 0;
    long holder3 = card_num;
    while (holder3 != 0)
    {
        holder3 = holder3 / 10;
        num_digits++;
    }

    //Find first two digits of card number
    long holder2 = card_num;
    while (holder2 > 100)
    {
         holder2 = holder2 / 10;
    }
    int firstdig, secdig;
    secdig = holder2 % 10;
    firstdig = holder2 / 10;

    //Check if VISA, Mastercard, or AMEX
    if (firstdig == 4)
    {
        if (num_digits == 13 || num_digits == 16)
        {
            printf ("VISA\n");
        }
    }
    else if (firstdig == 5 && secdig >= 1 && secdig <= 5)
    {
        if (num_digits == 16)
        {
            printf ("MASTERCARD\n");
        }
    }
    else if (firstdig == 3 && (secdig == 4 || secdig == 7))
    {
        if (num_digits == 15)
        {
            printf ("AMEX\n");
        }
    }
    else (printf("INVALID\n"));
    }
}

预期结果为 MASTERCARD、VISA、AMEX 或 INVALID。在沙盒中它可以工作,但 Check50 对所有数字都无效。

【问题讨论】:

  • 使用:else if (firstdig == 3 &amp;&amp; (secdig == 4 || secdig == 7)) { if (num_digits == 15) { printf ("AMEX\n"); } } 为例:如果输入第一个 'if()' 而第二个 'if()' 失败,则不输出任何内容。但是,应该输出一些错误指示
  • OT:强烈建议将get_long() 的调用替换为:scanf( "%lu", &amp;card_num );,因为头文件:cs50.h 不可移植和/或无法在任何地方使用

标签: c cs50 luhn


【解决方案1】:

不同的系统可以有不同的实现一个'long'的大小。

建议使用stdint.h 中的uint64_t,因为

  1. 在不同的系统/实现中将始终保持相同的大小
  2. 该值需要是无符号的,因为移动有符号值是有问题的。

调用scanf()时,建议使用格式说明符:SCNu64

SCNu64 来自inttypes.h

scanf() 的示例

uint64_t card_num;
scanf( "%" SCNu64, &card_num );

how to validate a credit card number

记下信用卡号的最后一位。这是您将用于验证信用卡号剩余部分的校验和数字。

列出信用卡号的每个数字,从校验和左侧的数字开始,向左移动。如果信用卡号有 16 位数字,请将奇数位置的每个数字的数量翻倍,从右到左排列,然后再将其添加到您的列表中。对于有 15 位数字的信用卡,您可以将偶数位置的数字加倍。如果将一个数字加倍得到一个大于 10 的数字,请将新数字的两个数字相加,并将该结果写在您的列表中。例如,如果卡片上的数字是 7,则将其加倍将得到 14。那么这两个数字的总和将是 5。

总计您的数字列表。不要在总数中包含校验和数字。如果总数可以被 10 整除,则信用卡有一个有效号码。如果没有,您不应该处理信用卡交易。


How to determine supplier of credit card

通过查看第一个数字来识别银行卡的信用公司。以“3”开头的卡是美国运通卡。以“4”开头的为 Visa 信用卡和借记卡,以“5”开头的为 MasterCard 信用卡和借记卡,以“6”开头的为 Discover 信用卡。向商户收取的服务费因卡公司而异。

计算信用卡号中的位数。大多数信用卡应包含 15 位或 16 位数字。美国运通信用卡包含 15 个。其他三大信用卡公司——Visa、Mastercard 和 Discover——在他们的卡上都有一个 16 位的序列。

【讨论】:

  • 我将变量的类型从 long 更改为 uint64_t,但这并没有解决问题并产生了另一个问题。 check50 评分者仍然认为所有数字都是无效的,现在不拒绝非数字输入,它只是输出它们是无效的。
  • OP 发布的代码没有实施必要的算法来正确验证卡,也没有实施必要的测试来确定哪家信用卡公司提供了卡
【解决方案2】:

我发现问题在于我声明了变量 sum1 和 sum2,但没有将它们初始化为任何值,因此它们被分配了内存中的任何值。当我将这些也初始化为 0 时,程序运行没有问题。

【讨论】:

    猜你喜欢
    • 2018-06-13
    • 2019-05-04
    • 1970-01-01
    • 2020-03-15
    • 2013-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-28
    相关资源
    最近更新 更多