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

C语言中for循环后未被显式修改的inputLen变量莫名变为0的原因排查

嘿,我帮你揪出了这个奇怪bug的根源——栈内存越界覆盖!

你的inputLen变量在循环后莫名变为0,核心原因是栈数组越界访问,覆盖了相邻的局部变量inputLen,下面给你详细拆解:

具体问题分析

在credit_test函数里,你声明了一个大小为16的栈数组evenArr[16],而inputLen作为同函数的局部变量,在C语言的栈内存布局中,它和evenArr是连续分配的(刚好在数组的相邻位置)。

看你处理偶数位的循环逻辑:

for(int i = 0; inputLen > i; i++) {
    int n = i * 2;
    evenArr[evenIndex] = input[n] * 2;
    // ... 数字拆分逻辑
    if(evenArr[evenIndex] > 9) {
        // ... 拆分两位数
        evenIndex++; // 这里evenIndex额外加1
    }
    evenIndex++; // 每次循环必加1
    evenSum += evenArr[i];
}

这里的evenIndex完全没有上限约束:

  • 当输入卡号长度是16时,循环会执行16次;
  • 每次循环至少让evenIndex加1,遇到需要拆分的数字(比如5*2=10)时,evenIndex还会额外再加1;
  • 很快evenIndex就会超过16(evenArr的最大合法索引是15),此时evenArr[evenIndex]就会访问到栈上数组之外的内存——而这个位置正好是inputLen的存储地址,越界写入的数据直接把inputLen覆盖成了0。

代码里的其他潜在问题

除了这个核心bug,还有几个需要修正的点:

  1. 字符转数字逻辑错误:你用input[n] * 2后减96是错的——数字字符的ASCII值是48~57(比如'0'是48),正确转换应该是input[n] - '0'(或减48),先转成数字再做乘法。
  2. 奇数位循环的越界风险:你写的for(int i = 0; 16 > i; i++)不管卡号长度是15还是16,都会循环16次,会访问input数组的越界位置。
  3. Luhn算法索引逻辑搞反:标准Luhn算法是从右往左数偶数位(倒数第2、4、6...位)乘以2,你原来从左往右取第0、2、4...位,会导致校验结果错误。

修复后的代码示例

其实根本不需要用数组存储每一位的计算结果,直接边计算边累加就能避免数组越界问题,同时修正算法逻辑:

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

int credit_test(string input);

int main(void) {
    string userInput;
    bool isInvalid = false;
    do {
        userInput = get_string("Number: ");
        isInvalid = false;
        int len = strlen(userInput);
        // 先校验长度是否合法
        if(len != 13 && len != 15 && len != 16) {
            isInvalid = true;
            continue;
        }
        // 校验每个字符是否都是数字
        for(int i = 0; i < len; i++) {
            if(userInput[i] < '0' || userInput[i] > '9') {
                isInvalid = true;
                break;
            }
        }
    } while(isInvalid);
    credit_test(userInput);
    return 0;
}

int credit_test(string input) {
    int inputLen = strlen(input);
    int evenSum = 0;
    int oddSum = 0;

    // 处理Luhn算法的偶数位(从右往左数第2、4、6...位)
    for (int i = inputLen - 2; i >= 0; i -= 2) {
        int num = input[i] - '0';
        int doubled = num * 2;
        // 拆分两位数:等价于把十位和个位相加,比如10=1+0=1,即10-9=1
        evenSum += (doubled > 9) ? (doubled - 9) : doubled;
    }

    // 处理奇数位(从右往左数第1、3、5...位)
    for (int i = inputLen - 1; i >= 0; i -= 2) {
        oddSum += input[i] - '0';
    }

    int finalSum = evenSum + oddSum;
    printf("Final Sum: %i\n", finalSum);

    // 修正卡种判断逻辑(符合各卡组织的真实规则)
    if (finalSum % 10 == 0) {
        if (inputLen == 16 && input[0] == '5' && input[1] >= '1' && input[1] <= '5') {
            printf("MasterCard\n");
        } else if ((inputLen == 13 || inputLen == 16) && input[0] == '4') {
            printf("Visa\n");
        } else if (inputLen == 15 && (input[0] == '3' && (input[1] == '4' || input[1] == '7'))) {
            printf("Amex\n");
        } else {
            printf("Invalid\n");
        }
    } else {
        printf("Invalid\n");
    }

    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 14:43:12