C++ 字符串比较

校验密码是否正确,或者把一组单词按字母顺序排列,都需要对字符串进行比较。

在 C++ 中,比较 std::string 字符串一般分为 2 种方式:一种是 “使用比较运算符”,另一种是 “使用 compare() 函数”。其中比较运算符直观好读,是我们平时最推荐掌握的方式。

判断字符串是否相等

如果我们想知道两个字符串的内容是否完全一样,可以直接使用比较运算符中的 ==;如果想判断它们是否不同,则使用 !=。

语法:

s1 == s2
s1 != s2

说明:

只有当两个字符串的字符内容、排列顺序以及长度都完全相同时,== 才会返回 true。只要有任何一个字符不同,或者中间多了一个空格,!= 就会返回 true。

跟拼接字符串类似,使用 == 或 != 时,只要左右两边至少有一边是 std::string 变量,另一边直接写双引号字符串字面量也是完全合法的,比如 input == "admin"。

示例 1:判断字符串是否相等

#include <iostream>
#include <string>

int main() {
    std::string s1 = "lvyenet";
    std::string s2 = "lvyenet";
    std::string s3 = "lvye net";

    if (s1 == s2) {
        std::cout << "s1 与 s2 相等" << '\n';
    }
    if (s1 != s3) {
        std::cout << "s1 与 s3 不相等" << '\n';
    }
    if (s1 == "lvyenet") {
        std::cout << "内容匹配成功" << '\n';
    }
    return 0;
}

运行结果如下。

s1 与 s2 相等
s1 与 s3 不相等
内容匹配成功

分析:

在这个例子中,s1 和 s2 保存的字符完全相同,所以 s1 == s2 成立。s3 中间多了一个空格,空格本身也算一个字符,因此 s1 != s3 成立。同时,s1 == "lvyenet" 也直接完成了变量与字面量的内容比对。

这里需要特别注意,不能把两个 C 风格字符串直接使用 == 比较内容。对两个 char 数组写 ==,比较的是它们在内存中的存放地址,哪怕两个数组保存的文字一模一样,比较结果也会是 false。

此外,C++ 的字符串比较严格区分英文字母的大小写。也就是说,"Admin" 和 "admin" 并不会被当成相同的字符串,下面我们来看一个例子。

示例 2:比较时区分大小写

#include <iostream>
#include <string>

int main() {
    std::string input = "Admin";
    std::string target = "admin";

    if (input != target) {
        std::cout << "两个字符串不相等" << '\n';
    }
    return 0;
}

运行结果如下。

两个字符串不相等

分析:

input 的首字母是大写 'A'(ASCII 码为 65),而 target 的首字母是小写 'a'(ASCII 码为 97),两者的编码值不同,因此 input != target 成立。

如果我们希望在比较时忽略字母的大小写差异,可以先将字符串统一转为小写再进行比较,后面在 “C++ 字符串大小写转换” 一节中会展开介绍。

C++ 字符串大小比较

除了判断相等之外,std::string 还支持使用 <、>、<=、>= 来比较两个字符串的大小。很多初学的小伙伴会觉得好奇:“数字可以比大小,那两个字符串比大小到底是在比什么呢?难道是比谁的长度更长吗?”

其实字符串比大小跟长度没有直接关系,它的规则跟平时查英文字典非常相似,在编程中也叫 “字典序比较”。

具体来说,程序会从两个字符串的第一个字符开始,从左往右逐个对比字符的 ASCII 码。一旦遇到第一个不相同的字符,谁的 ASCII 码大,谁所在的字符串就大,后面的字符就不需要再比了。

语法:

s1 < s2
s1 > s2

说明:

对于常见的数字和英文字母,小伙伴们不用去死记具体的编码数值,只需要记住下面这个先后顺序即可:

数字字符 '0' ~ '9' 小于大写字母 'A' ~ 'Z',而大写字母又小于小写字母 'a' ~ 'z',同一组内部按数字或字母表顺序从小到大排列。

示例 3:按字典序比较大小

#include <iostream>
#include <string>

int main() {
    std::string a = "abcde";
    std::string b = "abxde";

    if (a < b) {
        std::cout << "abcde 小于 abxde" << '\n';
    }

    std::string s1 = "cat";
    std::string s2 = "banana";

    if (s1 > s2) {
        std::cout << "cat 大于 banana" << '\n';
    }
    return 0;
}

运行结果如下。

abcde 小于 abxde
cat 大于 banana

分析:

先看第一组 a 和 b:它们的前两个字符都是 'a' 和 'b',无法区分大小。比到第 3 个字符时,'c' 的 ASCII 码小于 'x',因此直接得出 "abcde" 小于 "abxde",后面的 "de" 就不再比较了。

再看第二组 s1 和 s2:虽然 "cat" 只有 3 个字母,而 "banana" 有 6 个字母,但在对比第一个字符时,'c' 的编码值(99)大于 'b' 的编码值(98),在开头就已经分出了大小,因此 "cat" 大于 "banana"。

那如果两个字符串前面的字符全都一模一样,直到其中一个字符串先结束,此时又应该怎么判断呢?这种情况下,后面还有剩余字符的那个字符串更大,请看下面例子。

示例 4:前缀相同时比较大小

#include <iostream>
#include <string>

int main() {
    std::string s1 = "app";
    std::string s2 = "apple";

    if (s1 < s2) {
        std::cout << "app 小于 apple" << '\n';
    }
    return 0;
}

运行结果如下。

app 小于 apple

分析:

"app" 和 "apple" 的前 3 个字符完全相同。此时 "app" 已经没有后续字符了,而 "apple" 后面还有 "le",因此 "app" 小于 "apple"。

这里小伙伴们还要留意一个反直觉的细节:如果拿两个数字字符串直接比大小,比如 "9" 和 "10",得到的结果会是 "9" > "10"。

这是因为字符串永远是从左往右逐个比字符,首字符 '9' 的编码值(57)大于 '1' 的编码值(49),程序并不会把它们当成数学上的整数 9 和 10 来比较。

使用 compare() 函数(了解)

除了使用比较运算符之外,std::string 还提供了一个 compare() 成员函数。它的比较规则跟前面完全一致,只不过它返回的不是 true 或 false,而是一个 int 整数。

语法:

s1.compare(s2)

说明:

调用 s1.compare(s2) 后,我们可以根据返回值与 0 的大小关系来判断比较结果,具体分为以下 3 种情况:

  • 返回值小于 0:表示 s1 小于 s2。
  • 返回值等于 0:表示 s1 等于 s2。
  • 返回值大于 0:表示 s1 大于 s2。

示例 5:使用 compare() 函数

#include <iostream>
#include <string>

int main() {
    std::string a = "apple";
    std::string b = "banana";

    int result = a.compare(b);

    if (result < 0) {
        std::cout << "a 小于 b" << '\n';
    } else if (result == 0) {
        std::cout << "a 等于 b" << '\n';
    } else {
        std::cout << "a 大于 b" << '\n';
    }
    return 0;
}

运行结果如下。

a 小于 b

分析:

a.compare(b) 会依次对比 "apple" 和 "banana" 的字符。由于首字母 'a' 小于 'b',函数返回一个负数,程序进入 if...else 语句的第一个分支并输出结果。

需要注意的是,C++ 标准只规定 compare() 返回负数、0 或正数,并不一定返回 -1 或 1,有些编译器会直接返回字符的编码差值。因此判断时应该写成 result < 0 或 result > 0,不要写成 result == -1。

在实际开发中,直接使用 ==、!=、<、> 比调用 compare() 直观得多,推荐大家优先使用比较运算符。

上一篇:

下一篇:

给站长反馈

绿叶网正在不断完善中,小伙伴们如果发现任何问题,还望多多给站长反馈,谢谢!

邮箱:lvyenet@vip.qq.com

「绿叶网」服务号
绿叶网服务号放大
关注服务号,微信也能看教程。
绿叶网服务号