文章目录
- 💯前言
- 💯题目:B2090 年龄与疾病
- 输入格式
- 输出格式
- 输入输出样例
- 💯初始代码分析与问题排查
- 问题点分析
- 💯修正后的代码与优化
- 修正与优化要点
- 💯拓展:`printf` 中的特殊字符处理
- 1. 百分号 `%`
- 2. 反斜杠 `\`
- 3. 双引号 `"`
- 4. 常见转义字符
- 💯总结
💯前言
- 在C语言编程过程中,格式化输出函数
printf
是一个高频使用的工具。然而,由于其支持格式化字符串,某些特殊字符(如%
)的输出和处理经常导致困惑。本文通过具体问题的剖析,包括在洛谷平台的编程题目和相关代码的优化实践,系统地讲解了printf
中特殊字符处理的机制、常见错误的排查方法,以及代码优化的技巧。希望通过这一篇文章,读者能对C语言的printf
机制和编程逻辑有更深刻的理解。
C++ 参考手册
💯题目:B2090 年龄与疾病
B2090 年龄与疾病
题目描述:
某医院进行了一项研究,想知道某项疾病是否与年龄有关。因此对以往的诊断记录进行整理,统计0-18、19-35、36-60、61及以上这四个年龄段的患者人数占总患者人数的比例。
输入格式
输入共2行:
- 第一行包含一个整数 N N N ( 0 < N ≤ 100 ) (0 < N \leq 100) (0<N≤100),表示总患者人数。
- 第二行包含 N N N 个整数,代表这 N N N 个患者就诊时的年龄。
输出格式
输出共4行:
- 第1行包含一个百分数,表示0-18岁这个年龄段的患者人数占总患者人数的比例,精确到小数点后2位。
- 第2行包含一个百分数,表示19-35岁这个年龄段的患者人数占总患者人数的比例,精确到小数点后2位。
- 第3行包含一个百分数,表示36-60岁这个年龄段的患者人数占总患者人数的比例,精确到小数点后2位。
- 第4行包含一个百分数,表示61岁及以上这个年龄段的患者人数占总患者人数的比例,精确到小数点后2位。
输入输出样例
输入样例 #1:
10
1 11 21 31 41 51 61 71 81 91
输出样例 #1:
20.00%
20.00%
20.00%
40.00%
输入样例 #2:
12
10 19 96 94 58 57 34 18 99 5 13
输出样例 #2:
25.00%
25.00%
16.67%
33.33%
💯初始代码分析与问题排查
初始代码如下:
#include <iostream>
using namespace std;
int main()
{
int n = 0;
cin >> n;
int arr[n];
int sum = 0, sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0;
for(int i = 0; i < n; i++)
{
cin >> arr[i];
sum++;
if(i <= 18)
sum1++;
else if(i <= 35)
sum2++;
else if(i <= 60)
sum3++;
else
sum4++;
}
double rate1 = 100.0 * sum1 / sum;
double rate2 = 100.0 * sum2 / sum;
double rate3 = 100.0 * sum3 / sum;
double rate4 = 100.0 * sum4 / sum;
printf("%0.2lf% ", rate1);
return 0;
}
问题点分析
-
逻辑错误:
- 判断条件
if(i <= 18)
中,i
是数组的索引,而不是输入的年龄值。这导致判断逻辑与题目要求不符。 - 索引
i
的范围是0
到n-1
,无法正确反映年龄范围。
- 判断条件
-
范围错误:
- 题目要求的范围是
0-18, 19-35, 36-60, 61及以上
,但代码未正确实现。 - 代码中未对数组的值进行比较,而是直接比较索引值。
- 题目要求的范围是
-
数组定义错误:
- 在C++中,
int arr[n];
使用了变长数组,这是C99标准支持的特性,但并非所有C++编译器都支持。应使用动态内存分配(如new
)或标准容器(如vector
)。
- 在C++中,
-
输出格式错误:
printf("%0.2lf% ", rate1);
多余的空格和单独的%
符号导致输出不符合题目要求。- 百分号
%
需要用%%
来表示,确保格式化输出。
-
未释放动态分配内存:
- 如果使用动态数组,代码未正确释放分配的内存。
💯修正后的代码与优化
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
int n;
cin >> n;
int* arr = new int[n]; // 动态分配数组
int sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0;
for (int i = 0; i < n; i++) {
cin >> arr[i];
if (arr[i] >= 0 && arr[i] <= 18)
sum1++;
else if (arr[i] >= 19 && arr[i] <= 35)
sum2++;
else if (arr[i] >= 36 && arr[i] <= 60)
sum3++;
else if (arr[i] >= 61)
sum4++;
}
// 计算比例
printf("%.2lf%%\n", 100.0 * sum1 / n);
printf("%.2lf%%\n", 100.0 * sum2 / n);
printf("%.2lf%%\n", 100.0 * sum3 / n);
printf("%.2lf%%\n", 100.0 * sum4 / n);
delete[] arr; // 释放动态分配内存
return 0;
}
修正与优化要点
-
修正逻辑错误:
- 使用
arr[i]
比较输入的年龄值,而不是索引i
。
- 使用
-
调整范围判断:
- 按题目要求分别比较
0-18, 19-35, 36-60, 61及以上
。
- 按题目要求分别比较
-
动态内存分配:
- 使用
new
动态分配数组,并在程序结束时使用delete[]
释放内存,防止内存泄漏。
- 使用
-
输出格式修正:
- 使用
%%
正确输出百分号。 - 每行输出结果以换行符
\n
结尾,确保格式正确。
- 使用
-
代码简洁性:
- 合理命名变量,增强代码可读性。
- 省去冗余的
sum++
操作,直接用输入数量n
作为总人数。
💯拓展:printf
中的特殊字符处理
在C语言的printf
函数中,有一些特殊字符需要注意处理,类似于上述代码中使用的%%
。以下是常见的特殊字符及其用法:
1. 百分号 %
- 原因:
%
是格式说明符的起始符号,用于标记格式化占位符(如%d
,%f
)。如果需要输出实际的%
符号,必须使用%%
。 - 示例:
输出:printf("成功率为 50%%\n");
成功率为 50%
2. 反斜杠 \
- 原因:反斜杠
\
是转义字符的起始符号,必须用双反斜杠\\
表示实际的\
。 - 示例:
输出:printf("This is a backslash: \\\n");
This is a backslash: \
3. 双引号 "
- 原因:双引号
"
在字符串常量中需要用转义字符\"
表示。 - 示例:
输出:printf("She said, \"Hello, World!\"\n");
She said, "Hello, World!"
4. 常见转义字符
- 换行符:
\n
- 制表符:
\t
- 回车:
\r
- 退格:
\b
- 响铃:
\a
- 反斜杠:
\\
- 双引号:
\"
💯总结
通过对题目“年龄与疾病”的深入分析和代码优化,我们不仅修正了代码中的逻辑问题和格式错误,还系统性地探讨了C语言中printf
函数处理特殊字符的机制。这些知识点不仅适用于此题目,还对其他编程场景具有指导意义。
在实际开发中,理解格式化输出函数的工作机制,掌握正确的特殊字符处理方法,是写出健壮代码的重要一步。希望本文能帮助读者从细节中理解C语言编程的核心思想,从而在复杂问题的解决中游刃有余。