【C++】1139:整理药名
文章目录
- 💯前言
- 💯题目描述与需求分析
- 题目描述
- 输入格式
- 输出格式
- 输入输出样例
- 需求分析
- 💯我的解法与详细解析
- 代码实现
- 代码解析
- 优点
- 不足
- 💯老师的解法与详细解析
- 代码解析
- 优点
- 不足
- 💯解法对比与优化建议
- 相同点
- 不同点
- 优化建议
- 优化后的代码
- 💯知识点拓展
- 💯小结
💯前言
- C++ 是一门广泛应用于各种领域的编程语言,尤其在高性能和精细化操作场景下占有重要地位。编程的过程不仅是实现功能的过程,也是对代码逻辑、可读性和优化能力的一种考验。本文将以一个药品名称格式化的编程题为例,详细分析题目、两种不同的解法、它们的优缺点,并进行深入的优化与扩展探讨。
我们将从以下几个方面展开:- 题目描述与需求分析;
- 我的解法与详细解析;
- 老师的解法与详细解析;
- 两种解法的对比与优化建议;
- 对相关知识点的拓展。
希望通过这篇文章,不仅帮助读者深入理解该问题的实现思路,还能在代码规范和优化方面有所收获。
C++ 参考手册
💯题目描述与需求分析
题目要求我们编写一个程序,将医生书写混乱的药品名称格式化为统一的标准格式,具体如下:
题目描述
1139:整理药名
医生在书写药品名称时经常忽略大小写,格式比较混乱。现要求你写一个程序,将医生书写的药品名称整理成统一规范的格式。
- 规范规则:
- 药品名称的第一个字符如果是字母,需要大写;
- 其余字符需要全部小写;
例如:
- 输入
ASPIRIN
,规范化后为Aspirin
; - 输入
aspirin
,规范化后为Aspirin
; - 输入
2-PENICILLIN
,规范化后为2-penicillin
。
输入格式
- 第一行一个整数
n
,表示有n
个药品名称需要处理(n \leq 100
)。 - 接下来
n
行,每行一个单词(药品名称)。药品名称由字母、数字和-
组成,长度不超过 20。
输出格式
- 输出
n
行,每行一个规范化后的药品名称。
输入输出样例
输入样例:
4
Aspirin
cisapride
2-PENICILLIN
Cefradine-6
输出样例:
Aspirin
Cisapride
2-penicillin
Cefradine-6
需求分析
- 首字母大写、其余小写的操作本质上是大小写转换问题,核心是理解字符的 ASCII 编码以及转换方法;
- 需要遍历字符串进行逐字符判断和转换;
- 考虑边界情况,例如药品名称首字符为非字母的情况。
💯我的解法与详细解析
代码实现
以下是我的解法:
#include <iostream>
using namespace std;
const int N = 25;
char ch[N];
int main()
{
int i = 0;
int n;
cin >> n;
for (i = 0; i < n; i++)
{
cin >> ch;
if (ch[0] >= 'a' && ch[0] <= 'z')
ch[0] -= 32;
int j = 1;
while (ch[j] != '\0')
{
if (ch[j] >= 'A' && ch[j] <= 'Z')
ch[j] += 32;
j++;
}
cout << ch << endl;
}
return 0;
}
代码解析
-
定义字符数组与常量:
- 使用
char ch[N]
存储药品名称,N = 25
确保数组容量足够(题目中药品名称长度上限为 20); cin >> n
读取药品名称的数量。
- 使用
-
首字母处理:
- 判断首字符是否为小写字母(
ch[0] >= 'a' && ch[0] <= 'z'
),如果是,则通过减去 32 转换为大写(利用 ASCII 编码:小写字母与对应大写字母的差值为 32)。
- 判断首字符是否为小写字母(
-
逐字符遍历:
- 使用
while (ch[j] != '\0')
遍历字符串中的其余字符,直到遇到字符串结束符\0
; - 判断当前字符是否为大写字母(
ch[j] >= 'A' && ch[j] <= 'Z'
),如果是,则通过加 32 转换为小写。
- 使用
-
输出结果:
- 每处理一个药品名称,直接输出结果。
优点
- 逻辑简单清晰,直接基于 ASCII 编码进行大小写转换;
- 使用基本循环结构,适合初学者学习与理解。
不足
- 代码可读性不够高:直接操作 ASCII 值,对初学者可能不够直观;
- 边界情况未处理:如输入字符串长度超过数组容量时可能出现越界问题。
💯老师的解法与详细解析
以下是老师的解法:
#include <iostream>
#include <cctype>
using namespace std;
const int N = 25;
char arr[N];
int main()
{
int n = 0;
cin >> n;
for (int i = 0; i < n; i++)
{
scanf("%s", arr);
if (islower(arr[0]))
arr[0] -= 32;
int j = 1;
while (arr[j])
{
if (isupper(arr[j]))
arr[j] += 32;
j++;
}
cout << arr << endl;
}
return 0;
}
代码解析
-
使用
<cctype>
库函数:islower()
:判断字符是否为小写字母;isupper()
:判断字符是否为大写字母;- 这些库函数提高了代码可读性,避免了直接操作 ASCII 值。
-
输入输出:
- 使用
scanf("%s", arr)
读取药品名称; - 使用
cout
输出规范化结果。
- 使用
-
逐字符遍历:
- 首字符通过
islower()
检查,若为小写则转换为大写; - 非首字符通过
isupper()
检查,若为大写则转换为小写。
- 首字符通过
优点
- 可读性高:借助
<cctype>
库函数实现大小写判断,逻辑更加直观; - 代码结构清晰:将首字符和非首字符的处理逻辑分开。
不足
- 混用了
scanf
和cout
两种风格的输入输出,略显不统一; - 未处理输入字符串长度越界的情况。
💯解法对比与优化建议
相同点
- 两种解法的核心逻辑完全一致:
- 首字母大写,其余字母小写;
- 基于逐字符遍历实现。
- 都使用了字符数组存储字符串。
不同点
-
可读性:
- 老师的代码通过
<cctype>
库函数简化了大小写判断,逻辑更加直观; - 我的代码直接基于 ASCII 值,虽然实现简单,但可读性略差。
- 老师的代码通过
-
输入输出:
- 老师的代码使用了
scanf
,属于 C 风格输入; - 我的代码使用了
cin
,属于 C++ 风格输入。
- 老师的代码使用了
优化建议
-
统一输入输出风格:
- 统一使用 C++ 的
cin
和cout
,符合现代编程习惯。
- 统一使用 C++ 的
-
边界检查:
- 对输入字符串长度进行限制,避免数组越界问题:
cin >> setw(N) >> arr;
- 对输入字符串长度进行限制,避免数组越界问题:
-
避免全局变量:
- 将字符数组定义为局部变量,减少作用域污染。
-
代码重构:
- 使用
toupper()
和tolower()
函数替代 ASCII 运算,进一步提升代码可读性。
- 使用
优化后的代码
#include <iostream>
#include <cctype>
#include <iomanip>
using namespace std;
const int N = 25;
int main()
{
int n;
cin >> n;
char arr[N];
for (int i = 0; i < n; i++) {
cin >> setw(N) >> arr;
if (islower(arr[0]))
arr[0] = toupper(arr[0]);
for (int j = 1; arr[j]; j++) {
if (isupper(arr[j]))
arr[j] = tolower(arr[j]);
}
cout << arr << endl;
}
return 0;
}
💯知识点拓展
-
字符处理与 ASCII 编码:
- 字符在计算机中以 ASCII 编码存储,大写字母和小写字母的差值为 32,这为大小写转换提供了简单的数学操作。
-
<cctype>
库函数:islower()
、isupper()
、toupper()
、tolower()
是常用的字符处理函数,可以简化代码,提高可读性。
-
输入输出优化:
cin
和cout
是 C++ 的标准输入输出方式,推荐在现代 C++ 编程中统一使用。
💯小结
通过这道题目,我们深入探讨了药品名称格式化的实现方法以及不同解法的对比。我的解法和老师的解法各有优缺点,经过优化后,我们得到了更加健壮且高可读性的代码。
学习编程的过程,不仅要实现功能,还要注重代码的规范性和可维护性,希望这篇文章能为读者带来启发。