C风格字符串常用库函数

C风格字符串常用库函数

C风格字符串对应的string.hcstring中有很多常用的库函数,但是不经常使用的话会容易忘记用法,或者一些使用细节。

本文对常见字符串做一些总结与备忘,主要是最近使用过的库函数。

参考内容为cppreference.com

计算长度

strlen

std::size_t strlen( const char* str );

计算长度,注意它是不含终止符'\0'的,要想计算带终止符的,可以使用sizeof。

strspn

size_t strspn( const char* dest, const char* src );

这个函数的作用是:如果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";
}

输出:

After skipping initial lowercase letters from 'abcde312$#@'
The remainder is '312$#@'

比较

strcmp, strncmp, strcasecmp, strncasecmp

int strcmp( const char *lhs, const char *rhs );
int strncmp( const char *lhs, const char *rhs, std::size_t count );

前两个是原型,也就是是否带n决定了比较多少个元素。后面两个带case的表示是忽略大小写的。

返回值:

  • 相等:返回0
  • 大于:返回正数
  • 小于:返回负数

查找字符(或字符集)

strchr

const char* strchr( const char* str, int ch );
			char* strchr(       char* str, int ch );

ch是目标字符,str是一个字符数组,返回的是指向第一个ch位置的指针

strpbrk

const char* strpbrk( const char* dest, const char* breakset );
			char* strpbrk(       char* dest, const char* breakset );

与strchr的区别是,可以传入一个目标字符集breakset,只要找到字符集中的一个,那就返回一次指针,指向的是dest中第一次出现字符集中字符的位置。

分割字符串

strtok

char* strtok( char* str, const char* delim );

这个函数十分复杂。

  • 首先,它的作用是利用分隔符分割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, " ");
}

思考为什么每次调用都会记住上一次的位置呢,其实是库中存在一个静态变量(姑且称之为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 );

没什么好说的,从src拷贝到dest。注意后者(可以指定长度的)是不保证拷贝终止符的,因此要手动添加。

posted @ 2021-05-23 19:32  Molinchn  阅读(137)  评论(0编辑  收藏  举报