为何C程序循环次数≥2时无法读取板球运动员姓名输入?如何修复?
问题原因分析
- 姓名读取格式串错误:原代码中
scanf("%[^ ]s", &player[i].name);存在两处问题:一是%[^ ]已经表示读取所有字符直到换行符,后面额外的s属于冗余格式,会强制要求输入中包含s字符,否则scanf会失败;二是player[i].name是数组首地址,无需添加&符号。 - 输入缓冲区残留换行符:使用
%d读取整数后,用户输入的换行符会残留在输入缓冲区中。当循环进入下一次迭代时,scanf("%[^ ]")会直接读取到这个换行符,将其视为姓名的输入内容,导致跳过真实的姓名输入步骤。 - 场均得分类型不匹配:场均得分
run是float类型,但代码中用%d(整数格式)读取,会导致数据解析错误,破坏内存中的数据结构。 - 最高得分逻辑反转:查找最高场均得分的循环中,错误地将
high的值赋给player[i].run,而非将更高的player[i].run赋值给high,无法正确找到最大值。
修复方案及完整代码
针对上述问题,逐一修复后的代码如下:
//Write a C program to create a record containing the name of cricketer (char array), his age //(integer), and number of test matches (integer) that he has played and the average runs //(float) that he has scored in each test match. Create an array of structures to hold records //of 20 such cricketers and then write a program to read these records and print it, also find //the cricketer which has the highest average. #include <stdio.h> #include <string.h> struct cricketer { char name[40]; int age; int match; float run; }; int main() { struct cricketer player[20]; int recordCount = 3; // 测试用3条记录,可修改为20 for(int i=0; i<recordCount; i++) { printf("Enter details for cricketer %d ", i+1); printf("Name: "); // 用空格跳过缓冲区残留的空白字符,%[^ ]读取直到换行 scanf(" %[^ ]", player[i].name); printf("Age: "); scanf("%d", &player[i].age); printf("Number of matches played: "); scanf("%d", &player[i].match); printf("Average runs: "); scanf("%f", &player[i].run); // 用%f匹配float类型 } // 打印所有记录 printf(" === All Cricketer Records === "); for(int i=0; i<recordCount; i++) { printf(" Cricketer #%d: ", i+1); printf("Name: %s ", player[i].name); printf("Age: %d ", player[i].age); printf("Matches played: %d ", player[i].match); printf("Average runs: %.2f ", player[i].run); } // 查找最高场均得分的运动员 float highestAvg = player[0].run; int topPlayerIndex = 0; for(int i=1; i<recordCount; i++) { if(player[i].run > highestAvg) { highestAvg = player[i].run; topPlayerIndex = i; } } printf(" === Top Performer === Highest average runs: %.2f Player name: %s ", highestAvg, player[topPlayerIndex].name); return 0; }
关键修复点说明
- 姓名读取修正:
scanf(" %[^ ]", player[i].name);中的前置空格会自动跳过输入缓冲区中的所有空白字符(包括残留的换行符),确保读取到真实的姓名输入;同时去掉了冗余的s格式符。 - 场均得分格式修正:改用
%f格式符读取float类型的场均得分,避免类型不匹配问题。 - 最高得分逻辑修正:当发现更高的场均得分时,更新
highestAvg的值并记录对应的运动员索引,最终可以输出对应的运动员姓名,增强实用性。 - 可选优化:如果姓名中包含空格,原
%[^ ]仍然可以正常读取;若想进一步避免缓冲区问题,也可以使用fgets读取姓名后去除换行符:fgets(player[i].name, sizeof(player[i].name), stdin); player[i].name[strcspn(player[i].name, "
")] = '';
内容的提问来源于stack exchange,提问作者chintamani chaudhari
相关产品推荐
相关产品推荐

