
文章目录
- 💯前言
- 💯题目: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语言编程的核心思想,从而在复杂问题的解决中游刃有余。


















![[极客大挑战 2019]HardSQL 1](https://i-blog.csdnimg.cn/direct/25ee8a196c3149ec9a96eb4195a5d328.png)









