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

CS50 Pset1 Credit求助:分函数实现程序失效原因及正确方案

CS50 Pset1 Credit问题分函数实现故障排查与修复

代码失效原因分析

  • Luhn算法逻辑完全错误:
    • 第一个循环错误使用原始卡号cn取模,而非当前迭代的ccn,导致累加的始终是卡号最后一位;
    • 第一个循环结束后ccn已变为0,执行ccn = ccn/10后仍为0,处理乘2位的第二个循环根本不会执行;
    • checksum函数内部直接输出INVALID,会与main函数中的输出重复。
  • 卡号长度计算死循环:
    • 计算长度时用ccn = ccn % 10,导致ccn始终等于卡号最后一位(非0时),循环无限执行。
  • 首位数字提取逻辑错误:
    • 长度计算错误导致divisor值错误,且ccn在长度计算后已被破坏,无法正确提取首位数字。
  • MasterCard校验条件错误:
    • 条件first_twodigit > 50 && first_twodigit == 56永远不成立,正确范围应为51-55。
  • VISA输出格式错误:
    • 输出VISA时缺少换行符,不符合题目要求。

分函数实现的正确方案

将功能拆分为输入、校验、长度计算、首位提取等独立函数,每个函数职责单一:

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

// 函数声明
long get_credit_number(void);
int calculate_checksum(long card_num);
int get_card_length(long card_num);
int get_first_two_digits(long card_num, int length);
int get_first_digit(long card_num, int length);

int main(void)
{
    long card_num = get_credit_number();
    
    // 先校验Luhn算法
    if (!calculate_checksum(card_num))
    {
        printf("INVALID\n");
        return 0;
    }
    
    int length = get_card_length(card_num);
    int first_two = get_first_two_digits(card_num, length);
    int first = get_first_digit(card_num, length);
    
    // 判断卡类型
    if (length == 15 && (first_two == 34 || first_two == 37))
    {
        printf("AMEX\n");
    }
    else if (length == 16 && (first_two >= 51 && first_two <= 55))
    {
        printf("MASTERCARD\n");
    }
    else if ((length == 13 || length == 16) && first == 4)
    {
        printf("VISA\n");
    }
    else
    {
        printf("INVALID\n");
    }
    
    return 0;
}

// 获取合法的信用卡号输入
long get_credit_number(void)
{
    long num;
    do
    {
        num = get_long("Number: ");
    } while (num <= 0);
    return num;
}

// 实现Luhn算法校验
int calculate_checksum(long card_num)
{
    int sum = 0;
    long temp = card_num;
    int is_second = 0; // 标记是否是从右数第二位(需要乘2的位)
    
    while (temp > 0)
    {
        int digit = temp % 10;
        if (is_second)
        {
            digit *= 2;
            sum += digit / 10 + digit % 10;
        }
        else
        {
            sum += digit;
        }
        is_second = !is_second;
        temp /= 10;
    }
    
    return (sum % 10 == 0);
}

// 计算卡号长度
int get_card_length(long card_num)
{
    int length = 0;
    long temp = card_num;
    while (temp > 0)
    {
        length++;
        temp /= 10;
    }
    return length;
}

// 获取卡号前两位数字
int get_first_two_digits(long card_num, int length)
{
    long divisor = 1;
    for (int i = 0; i < length - 2; i++)
    {
        divisor *= 10;
    }
    return card_num / divisor;
}

// 获取卡号第一位数字
int get_first_digit(long card_num, int length)
{
    long divisor = 1;
    for (int i = 0; i < length - 1; i++)
    {
        divisor *= 10;
    }
    return card_num / divisor;
}

代码说明

  • get_credit_number:负责获取用户输入,确保输入为正整数;
  • calculate_checksum:正确实现Luhn算法,从右往左遍历每一位,交替处理乘2和直接累加的逻辑;
  • get_card_length:通过不断除以10计算卡号位数;
  • get_first_two_digits和get_first_digit:根据卡号长度计算除数,提取对应首位数字;
  • main函数仅负责调用各功能函数,判断最终卡类型,逻辑清晰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 11:45:43