C语言棒球选手打击率计算程序故障排查与修正需求
修正棒球选手打击率计算程序的三类错误
需求:编写C语言程序计算100名棒球选手的打击率,输入选手姓名(Name)、打数(at_bats)、安打数(hits)。当打击率≥0.50时备注为"High",否则为"Low",输出为表格形式,打击率公式:
Batting Ave = Hits/At_bats。当前代码设定
MAX=2,运行出现三类问题:
- 跨平台清屏命令
system("cls")报错- 第二名选手姓名重复显示为第一名的姓名
- 打击率计算结果均为0.000000,备注全部显示为Low
错误排查与修复方案
1. 跨平台清屏命令问题
system("cls")仅在Windows系统有效,Linux/macOS下会执行失败。解决方案是通过预编译指令判断操作系统,选择对应清屏命令:
- Windows环境:使用
system("cls") - Linux/macOS环境:使用
system("clear")
同时需要包含<stdlib.h>头文件以调用system()函数。
2. 姓名重复显示问题
这类问题通常是因为所有选手的姓名字段复用了同一内存空间(比如使用未分配独立内存的char *name指针),后续输入会覆盖之前的内容。修复方法是在结构体中为每个选手定义固定长度的字符数组(如char name[50];),确保每个姓名都有独立存储区域。
3. 打击率计算为0的问题
这是整数除法特性导致的:如果hits和at_bats都是整数类型,hits/at_bats会执行整数除法(结果取整),当hits < at_bats时结果直接为0。修复方法是将其中一个操作数强制转换为浮点型,比如(float)hits / at_bats,触发浮点除法得到精确的小数结果。
完整修正代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX 2 // 测试用,实际需求可修改为100 typedef struct { char name[50]; // 为每个选手分配独立的姓名存储空间 int at_bats; int hits; float batting_avg; char remark[10]; } Player; // 跨平台清屏函数 void clear_screen() { #ifdef _WIN32 system("cls"); #else system("clear"); #endif } int main() { Player players[MAX]; int i; clear_screen(); // 输入选手信息 for (i = 0; i < MAX; i++) { printf("请输入第%d名选手信息:\n", i+1); printf("姓名: "); fflush(stdin); // 清除输入缓冲区残留的换行符 fgets(players[i].name, sizeof(players[i].name), stdin); // 去除fgets读取的末尾换行符 players[i].name[strcspn(players[i].name, "\n")] = '\0'; printf("打数: "); scanf("%d", &players[i].at_bats); // 合法性检查:打数不能为0或负数 while (players[i].at_bats <= 0) { printf("打数不能为0或负数,请重新输入: "); scanf("%d", &players[i].at_bats); } printf("安打数: "); scanf("%d", &players[i].hits); // 合法性检查:安打数不能为负,且不能超过打数 while (players[i].hits < 0 || players[i].hits > players[i].at_bats) { printf("安打数必须在0到打数之间,请重新输入: "); scanf("%d", &players[i].hits); } // 计算打击率:强制转换为浮点型避免整数除法 players[i].batting_avg = (float)players[i].hits / players[i].at_bats; // 设置备注 strcpy(players[i].remark, players[i].batting_avg >= 0.5 ? "High" : "Low"); clear_screen(); } // 输出表格形式的结果 printf("=============================================\n"); printf("序号\t姓名\t\t打数\t安打数\t打击率\t\t备注\n"); printf("=============================================\n"); for (i = 0; i < MAX; i++) { printf("%d\t%s\t\t%d\t%d\t%.4f\t\t%s\n", i+1, players[i].name, players[i].at_bats, players[i].hits, players[i].batting_avg, players[i].remark); } printf("=============================================\n"); return 0; }
代码关键优化点
- 结构体中使用固定长度字符数组存储姓名,彻底避免内存复用导致的姓名覆盖问题
- 新增
clear_screen()函数,通过预编译指令实现跨平台兼容的清屏操作 - 计算打击率时强制将
hits转换为float,确保执行浮点除法得到精确结果 - 添加输入合法性校验,防止打数为0(除零错误)、安打数超出合理范围的情况
- 使用
fgets()读取姓名,避免scanf()读取字符串时的缓冲区溢出问题,同时处理掉换行符保证输出格式整洁
内容的提问来源于stack exchange,提问作者xtie83
相关产品推荐
相关产品推荐

