输入评分10时C语言程序输出垃圾值的原因及解决方案求助
C程序输入评分10时直方图出现垃圾值的问题分析与解决
我写了一个记录食物评分、理由并生成直方图的C语言程序,但当输入评分值为10时,程序输出的直方图会出现垃圾值。以下是我的代码:
#include <stdio.h> #include <string.h> struct Food{ char* item; int rating; char reason[30]; char histogram[11]; }; void removeNewline(char* x){ char temp[30]; for(int i = 0; i < strlen(x)-1; i++){ temp[i] = x[i]; } temp[strlen(x)-1] = '\0'; strcpy(x, temp); } int main() { struct Food x[10]; x[0].item = "Burger"; x[1].item = "Broast"; x[2].item = "Rice"; x[3].item = "Roll"; x[4].item = "Handi"; x[5].item = "Platter"; x[6].item = "Kebabs"; x[7].item = "Sandwich"; x[8].item = "Shake"; x[9].item = "Kheer"; char sum[10]; for(int i = 0; i < 2; i++){ printf("\nEnter score for %s (1 - 10) : ", x[i].item); scanf("%d", &x[i].rating); fflush(stdin); printf("Enter reason for liking or disliking : "); fgets(x[i].reason, 30, stdin); removeNewline(x[i].reason); strcpy(sum, "*"); for(int j = 1; j < x[i].rating; j++){ strcat(sum, "*"); } strcpy(x[i].histogram, sum); } printf("\n%-13s%-11s%-35s%s\n", "Item", "Rating", "Reason", "Histogram"); for(int i = 0; i < 2; i++){ printf("%-13s%-11d%-35s%s\n", x[i].item, x[i].rating, x[i].reason, x[i].histogram); } return 0; }
问题原因分析
出现垃圾值的核心原因是缓冲区溢出:
- 你定义的
sum数组大小是char sum[10];,当评分是10时,需要生成10个*字符,再加上字符串结束符\0,总共需要11个字节的空间。但sum只有10字节,拼接第10个*时会超出数组边界,覆盖相邻内存区域的数据,导致输出出现垃圾值。 - 另外还有两个潜在问题:
fflush(stdin)是C标准未定义的行为,不同编译器(比如GCC和MSVC)处理方式不同,可能导致输入处理异常。- 你的
removeNewline函数逻辑有缺陷:如果输入的字符串没有换行符(比如刚好填满reason数组),strlen(x)-1会导致错误的索引,甚至可能修改字符串外的内存。
解决办法
我整理了几个关键修复点,同时优化了代码的安全性和效率:
扩展
sum数组的空间(可选,若保留原生成逻辑):
把char sum[10];改为char sum[11];,刚好容纳10个*加结束符。替换
fflush(stdin)为标准的换行符清理方式:
用while(getchar() != '\n');来吃掉scanf后留在输入缓冲区的换行符,这是C标准认可的做法。简化并修复
removeNewline函数:
直接用strchr找到换行符并替换为\0,避免原函数的索引错误问题:void removeNewline(char* x){ char* newline = strchr(x, '\n'); if(newline != NULL){ *newline = '\0'; } }优化直方图生成逻辑(推荐):
不用循环调用strcat(效率低且容易出错),直接用memset快速填充*字符,然后手动添加结束符:memset(x[i].histogram, '*', x[i].rating); x[i].histogram[x[i].rating] = '\0';这样可以彻底避免
sum数组带来的缓冲区问题,直接操作histogram数组即可。
修改后的完整代码
#include <stdio.h> #include <string.h> struct Food{ char* item; int rating; char reason[30]; char histogram[11]; }; void removeNewline(char* x){ char* newline = strchr(x, '\n'); if(newline != NULL){ *newline = '\0'; } } int main() { struct Food x[10]; x[0].item = "Burger"; x[1].item = "Broast"; x[2].item = "Rice"; x[3].item = "Roll"; x[4].item = "Handi"; x[5].item = "Platter"; x[6].item = "Kebabs"; x[7].item = "Sandwich"; x[8].item = "Shake"; x[9].item = "Kheer"; for(int i = 0; i < 2; i++){ printf("\nEnter score for %s (1 - 10) : ", x[i].item); scanf("%d", &x[i].rating); // 清理输入缓冲区的换行符(替代fflush(stdin)) int c; while((c = getchar()) != '\n' && c != EOF); printf("Enter reason for liking or disliking : "); fgets(x[i].reason, 30, stdin); removeNewline(x[i].reason); // 直接生成直方图,无需sum数组 memset(x[i].histogram, '*', x[i].rating); x[i].histogram[x[i].rating] = '\0'; } printf("\n%-13s%-11s%-35s%s\n", "Item", "Rating", "Reason", "Histogram"); for(int i = 0; i < 2; i++){ printf("%-13s%-11d%-35s%s\n", x[i].item, x[i].rating, x[i].reason, x[i].histogram); } return 0; }
这样修改后,输入评分10时就能正确显示10个*,不会出现垃圾值,同时输入处理也更稳定。
内容的提问来源于stack exchange,提问作者emperor_c
相关产品推荐
相关产品推荐

