前言
在阅读过程中有任何问题都可以发布到评论区,有价值的问题将会放到文章末尾Q&A之中!
什么是字符串 由多个字符组成的长序列 叫做字符串。
字符串是计算机和人类进行沟通的手段之一。
人类以字符串形式向计算机输入代码指令,计算机将其转化为 01 代码进行识别,最后将结构再以字符串形式展示给人类。
ASCII码表 在计算机内部,每个字符都对应有一个整数进行表示,计算机再将这个整数转化为二进制进行识别。
这个字符与整数对应的表 为 ASCII 码表 。
具体对应关系如下图所示。
在使用的过程中,常用的字符有:'0' 对应整数 48,'A' 对应整数 65, 'a' 对应整数 97。
在使用 ASCII 码表时,无需特殊记忆所有的内容,在做题过程中如果需要用到该表可以直接打表输出 即可。
1 2 3 4 5 6 7 8 9 10 11 #include <iostream> using namespace std;int main () { for (int i = 0 ; i <= 128 ; i ++){ cout << i << " : " << (char )i << endl; } return 0 ; }
整数与字符转化 每个字符都有自己对应的 ASCII 码值,均可以实现整数与字符的相互转化 。
1 2 3 4 5 6 7 8 9 10 11 12 #include <iostream> using namespace std;int main () { char c = 'a' ; cout << c << " 字符对应整数为: " << (int )c << endl; int num = 65 ; cout << num << " 整数对应字符为:" << (char )num << endl; return 0 ; }
字符运算 因为每个字符都对应有一个整数表示,所有字符 也可以直接进行运算 ,参与运算时使用该字符对应的整数 进行运算。
1 2 3 4 5 6 7 8 9 10 11 12 13 #include <iostream> using namespace std;int main () { int a = 'a' - 'A' ; int b = 'A' * 'B' ; char c = 'A' + 2 ; cout << "a - A = " << a << endl; cout << "A * B = " << b << endl; cout << "A + 2 = " << c << endl; return 0 ; }
做题技巧 在做题的过程中,如果涉及到字符的判断,可以直接对字符 进行判断,也可以使用其对应的 ASCII 码 进行判断。
例题:输入一行字符,统计出其中数字字符的个数,以及字母字符的个数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <iostream> using namespace std;int main () { char c; int nums = 0 , chars = 0 ; while (cin >> c){ if (c >= '0' && c <= '9' ) nums ++; else if (c >= 97 && c <= 122 ) chars ++; else if (c >= 65 && c <= 'Z' ) chars ++; else break ; } cout << nums << " " << chars << endl; return 0 ; }
字符串 字符数组 定义一个 char 类型的数组 就是一个字符数组 。
字符数组和字符串是极其类似的,字符串 就是在**字符数组的末尾再加上一个结束符 ‘\0’**。
该结束符的意义是指明该字符串是在哪里结束 。
可以使用字符串来初始化字符数组,但此时要注意,每个字符串结尾会暗含一个’\0’字符 ,因此字符数组的长度至少要比字符串的长度多1 !同时,如果数组范围没有预留结束符的位置 ,使用字符串初始化的方式是错误的 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #include <iostream> using namespace std;int main () { char a1[] = {'C' , '+' , '+' }; char a2[] = {'C' , '+' , '+' ,'\0' }; char a3[] = "C++" ; char a4[6 ] = "ABCDEF" ; cout << "a1 长度为:" << sizeof a1 << endl; cout << "a2 长度为:" << sizeof a2 << endl; cout << "a3 长度为:" << sizeof a3 << endl; cout << "a4 长度为:" << sizeof a4 << endl; return 0 ; }
输入 可以直接使用 cin 字符串名 进行输入。
但是使用 cin 进行输入时,不会将空格识别为字符 。
即当输入的字符串包含空格时,只会识别到空格之前的字符串。
1 2 3 4 5 6 7 8 9 10 11 12 #include <iostream> using namespace std;int main () { char str[100 ]; cin >> str; cout << str << endl; return 0 ; }
想要输入包含空格的字符串时,需要用到 fgets() 函数.
fgets() 函数当遇到回车才表示输入结束 ,当遇到空格 时,会将其识别为字符 。
fgets() 函数默认三个参数,第一个参数填写 字符串名,第二个参数填写 字符串长度【表示最多读入到哪个字符】,第三个参数默认填写 stdin
1 2 3 4 5 6 7 8 9 10 11 12 #include <iostream> using namespace std;int main () { char str[100 ]; fgets (str, 100 , stdin); cout << str << endl; return 0 ; }
注意在某些课程中会提供一个 gets() 函数,在最新的 C++ 标准中已经将其删除 ,目前使用的话有可能不会报错,但是在竞赛中是属于错误的语法!!!
使用 scanf 也可以输入字符串,对应的标准格式类型为 %s 。
但是要注意和其他类型变量不同的是,在输入字符串时,scanf 不需要添加 &。
因为数组名会自动指向数组首元素的地址 ,无需再次引用。
同时,与 cin 相同,scanf 也不能识别空格 ,需要使用 fgets 函数进行输入。
1 2 3 4 5 6 7 8 9 10 #include <iostream> using namespace std;int main () { char str[100 ]; scanf ("%s" , str); cout << str << endl; return 0 ; }
做题技巧 输入默认的下标是从 0 开始 的。
想要输入的下标从非 0 位置开始 ,可以输入时,输入 字符串名 + 长度 来改变起始下标。
1 2 3 4 5 6 7 8 9 10 11 #include <iostream> using namespace std;int main () { char str[100 ]; cin >> str + 1 ; cout << str + 1 << endl; return 0 ; }
输出 输出可以直接用 cout / printf 进行输出
此外,想要从第几个字符开始进行输出,可以使用输出 字符串名 + 数量 的方式进行输出.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include <iostream> using namespace std;int main () { char a1[100 ] = "ABCDEFG" ; cout << a1 << endl; cout << a1 + 1 << endl; cout << a1 + 2 << endl; cout << a1 + 3 << endl; return 0 ; }
字符串的输出还有一个常用的函数 puts()。
可以直接输出字符串 或者在括号内填写字符串名输出该字符串 并且换行 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <iostream> using namespace std;int main () { puts ("Hello World!!" ); char a[100 ] = "ABCDEFG" ; puts (a); return 0 ; }
常用函数 在 C++ 中,字符串有一些常用的函数方便程序的编写。
在使用字符串的函数时,需要引入头文件 #include <cstring>.
常用的函数有如下几个:
strlen(字符串名),求字符串的长度 .
strcmp(字符串a, 字符串b),比较两个字符串 的大小,比较的方式是使用**字典序[ASCII 码小的就小]**进行比较。
a < b 返回 -1
a == b 返回 0
a > b 返回 1
strcpy(字符串a, 字符串b),将字符串b复制 给从a开始的字符串。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #include <iostream> #include <cstring> using namespace std;int main () { char a[100 ] = "Hello World!" ; cout << "strlen(a) = " << strlen (a) << endl; char b[100 ] = "abc" ; char c[100 ] = "aaa" ; cout << "strcmp(b, c) = " << strcmp (b, c) << endl; char d[100 ]; strcpy (d, a); cout << "d = " << d << endl; return 0 ; }
遍历 字符串本质是字符数组,所以和数组的遍历方式相似 。
在读取长度 时,用 strlen 函数读取。
在做题过程中,防止每次循环都计算一次长度,一般使用额外一个变量提前计算长度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #include <iostream> #include <cstring> using namespace std;int main () { char a[100 ] = "Hello World!" ; int len = strlen (a); for (int i = 0 ; i < len; i ++ ){ cout << a[i] << endl; } return 0 ; }
例题:给定一个只包含小写字母的字符串,请你找到第一个仅出现一次的字符。如果没有,输出“no”。
解题思路:输入的字符串只包含小写字母,共 26 个,可以额外使用一个数组来记录每个字符出现的次数,最后在重新遍历字符串,判断其对应数组值是否为 1 即可。
注意在最后遍历时要遍历原字符串 ,不可遍历计数数组 ,因为题目要求时输出第一个只出现一次的字符,不是字典序中最小的只出现一次的字符。
如果遍历计数数组的话,假如输入za,按照题目要求应该输出 z,但是遍历计数数组会输出 a
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 #include <iostream> #include <cstring> using namespace std;char str[100010 ];int cnt[30 ];int main () { cin >> str; int len = strlen (str); for (int i = 0 ; i < len; i ++){ cnt[str[i] - 'a' ] ++; } for (int i = 0 ; i < len; i ++){ if (cnt[str[i] - 'a' ] == 1 ){ cout << str[i] << endl; return 0 ; } } puts ("no" ); return 0 ; }
String 在 C++ 中,C++ 的标准库 (STL) 是 C++ 的核心组成部分之一,其中提供了大量的数据结构和算法。
string 是 STL 中用于处理字符串的一个标准库。
在使用该标准库对字符串进行操作时,要调用头文件 #include <string>
定义和初始化 string 定义字符串的方式和变量定义的方式是相同的,直接 string 变量名; 即可。
在初始化 string 类型字符串时有三种方法。
直接定义为一个字符串。
直接定义等于另一个 string 类型字符串。
定义为重复的单个字符。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <iostream> #include <string> using namespace std;int main () { string s1; string s2 = "Hello World!" ; string s3 = s2; string s4 (10 , 'c' ) ; return 0 ; }
输入输出 可以直接使用 cin/cout 实现 string 类型字符串的输入输出。
1 2 3 4 5 6 7 8 9 10 11 12 #include <iostream> #include <string> using namespace std;int main () { string s1, s2; cin >> s1 >> s2; cout << "s1 = " << s1 << " s2 = " << s2 << endl; return 0 ; }
但是和数组类型字符串相同,使用 cin 输入同样不识别空格 。
string 类型读取空格 需要使用 getline 函数实现。
getline语法:getline(cin, 字符串名)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #include <iostream> #include <string> using namespace std;int main () { string s; getline (cin, s); cout << s << endl; return 0 ; }
常用操作 拼接字符串 string 字符串可以直接进行拼接,直接相加 即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include <iostream> #include <string> using namespace std;int main () { string s1 = "Hello" ; string s2 = " World!" ; cout << "s1 = " << s1 << " s2 = " << s2 << endl; string s = s1 + s2; cout << "拼接后字符串为:" << s << endl; return 0 ; }
如果使用数组形式字符串进行拼接 时,需要进行两次遍历 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 #include <iostream> #include <cstring> using namespace std;int main () { char s1[] = "Hello" ; char s2[] = " World!" ; char s3[110 ]; int len1 = strlen (s1), len2 = strlen (s2); int cnt = 0 ; for (int i = 0 ; i < len1; i ++ ){ s3[cnt] = s1[i]; cnt ++; } for (int i = 0 ; i < len2; i ++ ){ s3[cnt] = s2[i]; cnt ++; } for (int i = 0 ; i < strlen (s3); i ++ ){ cout << s3[i]; } cout << endl; return 0 ; }
常用函数
size():返回字符串的长度 。
empty():检查字符串是否为空 。
operator[]:通过索引访问 字符串中的字符 。
substr():获取子字符串 。
find():查找子字符串 在主字符串中的位置 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 #include <iostream> #include <string> using namespace std;int main () { string s1 = "Hello, World!" ; cout << "原字符串: " << s1 << endl; cout << "s1 的长度为: " << s1.size () << endl; cout << "该字符串是否为空?" << (s1.empty () ? "Yes" : "No" ) << endl; cout << "下标为 7 的元素为: " << s1[7 ] << endl; string sub = s1.substr (7 , 5 ); cout << "从下标为 7 的位置开始获取长度为 5 的字串: " << sub << endl; cout << "字串 “World” 的下标开始位置为: " << s1.find ("World" ) << endl; return 0 ; }
Q&A