Hippogriff's Blog
首页
C++
  • 算法
  • 数据结构
  • Leetcode
  • 操作系统
  • 计算机网络
  • MySQL
  • 深度学习
  • 网络
收藏
  • 醍醐灌顶
  • 句读
个人书单 (opens new window)
GitHub (opens new window)

Absm

什么也不会
首页
C++
  • 算法
  • 数据结构
  • Leetcode
  • 操作系统
  • 计算机网络
  • MySQL
  • 深度学习
  • 网络
收藏
  • 醍醐灌顶
  • 句读
个人书单 (opens new window)
GitHub (opens new window)
  • 【C++&Leetcode】自定义排序的方法与辨析
  • 关于优先队列priority_queue
  • 关于C++ STL size的坑
  • C++ 智能指针
  • C++ const
  • C++&STL中String常见函数用法
  • C++11的decltype
  • C++11右值引用【来自IBM文档】
  • C++11中循环auto的引用
  • C++中的lambda表达式
  • C风格字符串库函数总结
    • 计算长度
      • strlen
      • strspn
    • 比较
      • strcmp, strncmp, strcasecmp, strncasecmp
    • 查找字符(或字符集)
      • strchr
      • strpbrk
    • 分割字符串
      • strtok
    • 字符串拷贝
      • strcpy, strncpy
  • C与C++风格的字符串辨析
  • CMake基础命令
  • C++
Absm
2021-05-23
目录

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

输出:

After skipping initial lowercase letters from 'abcde312$#@'
The remainder is '312$#@'
1
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

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

返回值:

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

# 查找字符(或字符集)

# strchr

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

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

# strpbrk

const char* strpbrk( const char* dest, const char* breakset );
			char* strpbrk(       char* dest, const char* breakset );
1
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

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

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

编辑 (opens new window)
上次更新: 2021/06/03, 13:03:33
C++中的lambda表达式
C与C++风格的字符串辨析

← C++中的lambda表达式 C与C++风格的字符串辨析→

最近更新
01
少年游·长安古道马迟迟
11-30
02
CMake基础命令
11-08
03
由浅入深剖析OAuth2.0的授权码模式
07-07
更多文章>
Theme by Vdoing | Copyright © 2019-2023 Murray Li | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×