C++基础笔记6
字符数组&字符串
定义&初始化
char str[] = {'a', 'b', 'c', 'd'};
char str[] = "abcd";
==注意:字符串包含最后\0
终止符,所以其实有五个元素==
因此字符串不完全等于字符数组, 终止字符可以直接用ASCII码值0来表示,字符形式需要用\0
来表示
如果再字符串中想定义双引号需要加\表示转义 char str[] = "abc\"";
否则遇到引号会认为字符结束了
因此字符串其实就等价于有终止字符的字符数组
字符串实际上是字符数组的首地址,因此字符串变量可以被看作是一个指向字符的指针。当我们对字符串变量进行加法或减法运算时,实际上是在进行指针运算
输入/输出
可以用循环输入 for(int i = 0;i < n;i ++) cin >> str[i];
但一般不会告诉你有几个字符,所以用scanf("%s", str);
和 cin >> str;
直接输入整个字符串是更好的选择
==注意会带终止字符,占用地址更大==
输出是会一直挨个遍历直到遇到了终止符,如果没有可能会输出乱码
普通输入会以空格分隔 例如
abc def
则读取到的字符串是
abc
可以使用
cin.getline(str, 10);//第一个参数是字符数组,第二个参数是最大输入的字符个数
或者
stdio.h
中的fgets(str, 10, stdin);//第三个参数表示从哪输入,stdin表示终端
<string.h>
中的常用函数
strlen
获取字符串长度
int len = strlen(str)
此长度并非数组长度而是以结束字符结尾的长度
strcpy
复制字符串
strcpy(dst, src)
将第二个字符串复制到第一个字符数组
要确保字符数组有足够的长度可以容纳归第二个字符串
==只会复制终止符前面的内容==
strcat
拼接
strcat(a,b)
将第二个字符串复制到第一个字符串的末尾,相当于两个字符串连接,同样需要确保内存大小
strcmp
比较大小
int order = strcmp(a,b);
比较两个字符串的字典序大小,返回其比较顺序
1 | order < 0 // a < b |
strstr
char *c = strstr(a,b);
判断字符串a是否包含字符串b,返回的结果是a中首次出现b的地址,类型为char *c
(指针类型)
如果用结果减去a,即int index = c - a;
则会返回下标;如果找不到b会返回NULL
(NULL 等价于 0)
直接判断结果可以知道a是否包含b
strtok
分隔字符串
将第一个字符串以第二个字符串中出现的字符进行分隔
找到第一个非分隔符的位置返回地址,如果没有则返回NULL,同时将这个地址之后的第一个分隔符转化为终止符
1 | char str[] = "= one + two * (three / four)"; |
输出token,则可以得到字符串one
并且strtok
是比较特殊的函数,它在调用时会记录上一次分隔的位置,再次调用时,第一个参数只需要传入NULL,可通过下述代码,token会指向这些位置
通过while循环,提取原字符串的one two three four
1 | while(token){ |
memset
& memcpy
对内存进行操作,由于字符的内存恰好是1byte,故也可以看作是对字符进行操作
memset(arr, ch, sizeof(arr));
- 第一个参数是内存的起始地址
- 第二个参数是设置的值,字符型(-128到127)
- 第三个参数是内存的长度
代表将内存中从这个字符数组开始,对应长度的内存都赋值为第二个参数
当然其他类型的数组也可以用memset
啦
但是,比如int占4个字节,如果赋值为1,对应的二进制是由四个值为1的字节组成的,即在内存中以4个00000001组成,其结果是一个大整数(但是0和-1没有问题,因为内存中0的二进制都是0来表示,-1都是1来表示)
memcpy
将一段内存从一个位置复制到另一个位置
memcpy(dst, src, sizeof(src));
- 第一个参数代表目标地址
- 第二个参数代表被复制的地址
- 第三个参数代表要复制的内存长度
用途:比如数组无法直接用等于号赋值,所以如果想对数组进行赋值,就可以直接用memcpy
<stdlib.h>
中的常见函数
==将字符串转化成数值==
atoi
& atoll
& atof
- a代表ASCII码表
i, f, ll
分别对应int
,float类型
,long long类型
(注意是代表float类型而不是转换成float,实际转化成double)
通过这些函数可以将字符串转化成对应类型的数值
例如cout << atoi("123") << endl;
字符串要是合法的数值,不然得到的结果是0. 例如cout << atof("abc") << endl;
<ctype.h>
中的常见函数
==用于判断字符的类型== (具体如下图)
isprint
判断是否是可打印字符
isspace
判断是否是空格
isgraph
判断是否是可绘制字符
ispunct
判断是否是标点符号
isalnum
判断字符串中的字符是否都是字母或数字
isdigit
判断是否是数字
isalpha
判断是否是字母
isupper
判断是否是大写字母
islower
判断是否是小写字母
toupper
& tolower
返回字母的大写或者小写形式
string
定义&初始化
引入头文件 include <string>
初始可直接用字符串
string str1 = "012345";
或者使用另一个字符串
string str2 = str1;
也可以像vector一样用长度加字符来初始化
string str3(6, '#');
也可以用括号代替等于号
string str4(str1);
或者string str5("012345");
利用
format
构造字符串形如:format("{0}.zip/{0}/{1}/{1}.cpp", id, problem)
这种用括号进行初始化的方式叫做构造函数
1 | //用括号的好处在于可用添加更多的参数 |
输入/输出
输入输出可以直接当一个普通变量来进行
使用
cin >> str;
也是根据空格分格;如果想要输入整行,需要使用
getline(cin, str);
同时也可以使用范围循环来遍历
string
的每个字符for (char& c: str) {};
比起C语言的字符串简单了很多,不需要考虑终止符,非常的直观清晰
string
所支持的运算&函数
==string
和vector
很像,但string
不属于容器==
支持的运算符
- = 赋值运算
- <=> 比较运算
- [ ] 下标访问运算
- + 加法运算,字符串的拼接
- += 直接将字符串加到末尾
支持的函数
访问
at —> 带范围检测的下标访问
front —> 获取第一个字符
back —> 获取最后一个字符
c_str —> 返回C语言字符
比如
printf("%s", str.c_str());
迭代器
- begin —> 起始迭代器
- end —> 末尾迭代器
容量
- empty —> 判断是否为空
- size —> 获取字符个数
- length —> 获取字符个数
修改
clear —> 清空字符串
resize —> 改变大小
push_back —> 将字符插入末尾
pop_back —> 移除末尾字符
insert —> 插入字符(串)
==除了可以使用迭代器表示位置外,还可以直接用下标表示==
例如
"abc"
插入后str.insert(1, "def");
得到字符串"abcdef"
erase —> 删除子串
str.erase(one, two);
同样可以用下标来表示第一个参数表示开始删除的位置,第二个参数表示删除的个数;如果第二个参数不填则默认删除之后所有的元素
append —> 将字符串插入末尾
replace —> 替换一段字串
str.replace(1,2,"xyz");
参数分别表示开始的位置,结束的位置,插入的元素(同样可以用下标表示位置)
操作
find —> 寻找字串首次出现的位置
对于字符串
"This is island";
int pos = str.find("is");
返回第一次出现的下标还可以指定从哪个下标开始查找
int pos = str.find("is", 3);
如果找不到会返回
string::npos
(string
的一个特殊值,代表没有找到,属于unsigned long long
类型,具体值是无符号整数的最大值,因为内存中全是1,所以也等于有符号的-1;所以有些代码会直接判断find的值是否为-1,来表示是否找到,和使用string::npos
来判断等价)substr —> 返回指定子串
string sub = str.substr(2,3);
根据开始下标(第一个参数)和返回长度(第二个参数)来返回一个子串,如果不填第二个参数,则返回开始下标到结尾子串starts_with —> 前缀判断
ends_with —> 后缀判断
bool res = str.starts_with("hel");
其他普通函数
stoi
—> 将string
转成数值(同样有stoll
和stod
的版本)to_string
—> 将数值转成string
- 用
format
构造函数 —>string str = format("d = {:.0f}", d);