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

CS50x PSET01 Credit程序无法输出VISA/MASTERCARD/AMEX求助

CS50x PSET1 Credit作业问题排查

问题描述

运行CS50x PSET1的Credit程序时,输入合法卡号会重复提示“Card no: ”,输入无效卡号能正确输出“INVALID”,但无法识别并输出VISA、MASTERCARD、AMEX卡种。以下是代码及编译警告信息:

代码

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

int main(void)
{
    long card;
    do
    {
        card = get_long("Card no: ");
    } while (card < 0); // Card number must be greater than 0.

    int card1, card2, card3, card4, card5, card6, card7, card8;
    card1 = ((card % 100) / 10) * 2;
    card2 = ((card % 10000) / 1000 * 2);
    card3 = ((card % 1000000) / 100000 * 2);
    card4 = ((card % 100000000) / 10000000 * 2);
    card5 = ((card % 10000000000) / 1000000000 * 2);
    card6 = ((card % 1000000000000) / 100000000000 * 2);
    card7 = ((card % 100000000000000) / 10000000000000 * 2);
    card8 = ((card % 10000000000000000) / 1000000000000000 * 2);

    card1 = (card1 % 100 / 10) + (card1 % 10);
    card2 = (card1 % 100 / 10) + (card2 % 10);
    card3 = (card1 % 100 / 10) + (card3 % 10);
    card4 = (card1 % 100 / 10) + (card4 % 10);
    card5 = (card1 % 100 / 10) + (card5 % 10);
    card6 = (card1 % 100 / 10) + (card6 % 10);
    card7 = (card1 % 100 / 10) + (card7 % 10);
    card8 = (card1 % 100 / 10) + (card8 % 10);

    int sum1 = card1 + card2 + card3 + card4 + card5 + card6 + card7 + card8;

    // Now we need to find the digits that are not multiplied by 2.

    int card9, card10, card11, card12, card13, card14, card15, card16;
    card9 = (card % 10);
    card10 = ((card % 1000) / 100);
    card11 = ((card % 100000) / 10000);
    card12 = ((card % 10000000) / 1000000);
    card13 = ((card % 1000000000) / 100000000);
    card14 = ((card % 100000000000) / 10000000000);
    card15 = ((card % 10000000000000) / 1000000000000);
    card16 = ((card % 1000000000000000) / 100000000000000);

    int sum2 = card9 + card10 + card11 + card12 + card13 + card14 + card15 + card16;
    int sum3 = sum1 + sum2;

    int length = 0;
    long visa = card;
    long master = card;
    long amex = card;

    if ((sum3 % 10) != 0)
    {
        printf("%s\n", "INVALID");
        return 0;
    }
    // Now we need to differentiate between VISA, Master and Amex.
    while (card > 0)
    {
        card = card / 10;
        length++;
    }

    // Identify if the card is VISA.
    while (visa >= 10)
    {
        visa /= 10;
    }
    if (visa == 4 && (length == 13 || length == 16))
    {
        printf("%s\n ", "VISA");
        return 0;
    }

    // Identify if the card is AMEX
    while (amex >= 10000000000000)
    {
        amex /= 10000000000000;
    }
    if (length == 15 && (amex == 34 || amex == 37))
    {
        printf("%s\n", "AMEX");
        return 0;
    }

    // Identify  if the card is MASTER
    while (master >= 100000000000000)
    {
        master /= 100000000000000;
    }
    if (length == 16 && (master == 51 || master == 52 || master == 53 ||
                         master == 54 || master == 55 || master == 56))
    {
        printf("%s\n", "MASTERCARD");
        return 0;
    }
    else
        printf("%s\n", "INVALID");
    return 0;
}

编译警告信息

credit.c: In function 'main':
credit.c:17:13: warning: conversion to 'int' from 'long long int' may alter its value [-Wconversion]
     card5 = ((card % 10000000000) / 1000000000 * 2);
             ^

credit.c:18:13: warning: conversion to 'int' from 'long long int' may alter its value [-Wconversion]
     card6 = ((card % 1000000000000) / 100000000000 * 2);
             ^

credit.c:19:13: warning: conversion to 'int' from 'long long int' may alter its value [-Wconversion]
     card7 = ((card % 100000000000000) / 10000000000000 * 2);
             ^
credit.c:20:13: warning: conversion to 'int' from 'long long int' may alter its value [-Wconversion]
     card8 = ((card % 10000000000000000) / 1000000000000000 * 2);
             ^

credit.c:41:14: warning: conversion to 'int' from 'long long int' may alter its value [-Wconversion]
     card14 = ((card % 100000000000) / 10000000000);
              ^

credit.c:42:14: warning: conversion to 'int' from 'long long int' may alter its value [-Wconversion]
     card15 = ((card % 10000000000000) / 1000000000000);
              ^


credit.c:43:14: warning: conversion to 'int' from 'long long int' may alter its value [-Wconversion]
     card16 = ((card % 1000000000000000) / 100000000000000);
              ^

credit.c:77:17: warning: comparison is always false due to limited range of data type [-Wtype-limits]
     while (amex >= 10000000000000)
                 ^~

credit.c:79:17: warning: conversion to 'long int' from 'long long int' may alter its value [-Wconversion]
         amex /= 10000000000000;
                 ^~~~~~~~~~~~~~

credit.c:88:19: warning: comparison is always false due to limited range of data type [-Wtype-limits]
     while (master >= 100000000000000)
                   ^~

credit.c:90:19: warning: conversion to 'long int' from 'long long int' may alter its value [-Wconversion]
         master /= 100000000000000;
                   ^~~~~~~~~~~~~~~

问题分析与修复

1. 变量类型溢出导致重复提示

card被定义为long类型,但get_long()返回的是long long。信用卡号(13-16位)远超过32位long的最大值(2147483647,仅10位),赋值后card会变成负数,触发do-while循环的card < 0条件,导致重复提示输入。

  • 修复:将card、visa、master、amex全部改为long long类型,避免数值溢出。

2. Luhn校验计算错误

计算sum1时,card2到card8的拆分逻辑错误,错误使用了card1的十位数字而非自身的十位数字,导致sum1计算结果错误,合法卡号也会因Luhn校验不通过被判定为无效。

  • 修复:每个变量拆分自身的十位和个位相加:
    card1 = (card1 / 10) + (card1 % 10);
    card2 = (card2 / 10) + (card2 % 10);
    card3 = (card3 / 10) + (card3 % 10);
    // 以此类推card4到card8
    

3. 卡种识别逻辑失效

  • AMEX和MASTERCARD的循环条件永远为假:amex是long类型,而10000000000000(10^13)超过了32位long的最大值,导致循环无法执行,无法提取正确前缀。
  • 计算卡号长度时修改了原始card变量,导致后续提取前缀时使用的是已修改后的值。
  • 修复:
    1. 计算卡号长度时使用临时变量,保留原始card值:
      long long temp = card;
      while (temp > 0) {
          temp /= 10;
          length++;
      }
      
    2. 通过统一方式提取前缀,避免大数字比较:
      // 提取前两位数字
      long long prefix = card;
      while (prefix >= 100) {
          prefix /= 10;
      }
      int first_two = prefix;
      int first_one = prefix / 10;
      
    3. 根据长度和前缀判断卡种:
      // VISA判断
      if ((length == 13 || length == 16) && first_one == 4) {
          printf("VISA\n");
          return 0;
      }
      // AMEX判断
      if (length == 15 && (first_two == 34 || first_two == 37)) {
          printf("AMEX\n");
          return 0;
      }
      // MASTERCARD判断(有效前缀为51-55)
      if (length == 16 && first_two >= 51 && first_two <= 55) {
          printf("MASTERCARD\n");
          return 0;
      }
      

4. 其他小问题

  • MASTERCARD前缀范围错误:代码中包含了56,实际有效前缀是51-55,需修正。
  • VISA输出多了空格:printf("%s\n ", "VISA");改为printf("VISA\n");。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 01:54:50