C++ 字符串比较
在C++编程中,字符串比较是一项基础但非常重要的操作。无论是用户输入验证、数据排序还是文本处理,我们经常需要比较两个字符串是否相等或者确定它们的字典顺序。本文将详细介绍C++中比较字符串的各种方法。
字符串比较的基本概念
字符串比较本质上是按照字典顺序(lexicographical order)对字符进行逐一比较。这意味着比较会从两个字符串的第一个字符开始,如果相等则比较第二个字符,依此类推,直到发现不同的字符或者其中一个字符串结束。
在C++中,我们主要有两种类型的字符串:
- C风格字符串(以null结尾的字符数组)
- C++标准库中的
std::string
类
使用关系运算符比较字符串
比较std::string对象
使用std::string
类时,可以直接使用关系运算符(==
, !=
, <
, <=
, >
, >=
)来比较字符串:
#include <iostream>
#include <string>
int main() {
std::string str1 = "apple";
std::string str2 = "banana";
if (str1 == str2) {
std::cout << "字符串相等" << std::endl;
} else {
std::cout << "字符串不相等" << std::endl;
}
if (str1 < str2) {
std::cout << "str1 在字典序中排在 str2 之前" << std::endl;
} else {
std::cout << "str1 在字典序中不排在 str2 之前" << std::endl;
}
return 0;
}
输出:
字符串不相等
str1 在字典序中排在 str2 之前
在这个例子中,"apple"和"banana"首先在第一个字符'a'和'b'处进行比较。由于'a'的ASCII值小于'b',所以"apple"被认为小于"banana"。
比较C风格字符串
对于C风格字符串,不能直接使用关系运算符进行比较,因为它们实际上是指向字符数组首元素的指针。直接使用==
只会比较指针地址而不是字符串内容。
以下代码可能不会如您所期望的那样工作:
const char* cstr1 = "hello";
const char* cstr2 = "hello";
if (cstr1 == cstr2) { // 比较指针,而不是字符串内容
// ...
}
要比较C风格字符串的内容,应使用strcmp()
函数:
#include <iostream>
#include <cstring>
int main() {
const char* cstr1 = "apple";
const char* cstr2 = "banana";
int result = strcmp(cstr1, cstr2);
if (result == 0) {
std::cout << "字符串相等" << std::endl;
} else if (result < 0) {
std::cout << "cstr1 在字典序中排在 cstr2 之前" << std::endl;
} else {
std::cout << "cstr1 在字典序中排在 cstr2 之后" << std::endl;
}
return 0;
}
输出:
cstr1 在字典序中排在 cstr2 之前
strcmp()
函数返回:
- 0:如果两个字符串相等
- 小于0的值:如果第一个字符串小于第二个
- 大于0的值:如果第一个字符串大于第二个
使用compare()方法
std::string
类提供了一个更灵活的compare()
方法,它不仅可以比较整个字符串,还可以比较子串:
#include <iostream>
#include <string>
int main() {
std::string str1 = "Hello, world!";
std::string str2 = "Hello, C++!";
// 比较整个字符串
int result1 = str1.compare(str2);
std::cout << "完整比较结果: " << result1 << std::endl;
// 比较子串 (从索引0开始的7个字符)
int result2 = str1.compare(0, 7, str2, 0, 7);
std::cout << "子串比较结果: " << result2 << std::endl;
return 0;
}
输出:
完整比较结果: 1
子串比较结果: 0
compare()
方法与strcmp()
类似,返回:
- 0:如果字符串相等
- 负值:如果调用对象小于参数
- 正值:如果调用对象大于参数
compare()方法的变体
std::string::compare()
有多种重载形式:
// 比较与另一个string对象
int compare(const string& str) const;
// 比较子串
int compare(size_t pos, size_t len, const string& str) const;
int compare(size_t pos, size_t len, const string& str,
size_t subpos, size_t sublen) const;
// 比较与C风格字符串
int compare(const char* s) const;
int compare(size_t pos, size_t len, const char* s) const;
int compare(size_t pos, size_t len, const char* s, size_t n) const;
字符串比较的性能考量
在选择字符串比较方法时,还需要考虑性能因素:
- 对于简单的相等性检查,使用
==
运算符即可 - 当需要确定字典顺序时,使用
<
、>
等运算符或compare()
方法 - 对于大量重复比较相同字符串的场景,可以考虑哈希比较
- 对于C风格字符串,
strcmp()
通常比转换为std::string
然后比较更高效
如果只需要检查字符串开头是否匹配特定前缀或结尾是否匹配特定后缀,C++11引入的starts_with()
和ends_with()
方法(C++20标准)比进行完整比较更高效。如果你的编译器不支持这些函数,可以使用substr()
和比较或compare()
的子串版本。
大小写不敏感的字符串比较
默认情况下,C++的字符串比较是区分大小写的。要执行不区分大小写的比较,需要先将两个字符串转换为相同的大小写:
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
// 辅助函数:转换为小写
std::string toLower(const std::string& s) {
std::string result = s;
std::transform(result.begin(), result.end(), result.begin(),
[](unsigned char c) { return std::tolower(c); });
return result;
}
int main() {
std::string str1 = "Apple";
std::string str2 = "apple";
// 区分大小写的比较
std::cout << "区分大小写: " << (str1 == str2 ? "相等" : "不相等") << std::endl;
// 不区分大小写的比较
std::cout << "不区分大小写: " << (toLower(str1) == toLower(str2) ? "相等" : "不相等") << std::endl;
return 0;
}
输出:
区分大小写: 不相等
不区分大小写: 相等
实际应用场景
1. 用户输入验证
#include <iostream>
#include <string>
int main() {
std::string password = "securePassword123";
std::string userInput;
std::cout << "请输入密码: ";
std::cin >> userInput;
if (password == userInput) {
std::cout << "密码正确,欢迎进入系统!" << std::endl;
} else {
std::cout << "密码错误,访问被拒绝!" << std::endl;
}
return 0;
}
2. 字符串排序
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
int main() {
std::vector<std::string> fruits = {"banana", "apple", "orange", "grape", "kiwi"};
// 使用字符串比较进行排序
std::sort(fruits.begin(), fruits.end());
std::cout << "按字母顺序排序的水果:" << std::endl;
for (const auto& fruit : fruits) {
std::cout << fruit << std::endl;
}
return 0;
}
输出:
按字母顺序排序的水果:
apple
banana
grape
kiwi
orange
3. 命令解析
#include <iostream>
#include <string>
int main() {
std::string command;
while (true) {
std::cout << "> ";
std::cin >> command;
if (command == "exit" || command == "quit") {
std::cout << "程序退出..." << std::endl;
break;
} else if (command == "help") {
std::cout << "可用命令: help, version, exit, quit" << std::endl;
} else if (command == "version") {
std::cout << "程序版本: 1.0.0" << std::endl;
} else {
std::cout << "未知命令。输入'help'获取帮助。" << std::endl;
}
}
return 0;
}
总结
C++中的字符串比较有多种方法,主要取决于你使用的字符串类型和比较需求:
- 对于
std::string
对象,可以直接使用关系运算符 (==
,!=
,<
,<=
,>
,>=
) - 对于C风格字符串,应使用
strcmp()
函数 std::string
的compare()
方法提供了更灵活的比较选项,包括子串比较- 对于不区分大小写的比较,需要先将字符串转换为相同的大小写
选择适当的字符串比较方法不仅能让你的代码更简洁、更易读,还能在性能方面有所优化。字符串比较是构建更复杂字符串操作(如搜索、排序和模式匹配)的基础。
练习
- 编写一个程序,接受用户输入的两个字符串,然后比较它们是否相等(区分大小写和不区分大小写)
- 实现一个函数,按字典顺序比较两个字符串的前n个字符
- 编写一个程序,根据用户选择的排序方式(按字母升序、降序或长度)对输入的多个字符串进行排序
- 实现一个简单的通讯录应用,允许用户按姓名搜索联系人(支持模糊匹配)