C语言小于10数值累加函数输入非法字符触发未定义行为排查
问题根因
你的代码触发未定义行为的核心原因是完全没有校验scanf的调用结果,且输入合法性判断逻辑完全错误,具体问题点如下:
scanf("%d", &inputNumber)匹配输入失败时(比如输入字符h),不会对inputNumber做任何赋值。inputNumber是栈上的局部变量,未初始化时存储的是随机栈垃圾值,你直接把这个随机值作为变长数组长度、循环上限传入tizAlatti,会导致内存越界访问,属于典型未定义行为。- 你写的校验逻辑
if(inputNumber % 1 != 0 && (isdigit(inputNumber) == 0))永远不会生效:inputNumber是int类型,任何整数对1取模的结果恒为0,条件前半段永远为假,整个if块永远不会执行。isdigit()函数的作用是判断传入的ASCII值是否对应数字字符,不是判断变量是不是数字,逻辑完全不符合你的校验需求。
- 输入
5.6时,%d格式符只会匹配小数点前的5赋值给inputNumber,小数点和后面的6会残留在输入缓冲区中,被后续循环里的第一个scanf("%f")直接读走,程序不会等待你输入第一个元素,直接跑后续逻辑,和你预期的执行流程完全不符。 - 另外
tizAlatti函数里的scanf("%f")同样没有做返回值校验,一旦输入非法内容,arr[i]会保持未初始化状态,读取未初始化的浮点数同样属于未定义行为。
修复方案
- 所有
scanf调用必须检查返回值:scanf会返回成功匹配并赋值的字段个数,返回值不等于预期个数时直接判定输入非法,报错退出。 - 删除完全无效的原有if校验块,整数输入合法性完全通过
scanf返回值判断,同时增加输入值合法性判断(比如元素个数不能为负数)。 - 读完整数输入后,清空输入缓冲区中残留的字符,避免残留内容被后续输入接口误读。
修复后的可运行代码如下:
#include <stdio.h> #include <stdlib.h> #include <ctype.h> float tizAlatti(int inputCount); int main(){ int inputNumber; printf("Number of input elements: "); // 校验整数输入是否成功 if (scanf("%d", &inputNumber) != 1) { printf("Error encountered.\n"); exit(1); } // 校验输入个数合法性 if (inputNumber <= 0) { printf("Error: input count must be a positive integer.\n"); exit(1); } // 清空输入缓冲区残留内容 int c; while ((c = getchar()) != '\n' && c != EOF); printf("\n%.2f", tizAlatti(inputNumber)); return 0; } float tizAlatti(int inputCount){ float arr[inputCount], sum = 0; printf("\n"); for(int i = 0; i<inputCount; i++){ printf("Element %d: ", i+1); // 校验浮点数输入是否成功 if (scanf("%f", &arr[i]) != 1) { printf("Error: invalid numeric input.\n"); exit(1); } if(arr[i] < 10){ sum += arr[i]; } } return sum; }
内容的提问来源于stack exchange,提问作者István Csige
相关产品推荐
相关产品推荐

