文章目录
- 💯前言
- 💯题目背景
- 题目描述
- 输入格式
- 输出格式
- 样例 #1
- 样例输入 #1
- 样例输出 #1
- 样例 #2
- 样例输入 #2
- 样例输出 #2
- 提示
- 数据规模与约定
- 💯方法分析
- 方法1:我的做法
- 实现代码
- 详细解析
- 优点
- 缺点
- 方法2:老师的第一种做法
- 实现代码
- 详细解析
- 优点
- 缺点
- 方法3:老师的第二种做法
- 实现代码
- 详细解析
- 优点
- 缺点
- 💯方法对比与优化
- 方法对比
- 优化建议
- 💯扩展与思考
- 1. 字符串处理常用函数
- 2. 输入方式的选择
- 3. 实际应用场景
- 💯小结
💯前言
- 在学习C++编程的过程中,字符处理问题是一个重要的实践方向。本文将以NOIP2018普及组的一道题目"标题统计"为切入点,详细解析题目要求,并对三种实现方法进行对比和优化。文章还会结合题目扩展一些相关知识点,帮助读者深入理解字符串操作及其应用。
C++ 参考手册
💯题目背景
PP5015 [NOIP2018 普及组] 标题统计
这道题目源于NOIP2018普及组T1,目的是对作文标题中字符的数量进行统计。题目描述如下:
题目描述
凯凯刚写了一篇美妙的作文,请问这篇作文的标题中有多少个字符?注意:标题中可能包含大、小写英文字母、数字字符、空格和换行符。统计标题字符数时,空格和换行符不计算在内。
输入格式
输入文件只有一行,一个字符串 s s s。
输出格式
输出文件只有一行,包含一个整数,即作文标题的字符数(不含空格和换行符)。
样例 #1
样例输入 #1
234
样例输出 #1
3
样例 #2
样例输入 #2
Ca 45
样例输出 #2
4
提示
- 样例 1 说明:标题中共有 3 个字符,这 3 个字符都是数字字符。
- 样例 2 说明:标题中共有 4 个字符,包括 1 个大写字母,1 个小写字母和 2 个数字字符(忽略了空格)。
数据规模与约定
- 对于 40% 的数据, 1 ≤ ∣ s ∣ ≤ 5 1 \leq |s| \leq 5 1≤∣s∣≤5,保证输入为数字字符及行末换行符。
- 对于 100% 的数据, 1 ≤ ∣ s ∣ ≤ 5 1 \leq |s| \leq 5 1≤∣s∣≤5,输入可能包含大、小写英文字母、数字字符、空格和行末换行符。
💯方法分析
为了解决这道题目,我们探讨了三种主要的实现方式,并分析它们的优缺点。
方法1:我的做法
实现代码
#include <iostream>
#include <string>
using namespace std;
int main()
{
int count = 0;
string s;
getline(cin, s); // 读取整行字符串
for (int i = 0; i < s.size(); i++)
{
if (s[i] == ' ')
continue; // 跳过空格
count++;
}
cout << count << endl; // 输出统计结果
return 0;
}
详细解析
-
输入方式:
- 使用
getline()
读取整行输入,便于处理包含空格的内容。
- 使用
-
统计逻辑:
- 遍历字符串中的每个字符。
- 通过判断字符是否为空格(
s[i] == ' '
),跳过统计。 - 对于非空格字符,
count
累加。
-
输出结果:
- 最终输出有效字符的数量。
优点
- 逻辑简单,易于理解。
- 手动实现字符过滤逻辑,适合初学者练习。
缺点
- 没有考虑换行符和其他空白字符的处理。
- 代码冗长,可以通过标准库函数简化。
方法2:老师的第一种做法
实现代码
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
int main()
{
string s;
getline(cin, s); // 一次性读取整行输入
int cnt = 0;
for (auto e : s)
{
if (isspace(e)) // 判断是否为空白字符
continue;
else
cnt++;
}
cout << cnt << endl; // 输出有效字符数
return 0;
}
详细解析
-
输入方式:
- 使用
getline()
读取整行输入,这种方式能读取包含空格的字符串。 - 不会因为空格而分隔字符串,这是统计字符的基础。
- 使用
-
统计逻辑:
- 遍历字符串中的每个字符。
- 使用
isspace()
判断字符是否为空白字符(包括空格、制表符和换行符)。 - 如果是空白字符,则跳过;否则将计数器
cnt
加1。
-
输出结果:
- 统计完成后,将有效字符的总数输出。
优点
- 利用了C++标准库中的
isspace()
函数,过滤空白字符非常方便。 - 更加通用,能处理所有空白字符而非仅空格。
缺点
- 输入内容较大时,需一次性加载到内存,可能导致性能问题。
方法3:老师的第二种做法
实现代码
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s;
int ans = 0;
while (cin >> s) // 按单词读取
{
ans += s.size(); // 累计单词长度
}
cout << ans << endl; // 输出结果
return 0;
}
详细解析
-
输入方式:
- 使用
cin >> s
按单词读取输入,遇到空格或换行符自动分隔。 - 每次只读取一个单词,避免一次性加载所有内容。
- 使用
-
统计逻辑:
- 对于每次读取的单词,直接调用
s.size()
获取其长度,并累计到ans
中。
- 对于每次读取的单词,直接调用
-
输出结果:
- 所有单词处理完成后,输出有效字符总数。
优点
- 更加节省内存,适合处理大输入数据。
- 逻辑简洁,利用
cin
天然跳过空白字符的特性。
缺点
- 按单词分隔输入,可能会在某些特殊场景下不够灵活(如连续空格的处理)。
💯方法对比与优化
方法对比
比较维度 | 方法1:我的做法 | 方法2:老师的第一种做法 | 方法3:老师的第二种做法 |
---|---|---|---|
内存使用 | 较高,需要一次性加载整行内容 | 较高,需要一次性加载整行内容 | 较低,只处理一个单词 |
代码复杂度 | 稍高,需要手动判断字符 | 较低,使用标准库函数isspace() | 最低,直接利用cin 分隔单词 |
适用场景 | 输入内容较小或初学者练习 | 输入内容较小且需要逐字符处理的场景 | 输入内容较大或逐单词处理的场景 |
优化建议
-
统一有效字符的定义:
- 如果题目要求更加严格,可以结合
isalnum()
函数,确保只统计字母和数字字符。
- 如果题目要求更加严格,可以结合
-
增强鲁棒性:
- 在读取和统计时添加更多异常处理逻辑,如过滤特殊符号。
-
结合方法:
- 将方法1和方法2结合,按实际需求选择读取方式,优化性能和灵活性。
💯扩展与思考
1. 字符串处理常用函数
isspace(char c)
:判断字符是否为空白字符。isalnum(char c)
:判断字符是否为字母或数字。tolower(char c)
/toupper(char c)
:将字符转换为小写或大写。
2. 输入方式的选择
getline()
:- 适合处理整行输入,尤其是包含空格的内容。
cin >> s
:- 适合按单词分隔的场景,自带空白字符过滤。
3. 实际应用场景
- 文本分析:如统计单词数、字符频率。
- 数据过滤:如提取特定格式的内容。
💯小结
通过对NOIP2018普及组"标题统计"题目的深入分析,我们探讨了三种主要的实现方法,并对其优缺点和适用场景进行了详细对比。无论是整行读取还是按单词读取,都有各自的优势,可以根据具体需求灵活选择。在实际编程中,合理选择输入方式和统计逻辑,不仅能提高代码的效率,还能增强其鲁棒性。