C语言数组字符存储值非ASCII值异常及代码仍可运行的原因问询
问题分析与修复方案
嘿,我来帮你拆解这两个问题,顺便把代码里的坑给你捋清楚~
1. 为什么数组中存储的字符值显示为随机数而非ASCII值?
核心问题出在输入缓冲区处理不当和未初始化变量:
- 输入残留的换行符被误读:在
arrayFiller函数中,用scanf("%d", &v[i])读取数字后,你按下的回车键(ASCII码10)会留在输入缓冲区里。下一次循环到偶数索引(需要读取字符)时,scanf("%c")会直接读取这个换行符,而不是你输入的目标字符。如果某次输入数字时出错(比如输入了字母),scanf会失败,对应的数组元素根本没被赋值,保留了栈内存的随机初始值——这就是你看到的“随机数”。 - 同一字符存储值不匹配:比如第一次输入
'e'时成功存了ASCII码101,但第二次可能读的是残留的换行符或其他缓冲区垃圾数据,或者因为输入处理失败存了随机值,所以两次数值不一样。 - 类型匹配小问题:
CharlessOn函数里的charless是int类型,但用%c格式符读取,虽然能存储,但结合输入缓冲区的问题,更容易出现错误读取的情况。
2. 为什么异常情况下代码仍能正常运行?
这是C语言的特性——它信任程序员会处理好内存和输入:
- 局部数组
vec是在栈上声明的,未初始化的元素会保留栈上的原有随机值,但只要你没有访问数组边界外的内存(你的循环都在SIZE=10范围内),程序就不会立刻崩溃。 - C语言不会自动检查输入操作是否成功,也不会强制初始化局部变量,所以即使有错误数据,程序还是会继续执行,只是输出结果不符合预期而已。这种“看似正常运行”其实是很多隐蔽bug的来源。
修复后的代码
我把几个关键坑都修好了,你可以参考:
#include <stdio.h> #include <string.h> // 新增,用于处理换行符 #define SIZE 10 void arrayFiller(int v[]); void charTimes(int v[]); void arrayPrinter(int v[]); void CharlessOn(int v[]); void stringToDigit(char string_num[]); int main() { int vec[SIZE] = {0}; // 初始化数组,避免随机值干扰 char string_num[50]; arrayFiller(vec); arrayPrinter(vec); charTimes(vec); CharlessOn(vec); // 替换废弃的gets,用fgets更安全 printf("\n请输入一个数字字符串:"); fgets(string_num, sizeof(string_num), stdin); // 去掉fgets读取的换行符 string_num[strcspn(string_num, "\n")] = '\0'; stringToDigit(string_num); return 0; } void arrayFiller(int v[]) { printf("请输入字符和数字,重复5次:\n"); printf("字符是要打印的内容,数字是打印次数(1-10)\n"); for (int i = 0; i < SIZE; i++) { int checker = 0; if (i % 2 == 0) { // 用" %c"跳过所有空白字符(换行、空格等) scanf(" %c", &v[i]); } else { do { if (checker > 0) printf("数字必须在1-10之间,请重新输入:\n"); // 检查scanf是否成功,避免输入错误导致死循环 if (scanf("%d", &v[i]) != 1) { // 清空输入缓冲区的错误内容 while (getchar() != '\n'); v[i] = 0; // 重置为0,避免随机值 } checker++; } while (v[i] < 1 || v[i] > 10); } } } void charTimes(int v[]) { int k = 1; printf("\n按次数打印字符:\n"); for (int i = 0; i < SIZE; i += 2) { for (int j = 0; j < v[k]; j++) { printf("%c,", v[i]); } k += 2; } } void arrayPrinter(int v[]) { printf("\n你的数组内容(ASCII值):\n"); for (int i = 0; i < SIZE; i++) { printf("%d,", v[i]); } } void CharlessOn(int v[]) { char charless; // 改为char类型,匹配%c格式符 int k = 1; printf("\n请输入要移除的字符:"); scanf(" %c", &charless); // 同样加空格跳过空白字符 printf("你选择的字符ASCII值:%d\n", charless); printf("\n移除指定字符后的结果:\n"); for (int i = 0; i < SIZE; i += 2) { if (v[i] != charless) { // 先判断,再循环打印 for (int j = 0; j < v[k]; j++) { printf("%c,", v[i]); } } k += 2; } } void stringToDigit(char string_num[]){ int number = 0; for(int i = 0; string_num[i] != '\0'; i++){ // 用'\0'判断字符串结束,不是NULL if (string_num[i] >= '0' && string_num[i] <= '9') { // 增加输入合法性判断 number *= 10; number += (string_num[i] - '0'); // 用'0'代替48,可读性更好 } } printf("\n转换后的数字是:%d", number); }
内容的提问来源于stack exchange,提问作者alenkogen
相关产品推荐
相关产品推荐

