C风格字符串库函数总结
# C风格字符串常用库函数
C风格字符串对应的string.h
和cstring
中有很多常用的库函数,但是不经常使用的话会容易忘记用法,或者一些使用细节。
本文对常见字符串做一些总结与备忘,主要是最近使用过的库函数。
参考内容为cppreference.com
# 计算长度
# strlen
std::size_t strlen( const char* str );
1
计算长度,注意它是不含终止符'\0'
的,要想计算带终止符的,可以使用sizeof。
# strspn
size_t strspn( const char* dest, const char* src );
1
这个函数的作用是:如果dest的一个前缀的全部字符都在src中,计算dest中这种前缀的最大长度。也就是dest前面有多少src中的字符。
它常用的做法是用来跳过某些分隔符,如空格,逗号等。
例如:
#include <cstring>
#include <string>
#include <iostream>
const char *low_alpha = "qwertyuiopasdfghjklzxcvbnm";
int main()
{
std::string s = "abcde312$#@";
std::size_t spnsz = std::strspn(s.c_str(), low_alpha);
std::cout << "After skipping initial lowercase letters from '" << s
<< "'\nThe remainder is '" << s.substr(spnsz) << "'\n";
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
输出:
After skipping initial lowercase letters from 'abcde312$#@'
The remainder is '312$#@'
1
2
2
# 比较
# strcmp, strncmp, strcasecmp, strncasecmp
int strcmp( const char *lhs, const char *rhs );
int strncmp( const char *lhs, const char *rhs, std::size_t count );
1
2
2
前两个是原型,也就是是否带n决定了比较多少个元素。后面两个带case的表示是忽略大小写的。
返回值:
- 相等:返回0
- 大于:返回正数
- 小于:返回负数
# 查找字符(或字符集)
# strchr
const char* strchr( const char* str, int ch );
char* strchr( char* str, int ch );
1
2
2
ch是目标字符,str是一个字符数组,返回的是指向第一个ch位置的指针
# strpbrk
const char* strpbrk( const char* dest, const char* breakset );
char* strpbrk( char* dest, const char* breakset );
1
2
2
与strchr的区别是,可以传入一个目标字符集breakset,只要找到字符集中的一个,那就返回一次指针,指向的是dest中第一次出现字符集中字符的位置。
# 分割字符串
# strtok
char* strtok( char* str, const char* delim );
1
这个函数十分复杂。
- 首先,它的作用是利用分隔符分割str字符串,其中delim是一个「分隔符集」
- 为了理解它的返回值,必须理解该函数的行为过程。strtok会首先找到第一个“在str但是不在delim”中的字符,为了表述方便我们称之为「开始点」。然后继续找到下一个同时存在于str和delim的字符位置。接着会有一个重要的行为:把这个位置的字符串置为
'\0'
。也就是说,str的值被改变了,这一点很重要,这也是为什么str并非const,而且该函数也不是线程安全的。 - 返回值是上一条所属的「开始点」。由于后面被写了结束符,所以从开始点开始的一个字符串其实是完整的。
- 这个函数远不止于此,它的另一个重要特性是:可以反复调用。当你反复调用strtok时,它会返回下一个被delim分割的字符串。直到最后没有剩余字符串了,他会返回null。因此通常以这种形式调用它
char input[100] = "A bird came down the walk";
char *token = std::strtok(input, " ");
while (token) {
std::cout << token << '\n';
token = std::strtok(nullptr, " ");
}
1
2
3
4
5
6
2
3
4
5
6
思考为什么每次调用都会记住上一次的位置呢,其实是库中存在一个静态变量(姑且称之为left),每次调用时其实并不是从begin开始的,而是从left开始。那strtok怎么知道,到底是从这个left开始,还是从begin开始呢。毕竟程序员的操作千奇百怪,可能并不是一直调用到结束。**这里仔细观赏上面代码的第五行会发现,它第一个变量传入的并不是str,而是nullptr。这就是判断的关键点,当传入nullptr时才会从left开始,否则都会从begin开始。**这样使用时只要遵循上面的方法,就可以很容易分割字符串了。
# 字符串拷贝
# strcpy, strncpy
char* strcpy( char* dest, const char* src );
char *strncpy( char *dest, const char *src, std::size_t count );
1
2
2
没什么好说的,从src拷贝到dest。注意后者(可以指定长度的)是不保证拷贝终止符的,因此要手动添加。
编辑 (opens new window)
上次更新: 2021/06/03, 13:03:33