You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CS50第1周信用卡检测代码问题:无法识别有效卡种

CS50 2023第1周信用卡检测作业问题排查

在完成CS50 2023第1周信用卡检测作业时,代码可识别无效案例,但无法正确识别AMEX、MASTERCARD、VISA的有效测试用例,怀疑问题出在calculate_sum函数,附上代码及报错信息,请求排查。

代码实现

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

long get_card_number(void);
int get_length(long cardno);
int calculate_sum(long cardno);
void printtype(int sum, int length_cardno, long cardno);


int main(void)
{

    long cardno = get_card_number();    // Get card number from user

    int length_cardno = get_length(cardno); // Calculate length of the card number

    int sum = calculate_sum(cardno);    // To calculate total = sum_digit + alt_digit + last_digit

    printtype(sum, length_cardno, cardno); // To check what type of credit card it is, based on the different parameters

}

long get_card_number(void) // Function to get the card number from the user
{
    long cardno;
    do
    {
        cardno = get_long("Number: ");
    }
    while(cardno < 0);
    return cardno;
}

int get_length(long cardno) // Function to get the length of the card and to get the length of altdigit*2
{
    int i;
    for(i = 0; cardno != 0; i++)
    {
        cardno = cardno/10;
    }
    return i;
}

int calculate_sum(long cardno) // Function to get sum of the digits
{
    int alt_digit = 0;
    int alt_sum = 0;
    int digit = 0;
    int sum = 0;
    int total = 0;
    int last_digit = cardno % 10;

    cardno = cardno/10; // To get rid of the last digit
    bool Alternate_number = true; // To start with 2nd last digit

    while(cardno > 0)
    {
        if(Alternate_number == true) // Alt digits are the 2nd last digit, 4th last digit, 6th last digit and so on (even)
        {
            alt_digit = cardno % 10;
            alt_digit = alt_digit*2;
            if(alt_digit >= 10)          // To add the first and second digits of the 2 digit alt product separately
            {
                int first_alt_digit = alt_digit/100;
                int second_alt_digit = alt_digit/10;
                alt_sum += first_alt_digit + second_alt_digit;
            }
            else
            {
                alt_sum += alt_digit;
            }
            cardno = cardno/10;
        }
        else    // Digits are the 3rd last digit, 5th last digit, 7th last digit and so on (odd)
        {
            digit = cardno % 10;
            sum += digit;
            cardno = cardno/10;
        }
        Alternate_number = !Alternate_number; // To keep alternating

    }
    total = alt_sum + sum + last_digit; // Adding both of them together along with the last digit we removed at the start
    return total;

}

void printtype(int sum, int length_cardno, long cardno) // Function to know the type of card
{
    int zero_or_not = sum % 10; // To only look at the unit's place to see if sum ends with 0
    int first_digit = 0;
    int second_digit = 0;

    if(length_cardno == 13) // If statement to know the first two digits of the credit card number
    {
        first_digit = cardno/10^13;
    }
    else if(length_cardno == 15)
    {
        first_digit = cardno/10^15;
        second_digit = cardno/10^14;
    }
    else if(length_cardno == 16)
    {
        first_digit = cardno/10^16;
        second_digit = cardno/10^15;
    }

    if((length_cardno == 13 || length_cardno == 15 || length_cardno == 16) && (zero_or_not == 0)) // If statement to print the card type based on length, and the first and second digits
    {
        if((length_cardno == 15) && (first_digit == 3) && (second_digit == 4 || second_digit == 7))
        {
            printf("AMEX\n");

        }
        else if(length_cardno == 16 && (first_digit == 5) && (second_digit == 1 || second_digit == 2 || second_digit == 3 || second_digit == 4 || second_digit == 5))
        {
            printf("MASTERCARD\n");
        }
        else if((length_cardno == 13 || length_cardno == 16) && (first_digit == 4))
        {
            printf("VISA\n");
        }
        else
        {
            printf("INVALID\n");
        }
    }
    else
    {
        printf("INVALID\n");
    }

}

测试报错信息

:( identifies 378282246310005 as AMEX
    expected "AMEX\n", not "INVALID\n"
:( identifies 371449635398431 as AMEX
    expected "AMEX\n", not "INVALID\n"
:( identifies 5555555555554444 as MASTERCARD
    expected "MASTERCARD\n", not "INVALID\n"
:( identifies 5105105105105100 as MASTERCARD
    expected "MASTERCARD\n", not "INVALID\n"
:( identifies 4111111111111111 as VISA
    expected "VISA\n", not "INVALID\n"
:( identifies 4012888888881881 as VISA
    expected "VISA\n", not "INVALID\n"
:( identifies 4222222222222 as VISA
    expected "VISA\n", not "INVALID\n"

已做修改

  • 将first_digit改为first_alt_digit,second_digit改为second_alt_digit
  • 补充alt_digit = first_alt_digit + second_alt_digit中的加号
  • 移除检查alt_digit长度的函数,改用alt_digit >= 10判断

问题排查与修复

代码存在两处关键错误:

1. calculate_sum函数的数字拆分错误

当alt_digit是两位数时,原代码用alt_digit/100获取十位数字,这会得到0(因为两位数除以100结果为0),导致计算的和错误。正确的拆分方式应该是用alt_digit/10取十位,alt_digit%10取个位,两者相加。

修改后的calculate_sum对应代码块:

if(alt_digit >= 10)
{
    alt_sum += (alt_digit / 10) + (alt_digit % 10);
}
else
{
    alt_sum += alt_digit;
}

2. printtype函数的首位数字获取错误

C语言中^是位异或运算符,不是幂运算符,原代码中cardno/10^13的计算逻辑完全错误,无法正确提取卡号的首位数字。正确的做法是先计算10的(卡号长度-1)次方作为除数,再用卡号除以该除数得到首位数字;第二位数字则用卡号除以(除数/10)后取模10。

修改后的printtype中获取首位数字的代码:

int zero_or_not = sum % 10;
int first_digit = 0;
int second_digit = 0;

// 计算用于提取首位数字的除数
long divisor = 1;
for (int i = 1; i < length_cardno; i++) {
    divisor *= 10;
}
first_digit = cardno / divisor;
if (length_cardno >= 2) {
    second_digit = (cardno / (divisor / 10)) % 10;
}

修复这两处错误后,即可正确识别所有有效信用卡测试用例。

内容的提问来源于stack exchange,提问作者King Brain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 02:26:58