校验验证码或比对账号名时,我们经常需要把字符串里的英文字母统一转换成大写或小写。
在 C++ 中,std::string 没有自带整串转换大小写的成员函数,我们可以借助 <cctype> 头文件中的 std::toupper() 和 std::tolower() 函数,配合循环遍历来实现。
转换单个字符:toupper() 和 tolower()
在转换整段字符串之前,我们先来看看如何转换单个 char 字符的大小写。
语法:
#include <cctype>
char upperCh = std::toupper(ch);
char lowerCh = std::tolower(ch);说明:
其中,toupper 是 “to upper(转为大写)” 的意思,而 tolower 是 “to lower(转为小写)” 的意思。这两个函数的具体作用如下:
- std::toupper(ch):如果参数
ch是'a' ~ 'z'之间的小写字母,则返回对应的大写字母'A' ~ 'Z'。如果ch原本就是大写字母、数字或标点符号,则保持原样返回。 - std::tolower(ch):如果参数
ch是'A' ~ 'Z'之间的大写字母,则返回对应的小写字母'a' ~ 'z'。如果是其他字符,同样保持原样返回。
示例 1:转换单个字符的大小写
#include <cctype>
#include <iostream>
int main() {
char c1 = std::toupper('a');
char c2 = std::tolower('Z');
char c3 = std::toupper('8');
std::cout << c1 << '\n';
std::cout << c2 << '\n';
std::cout << c3 << '\n';
return 0;
}运行结果如下。
A
z
8分析:
std::toupper('a') 表示将小写字母 'a' 转换成大写字母 'A',std::tolower('Z') 表示将大写字母 'Z' 转换成小写字母 'z'。数字字符 '8' 不是英文字母,因此保持原样返回了 '8'。
使用这两个函数时有一个细节需要留意:std::toupper() 和 std::tolower() 返回的其实是 int 类型的 ASCII 码整数,而不是 char 字符。我们可以对比一下下面 2 种写法:
char ch = 'a';
// 方式 1
char upperCh = std::toupper(ch);
std::cout << upperCh << '\n'; // 输出 A
// 方式 2
std::cout << std::toupper(ch) << '\n'; // 输出 65在方式 1 中,我们先把返回值赋给 char 变量 upperCh,借助 C++ 的类型转换还原为字符,打印出来就是字母 'A'。
如果像方式 2 那样不经过 char 变量,直接把函数返回值放进 std::cout 中输出,屏幕上就会按整数打印出 'A' 的编码值 65。
转换整个字符串的大小写
掌握了单个字符的转换方法后,想要把整段 std::string 字符串转换成全大写或全小写就很简单了:我们只需要结合 for 循环按下标依次取出字符串中的每一个字符,转换大小写后再存回原来的 text[i] 位置即可。
示例 2:转换整段字符串大小写
#include <cctype>
#include <iostream>
#include <string>
int main() {
std::string text = "Hello, C++ 2026!";
// 全部转换为大写
for (std::size_t i = 0; i < text.size(); i++) {
text[i] = std::toupper(text[i]);
}
std::cout << text << '\n';
// 全部转换为小写
for (std::size_t i = 0; i < text.size(); i++) {
text[i] = std::tolower(text[i]);
}
std::cout << text << '\n';
return 0;
}运行结果如下。
HELLO, C++ 2026!
hello, c++ 2026!分析:
在这个例子中,我们通过下标 i 遍历字符串 text,每次把转换后的字符重新赋给 text[i]。转换后只有英文字母改变了大小写,逗号、空格、加号和数字 "2026" 都保持不变。
这里小伙伴们要注意,如果改用范围 for 循环,不要写成下面这样:
// 错误方式
for (char ch : text) {
ch = std::toupper(ch);
}为什么这样写改不了原字符串呢?因为 char ch 每次只是从 text 里复制出来的一个字符副本,修改副本 ch 并不会影响原字符串 text。
等后面章节学完引用之后,我们也可以把循环写成 for (char& ch : text) 来直接修改原字符,写起来会更简短。
注意 <cctype> 中的大小写转换函数仅适用于纯英文 ASCII 字符。如果字符串中包含中文汉字等多字节字符,请不要直接按单字节逐个转换。
忽略大小写比较字符串
在学习字符串比较时我们知道,直接使用 == 比较两个字符串是严格区分大小写的,比如 "Yes" 和 "yes" 会被判定为不相等。
但在校验用户输入的确认指令或比对账号名时,我们往往希望忽略大小写差异。此时只需要先把字符串统一转换成全小写或全大写,然后再使用 == 进行比较即可。
示例 3:忽略大小写比较字符串
#include <cctype>
#include <iostream>
#include <string>
int main() {
std::string input = "LvYeNet";
std::string target = "lvyenet";
std::string temp = input;
for (std::size_t i = 0; i < temp.size(); i++) {
temp[i] = std::tolower(temp[i]);
}
if (temp == target) {
std::cout << "匹配成功" << '\n';
}
return 0;
}运行结果如下。
匹配成功分析:
上面代码中,input 包含大写字母,直接写 input == target 会返回 false。我们先复制出一份副本 temp,把 temp 里的字母全部转为小写 "lvyenet",再与 target 比较就相等了。
之所以先复制一份副本 temp,是为了保留 input 原本的大小写格式不被改动。如果后续不再需要原来的格式,也可以直接在 input 本身上转换。
常用字符判断函数
除了转换大小写之外,<cctype> 头文件还提供了几个常用的字符判断函数,可以用来检查某个字符属于哪一类:
std::isupper(ch):判断 ch 是否为 'A' ~ 'Z' 之间的大写字母,如果是则返回非 0 值(真),否则返回 0(假)。
std::islower(ch):判断 ch 是否为 'a' ~ 'z' 之间的小写字母。
std::isdigit(ch):判断 ch 是否为 '0' ~ '9' 之间的数字字符。
