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

输入评分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个*时会超出数组边界,覆盖相邻内存区域的数据,导致输出出现垃圾值。
  • 另外还有两个潜在问题:
    1. fflush(stdin)是C标准未定义的行为,不同编译器(比如GCC和MSVC)处理方式不同,可能导致输入处理异常。
    2. 你的removeNewline函数逻辑有缺陷:如果输入的字符串没有换行符(比如刚好填满reason数组),strlen(x)-1会导致错误的索引,甚至可能修改字符串外的内存。

解决办法

我整理了几个关键修复点,同时优化了代码的安全性和效率:

  1. 扩展sum数组的空间(可选,若保留原生成逻辑):
    把char sum[10];改为char sum[11];,刚好容纳10个*加结束符。

  2. 替换fflush(stdin)为标准的换行符清理方式:
    用while(getchar() != '\n');来吃掉scanf后留在输入缓冲区的换行符,这是C标准认可的做法。

  3. 简化并修复removeNewline函数:
    直接用strchr找到换行符并替换为\0,避免原函数的索引错误问题:

    void removeNewline(char* x){
        char* newline = strchr(x, '\n');
        if(newline != NULL){
            *newline = '\0';
        }
    }
    
  4. 优化直方图生成逻辑(推荐):
    不用循环调用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 05:42:43