# 第1课编程题(教师版) ## 本课知识点覆盖表 | 核心知识点 | GESP等级 | 对应课堂题 | |---|---|---| | `sqrt`、`pow`、`abs`及 `` | 一级巩固/二级拓展 | 课堂1 | | `max`、`min`、`swap`及 `` | 二级 | 课堂2 | | `max`、`min` 综合应用 | 二级 | 课堂3 | | `isalpha`、`isdigit`、`islower`、`isupper`、`tolower`、`toupper` | 一级/二级 | 课堂4 | > 难度均为本课内部的相对难度。参考程序采用 C++17。 ## 一、课堂练习(4题) ### 课堂1:三点中最近的一对【适中】 **题目描述:** 输入平面上三个点的坐标,求三对点之间的最短距离,结果保留两位小数。要求使用 `sqrt`、`pow` 和 `min`。 **输入格式:** 输入六个实数,依次表示三个点的横坐标和纵坐标。 **输出格式:** 输出最短距离,保留两位小数。 **数据范围:** 每个坐标的绝对值不超过 1000。 **输入样例:** ```text 0 0 3 4 0 2 ``` **输出样例:** ```text 2.00 ``` **解题思路:** 用勾股定理分别求出三段距离,再用 `min` 取最小值。 **参考代码:** ```cpp #include #include #include #include using namespace std; double distance(double x1, double y1, double x2, double y2) { return sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2)); } int main() { double x1, y1, x2, y2, x3, y3; cin >> x1 >> y1 >> x2 >> y2 >> x3 >> y3; double d1 = distance(x1, y1, x2, y2); double d2 = distance(x1, y1, x3, y3); double d3 = distance(x2, y2, x3, y3); cout << fixed << setprecision(2) << min(d1, min(d2, d3)); return 0; } ``` **易错提醒:** `sqrt` 返回浮点数;格式化输出需要包含 ``。 ### 课堂2:整理三个数【适中】 **题目描述:** 输入三个整数,第一行输出最大值和最小值;再使用 `swap` 将三个变量调整为升序,第二行输出调整结果。 **输入格式:** 输入三个整数。 **输出格式:** 第一行输出最大值和最小值;第二行输出升序结果。 **数据范围:** `-10^9≤a,b,c≤10^9`。 **输入样例:** ```text 8 2 5 ``` **输出样例:** ```text 8 2 2 5 8 ``` **解题思路:** 用嵌套的 `max`、`min` 求最值;再进行三次相邻比较,需要时调用 `swap`。 **参考代码:** ```cpp #include #include using namespace std; int main() { int a, b, c; cin >> a >> b >> c; cout << max(a, max(b, c)) << " " << min(a, min(b, c)) << "\n"; if (a > b) swap(a, b); if (b > c) swap(b, c); if (a > b) swap(a, b); cout << a << " " << b << " " << c; return 0; } ``` **易错提醒:** `swap` 的参数必须是两个变量,不能传入 `a+b` 这样的表达式。 ### 课堂3:去掉最高分和最低分【适中】 **题目描述:** 输入若干个评委分数,去掉一个最高分和一个最低分,输出剩余分数之和。不得使用排序。 **输入格式:** 第一行输入评委人数;第二行输入所有评委给出的分数。 **输出格式:** 输出剩余分数之和。 **数据范围:** `3≤n≤100`,分数为 `0~100`。 **输入样例:** ```text 5 9 7 10 8 6 ``` **输出样例:** ```text 24 ``` **解题思路:** 遍历时同时计算总分、最高分和最低分,最后用总分减去两个极值。 **参考代码:** ```cpp #include #include using namespace std; int main() { int n, score, sum = 0, biggest, smallest; cin >> n; cin >> score; sum = biggest = smallest = score; for (int i = 1; i < n; i++) { cin >> score; sum += score; biggest = max(biggest, score); smallest = min(smallest, score); } cout << sum - biggest - smallest; return 0; } ``` **易错提醒:** 最高分和最低分要用第一个合法分数初始化;即使最高分重复,也只去掉一个。 ### 课堂4:字符身份证【适中】 **题目描述:** 输入一个可见字符。若为字母,输出 `LETTER` 和相反大小写的字符;若为数字,输出 `DIGIT`;否则输出 `OTHER`。 **输入格式:** 一个可见字符。 **输出格式:** 按题目要求输出。 **数据范围:** 标准 ASCII 可见字符。 **输入样例:** ```text G ``` **输出样例:** ```text LETTER g ``` **解题思路:** 用 `isalpha`、`isdigit` 分类,用 `islower` 或 `isupper` 判断大小写,再调用 `toupper` 或 `tolower` 转换。 **参考代码:** ```cpp #include #include using namespace std; int main() { char c; cin >> c; if (isalpha(c)) { cout << "LETTER "; if (islower(c)) cout << (char)toupper(c); else if (isupper(c)) cout << (char)tolower(c); } else if (isdigit(c)) { cout << "DIGIT"; } else { cout << "OTHER"; } return 0; } ``` **易错提醒:** `tolower` 和 `toupper` 返回的是字符编码,输出字符时应转换为 `char`。 ## 二、课后作业(3题) ### 课后1:离原点的距离【简单】 **题目描述:** 输入点 `(x,y)`,输出它到原点的距离,保留两位小数。 **输入格式:** 输入两个实数,依次表示横坐标和纵坐标。 **输出格式:** 距离,保留两位小数。 **数据范围:** 坐标绝对值不超过 1000。 **输入样例:** ```text 3 4 ``` **输出样例:** ```text 5.00 ``` **解题思路:** 根据勾股定理计算 `sqrt(pow(x,2)+pow(y,2))`。 **参考代码:** ```cpp #include #include #include using namespace std; int main() { double x, y; cin >> x >> y; cout << fixed << setprecision(2) << sqrt(pow(x, 2) + pow(y, 2)); return 0; } ``` **易错提醒:** 不要忘记 `` 和 ``。 ### 课后2:两数差的绝对值【简单】 **题目描述:** 输入两个整数,输出它们差的绝对值。 **输入格式:** 输入两个整数。 **输出格式:** 输出 `|a-b|`。 **数据范围:** 两数绝对值不超过 10000。 **输入样例:** ```text 3 9 ``` **输出样例:** ```text 6 ``` **解题思路:** 直接调用 `abs(a-b)`。 **参考代码:** ```cpp #include #include using namespace std; int main() { int a, b; cin >> a >> b; cout << abs(a - b); return 0; } ``` **易错提醒:** 先求差再取绝对值,不要误写成 `abs(a)-abs(b)`。 ### 课后3:数字还是字母【简单】 **题目描述:** 输入一个字符。是数字输出 `1`,是字母输出 `2`,其他字符输出 `0`。 **输入格式:** 一个字符。 **输出格式:** 一个整数。 **数据范围:** 标准 ASCII 可见字符。 **输入样例:** ```text 8 ``` **输出样例:** ```text 1 ``` **解题思路:** 依次调用 `isdigit` 和 `isalpha`。 **参考代码:** ```cpp #include #include using namespace std; int main() { char c; cin >> c; if (isdigit(c)) cout << 1; else if (isalpha(c)) cout << 2; else cout << 0; return 0; } ``` **易错提醒:** 字符数字 `'8'` 与整数 `8` 不同。 ## 三、扩展练习(7题) ### 扩展1:正方形对角线【基础综合】 **题目描述:** 输入正方形边长,输出对角线长度,保留三位小数。 **输入格式:** 输入一个正实数,表示正方形的边长。 **输出格式:** 对角线长度。 **数据范围:** `0 #include #include using namespace std; int main() { double a; cin >> a; cout << fixed << setprecision(3) << sqrt(2.0) * a; return 0; } ``` **易错提醒:** 使用 `2.0` 可以明确进行浮点运算。 ### 扩展2:三个数的中间数【基础综合】 **题目描述:** 输入三个互不相同的整数,使用 `max` 和 `min` 输出大小居中的数。 **输入格式:** 三个整数。 **输出格式:** 中间数。 **数据范围:** 每个数的绝对值不超过 `10^9`。 **输入样例:** ```text 9 2 6 ``` **输出样例:** ```text 6 ``` **解题思路:** 三数之和减去最大值和最小值。 **参考代码:** ```cpp #include #include using namespace std; int main() { long long a, b, c; cin >> a >> b >> c; long long biggest = max(a, max(b, c)); long long smallest = min(a, min(b, c)); cout << a + b + c - biggest - smallest; return 0; } ``` **易错提醒:** 三数之和可能超过 `int`,这里使用 `long long`。 ### 扩展3:成绩极差【中等】 **题目描述:** 输入若干个成绩,输出最低分、最高分以及两者之差。 **输入格式:** 第一行输入成绩数量;第二行输入所有成绩。 **输出格式:** 依次输出最低分、最高分和极差。 **数据范围:** `1≤n≤100`,成绩为 `0~100`。 **输入样例:** ```text 4 80 60 90 70 ``` **输出样例:** ```text 60 90 30 ``` **解题思路:** 用第一个成绩初始化最值,随后逐一调用 `max` 和 `min` 更新。 **参考代码:** ```cpp #include #include using namespace std; int main() { int n, score, biggest, smallest; cin >> n; cin >> score; biggest = smallest = score; for (int i = 1; i < n; i++) { cin >> score; biggest = max(biggest, score); smallest = min(smallest, score); } cout << smallest << " " << biggest << " " << biggest - smallest; return 0; } ``` **易错提醒:** 当只有一个成绩时,最低分和最高分相同,极差为 0。 ### 扩展4:口令规范化【中等】 **题目描述:** 输入一个不含空格的口令,把其中所有字母转成大写,数字和符号保持不变。 **输入格式:** 一个不含空格的字符串。 **输出格式:** 转换后的字符串。 **数据范围:** 字符串长度不超过 100。 **输入样例:** ```text GesP2026! ``` **输出样例:** ```text GESP2026! ``` **解题思路:** 逐个检查字符;是字母就调用 `toupper`。 **参考代码:** ```cpp #include #include #include using namespace std; int main() { string s; cin >> s; for (int i = 0; i < (int)s.size(); i++) { if (isalpha(s[i])) s[i] = (char)toupper(s[i]); } cout << s; return 0; } ``` **易错提醒:** 不要改动数字和符号。 ### 扩展5:离目标最近的数【中等】 **题目描述:** 输入 `n` 个整数和目标值 `t`,输出与 `t` 的差的绝对值最小的数;若并列,输出较小者。 **输入格式:** 第一行输入整数数量和目标值;第二行输入所有整数。 **输出格式:** 满足条件的整数。 **数据范围:** `1≤n≤100`,输入整数绝对值不超过 10000。 **输入样例:** ```text 4 10 8 12 15 3 ``` **输出样例:** ```text 8 ``` **解题思路:** 用第一个数初始化答案;比较 `abs(x-t)`,相等时比较数值大小。 **参考代码:** ```cpp #include #include using namespace std; int main() { int n, t, x, answer; cin >> n >> t >> answer; for (int i = 1; i < n; i++) { cin >> x; if (abs(x - t) < abs(answer - t) || (abs(x - t) == abs(answer - t) && x < answer)) { answer = x; } } cout << answer; return 0; } ``` **易错提醒:** 不能把答案初始化为 0,因为 0 不一定在输入中。 ### 扩展6:最接近平均值的成绩【略难】 **题目描述:** 输入 `n` 个整数成绩,求平均值,并输出最接近平均值的成绩;若并列,输出较小者。 **输入格式:** 第一行输入成绩数量;第二行输入所有成绩。 **输出格式:** 一个成绩。 **数据范围:** `1≤n≤100`,成绩为 `0~100`。 **输入样例:** ```text 4 60 70 80 100 ``` **输出样例:** ```text 80 ``` **解题思路:** 先求浮点平均值,再使用 `abs` 进行二次打擂台。 **参考代码:** ```cpp #include #include using namespace std; int main() { int n, a[105], sum = 0; cin >> n; for (int i = 0; i < n; i++) { cin >> a[i]; sum += a[i]; } double average = 1.0 * sum / n; int answer = a[0]; for (int i = 1; i < n; i++) { double now = abs(a[i] - average); double best = abs(answer - average); if (now < best || (now == best && a[i] < answer)) { answer = a[i]; } } cout << answer; return 0; } ``` **易错提醒:** 平均值必须使用浮点除法;并列规则不能遗漏。 ### 扩展7:统一大小写并分类统计【略难】 **题目描述:** 输入一个不含空格的字符串,把所有字母转成小写,并统计原字符串中大写字母、小写字母和数字的数量。 **输入格式:** 输入一个不含空格的字符串。 **输出格式:** 第一行输出转换后的字符串;第二行依次输出三类字符数量。 **数据范围:** 字符串长度为 1~100。 **输入样例:** ```text AbC2026xY ``` **输出样例:** ```text abc2026xy 3 3 4 ``` **解题思路:** 遍历原字符串,先分类计数,再对字母调用 `tolower`。 **参考代码:** ```cpp #include #include #include using namespace std; int main() { string s; int upper = 0, lower = 0, digit = 0; cin >> s; for (char &c : s) { if (isupper(c)) upper++; else if (islower(c)) lower++; else if (isdigit(c)) digit++; if (isalpha(c)) c = (char)tolower(c); } cout << s << "\n"; cout << upper << " " << lower << " " << digit; return 0; } ``` **易错提醒:** 分类统计必须依据转换前的字符;数字不参与大小写转换。