scanf返回值忽略错误排查:结构体实现员工年龄统计代码问题
解决C++员工信息管理代码的scanf返回值警告及逻辑问题
问题描述
编写了一段通过结构体实现员工信息管理并筛选最年轻、最年长员工的C++代码,编译器触发**Return value ignored: 'scanf'**警告,且无法正确筛选目标员工。原代码如下:
#define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <stdio.h> #include <string> using namespace std; int main() { setlocale(LC_ALL, "Russian"); struct worker { char surname[22], posada[15], osvita[25]; int birthday, salary; }; int kol; cout << "Введите кол-во робітників: "; cin >> kol; cout << "Введите поочередно строки с ведомостью:\nПрiзвище Посада Освіта Рік народження Зарплатня" << endl; worker* z = new worker[kol]; for (int i = 0; i < kol; i++) { scanf("%s %s %s %i %i", z[i].surname, z[i].posada, z[i].osvita, &z[i].birthday, &z[i].salary); } setlocale(LC_ALL, "Russian"); cout << "Прiзвище Посада Освіта Рік народження Зарплатня" << endl; for (int i = 0; i < kol; i++) { cout << z[i].surname << "\t" << z[i].posada << "\t" << z[i].osvita << "\t" << z[i].birthday << "\t" << z[i].salary << endl; } cout << "Найстарший і наймолодний робітники:\nПрiзвище Посада Освіта Рік народження Зарплатня" << endl; int min, max; int max_index = 0, min_index = 0; min = z[0].birthday; max = z[0].birthday; for (int i = 0; i < kol; i++) { if (max < z[i].birthday) {max_index = i;} if (min > z[i].birthday) {min_index = i;} printf("% s % s % s % i % i\n", z[i].surname, z[i].posada, z[i].osvita, z[i].birthday, z[i].salary); } setlocale(LC_ALL, "Russian"); cout << "Наймолодний робітник: " << z[min_index].surname<< endl; cout << "Найстарший робітник: " << z[max_index].surname << endl; setlocale(LC_ALL, ".OCP"); delete[]z; return 0; }
问题根源
- scanf返回值未处理:
scanf返回成功读取的参数数量,代码未检查该返回值,编译器会抛出警告,且无法发现输入失败的情况。 - 筛选逻辑错误:寻找最大/最小出生年份时,仅更新索引但未同步更新
max和min变量,导致后续判断失效,无法正确定位目标员工,且输出时的索引对应关系也存在错误。 - 格式符错误:
printf中的格式符与空格之间多了空格(如% s),会导致输出格式混乱。 - 冗余本地化设置:多次重复调用
setlocale,属于无效冗余操作。
修正后的代码
#define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <stdio.h> #include <string> using namespace std; int main() { setlocale(LC_ALL, "Russian"); // 仅需初始化一次本地化设置 struct worker { char surname[22], posada[15], osvita[25]; int birthday, salary; }; int kol; cout << "Введите кол-во робітників: "; cin >> kol; cout << "Введите поочередно строки с ведомостью:\nПрiзвище Посада Освіта Рік народження Зарплатня" << endl; worker* z = new worker[kol]; for (int i = 0; i < kol; i++) { // 处理scanf返回值,检查输入是否成功 if (scanf("%s %s %s %i %i", z[i].surname, z[i].posada, z[i].osvita, &z[i].birthday, &z[i].salary) != 5) { cerr << "Ошибка ввода данных для работника #" << i+1 << endl; delete[] z; return 1; } } cout << "Прiзвище Посада Освіта Рік народження Зарплатня" << endl; for (int i = 0; i < kol; i++) { cout << z[i].surname << "\t" << z[i].posada << "\t" << z[i].osvita << "\t" << z[i].birthday << "\t" << z[i].salary << endl; } cout << "Найстарший і наймолодний робітники:\nПрiзвище Посада Освіта Рік народження Зарплатня" << endl; int min_birth = z[0].birthday, max_birth = z[0].birthday; int max_index = 0, min_index = 0; for (int i = 0; i < kol; i++) { // 更新最大出生年份(对应最年轻员工) if (max_birth < z[i].birthday) { max_birth = z[i].birthday; max_index = i; } // 更新最小出生年份(对应最年长员工) if (min_birth > z[i].birthday) { min_birth = z[i].birthday; min_index = i; } // 修正printf格式符,去掉多余空格 printf("%s %s %s %i %i\n", z[i].surname, z[i].posada, z[i].osvita, z[i].birthday, z[i].salary); } cout << "Наймолодний робітник: " << z[max_index].surname << endl; cout << "Найстарший робітник: " << z[min_index].surname << endl; delete[] z; return 0; }
核心修改说明
- 处理scanf返回值:添加判断,确保每次输入都成功读取5个参数,若失败则提示错误并释放内存后退出。
- 修复筛选逻辑:更新索引的同时同步更新
min_birth和max_birth的值,保证后续判断的准确性,同时修正了输出时的索引对应关系。 - 修正格式符:移除
printf格式符中的多余空格,保证输出格式正确。 - 清理冗余代码:移除重复的
setlocale调用,仅保留初始化时的一次设置。
内容的提问来源于stack exchange,提问作者David Kotsiuba
相关产品推荐
相关产品推荐

