【C++】深入理解C语言中的特殊字符处理与问题分析优化



博客主页:[小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C++


文章目录



💯前言

  • 在C语言编程过程中,格式化输出函数printf是一个高频使用的工具。然而,由于其支持格式化字符串,某些特殊字符(如%)的输出和处理经常导致困惑。本文通过具体问题的剖析,包括在洛谷平台的编程题目和相关代码的优化实践,系统地讲解了printf中特殊字符处理的机制、常见错误的排查方法,以及代码优化的技巧。希望通过这一篇文章,读者能对C语言的printf机制和编程逻辑有更深刻的理解。
    C++ 参考手册

💯题目:B2090 年龄与疾病

B2090 年龄与疾病

题目描述:

某医院进行了一项研究,想知道某项疾病是否与年龄有关。因此对以往的诊断记录进行整理,统计0-18、19-35、36-60、61及以上这四个年龄段的患者人数占总患者人数的比例。

输入格式

输入共2行:

  1. 第一行包含一个整数 N N N ( 0 < N ≤ 100 ) (0 < N \leq 100) (0<N≤100),表示总患者人数。
  2. 第二行包含 N N N 个整数,代表这 N N N 个患者就诊时的年龄。

输出格式

输出共4行:

  1. 第1行包含一个百分数,表示0-18岁这个年龄段的患者人数占总患者人数的比例,精确到小数点后2位。
  2. 第2行包含一个百分数,表示19-35岁这个年龄段的患者人数占总患者人数的比例,精确到小数点后2位。
  3. 第3行包含一个百分数,表示36-60岁这个年龄段的患者人数占总患者人数的比例,精确到小数点后2位。
  4. 第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%

💯初始代码分析与问题排查

初始代码如下:

cpp 复制代码
#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;    
}

问题点分析

  1. 逻辑错误:

    • 判断条件 if(i <= 18) 中,i 是数组的索引,而不是输入的年龄值。这导致判断逻辑与题目要求不符。
    • 索引 i 的范围是 0n-1,无法正确反映年龄范围。
  2. 范围错误:

    • 题目要求的范围是 0-18, 19-35, 36-60, 61及以上,但代码未正确实现。
    • 代码中未对数组的值进行比较,而是直接比较索引值。
  3. 数组定义错误:

    • 在C++中,int arr[n]; 使用了变长数组,这是C99标准支持的特性,但并非所有C++编译器都支持。应使用动态内存分配(如new)或标准容器(如vector)。
  4. 输出格式错误:

    • printf("%0.2lf% ", rate1); 多余的空格和单独的%符号导致输出不符合题目要求。
    • 百分号%需要用%%来表示,确保格式化输出。
  5. 未释放动态分配内存:

    • 如果使用动态数组,代码未正确释放分配的内存。

💯修正后的代码与优化

cpp 复制代码
#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;
}

修正与优化要点

  1. 修正逻辑错误:

    • 使用 arr[i] 比较输入的年龄值,而不是索引 i
  2. 调整范围判断:

    • 按题目要求分别比较 0-18, 19-35, 36-60, 61及以上
  3. 动态内存分配:

    • 使用 new 动态分配数组,并在程序结束时使用 delete[] 释放内存,防止内存泄漏。
  4. 输出格式修正:

    • 使用 %% 正确输出百分号。
    • 每行输出结果以换行符 \n 结尾,确保格式正确。
  5. 代码简洁性:

    • 合理命名变量,增强代码可读性。
    • 省去冗余的 sum++ 操作,直接用输入数量 n 作为总人数。

💯拓展:printf 中的特殊字符处理

在C语言的printf函数中,有一些特殊字符需要注意处理,类似于上述代码中使用的%%。以下是常见的特殊字符及其用法:

1. 百分号 %

  • 原因% 是格式说明符的起始符号,用于标记格式化占位符(如 %d, %f)。如果需要输出实际的 % 符号,必须使用 %%

  • 示例

    c 复制代码
    printf("成功率为 50%%\n");

    输出:

    成功率为 50%
    

2. 反斜杠 \

  • 原因 :反斜杠 \ 是转义字符的起始符号,必须用双反斜杠 \\ 表示实际的 \

  • 示例

    c 复制代码
    printf("This is a backslash: \\\n");

    输出:

    This is a backslash: \
    

3. 双引号 "

  • 原因 :双引号 " 在字符串常量中需要用转义字符 \" 表示。

  • 示例

    c 复制代码
    printf("She said, \"Hello, World!\"\n");

    输出:

    She said, "Hello, World!"
    

4. 常见转义字符

  • 换行符\n
  • 制表符\t
  • 回车\r
  • 退格\b
  • 响铃\a
  • 反斜杠\\
  • 双引号\"

💯总结

通过对题目"年龄与疾病"的深入分析和代码优化,我们不仅修正了代码中的逻辑问题和格式错误,还系统性地探讨了C语言中printf函数处理特殊字符的机制。这些知识点不仅适用于此题目,还对其他编程场景具有指导意义。

在实际开发中,理解格式化输出函数的工作机制,掌握正确的特殊字符处理方法,是写出健壮代码的重要一步。希望本文能帮助读者从细节中理解C语言编程的核心思想,从而在复杂问题的解决中游刃有余。



相关推荐
Ronin-Lotus3 天前
蓝桥杯篇---IAP15F2K61S2串口
单片机·嵌入式硬件·职场和发展·蓝桥杯·c·iap15f2k61s2
Nicn6 天前
【C++初阶】类和对象①
c语言·开发语言·c++·算法·c·编程软件
Ronin-Lotus7 天前
蓝桥杯篇---实时时钟 DS1302
stm32·单片机·嵌入式硬件·职场和发展·蓝桥杯·c·ds1302
Ronin-Lotus9 天前
蓝桥杯篇---温度传感器 DS18B20
嵌入式硬件·职场和发展·蓝桥杯·c·ds18b20·iap15f2k61s2
IOT那些事儿12 天前
一个简单的Windows TCP服务器实现
服务器·windows·c·server·winsock2
飞翔的煤气罐boom15 天前
TCP服务器与客户端搭建
linux·tcp/ip·c
学习前端的小z16 天前
理解 C 与 C++ 中的 const 常量与数组大小的关系
c
Leon_Chenl16 天前
FFmpeg 头文件完美翻译之 libavdevice 模块
ffmpeg·音视频·c·编解码·libavdevice
学习前端的小z18 天前
【C语言】指针详解:概念、类型与解引用
c
学习前端的小z19 天前
【C++】B2122 单词翻转
c