本文已整合到C语言标准库深度解读
为了看上去规整简洁,令
#define cSTR const char *str
#define vSTR const void *str
由于字符串自身存在终止符\0
,所以下面所有提及对字符串前n
个字符的操作,均默认n
小于字符串长度;若n
大于字符串长度,则对字符串整体进行操作。
首先,由于C语言中的字符串无非是终止于\0
的字符数组,数组中并未给我们提供任何长度信息,所以要有一个函数来计算字符串长度,此即
size_t strlen(cSTR)
然后认识一下用于分割字符串的strtok
char *strtok(char *str, const char *delim)
其功能为通过delim
将str
分解为一组小字符串,所谓分解,其实就是将分割符号替换为\0
;然后返回被分割之后的第一个字符串。
如果strtok
已经对某个字符串进行分割了,那么接下来需要将其表达式写为strtok(NULL, delim)
,这样可以逐一调出被分割的字符串。
//teststrtok.c
#include<stdio.h>
#include<string.h>
int main(){
char oldStr[50] = "I am micro tiny cold";
const char s[2] = " ";
printf("str length: %d\n", strlen(oldStr));
char* newStr = strtok(oldStr,s);
while(newStr != NULL){
printf("the oldStr is %s.\t", oldStr);
printf("the newStr is %s with length : %d\n", newStr, strlen(newStr));
newStr = strtok(NULL, s);
}
return 0;
}
测试结果为
>gcc testStrtok.c
>a.exe
str length: 20
the oldStr is I. the newStr is I with length : 1
the oldStr is I. the newStr is am with length : 2
the oldStr is I. the newStr is micro with length : 5
the oldStr is I. the newStr is tiny with length : 4
the oldStr is I. the newStr is cold with length : 4
接下来将string.h
中的函数分为四个类别,分别是查询,比较,复制和追加以及本地函数。
查询函数
查询函数 | 返回 | 类型 |
---|---|---|
void *memchr(vSTR, int c, size_t n) | str 前n 个字节中首次出现c 的位置 | 指针 |
char *strchr(cSTR, int c) | str 首次出现c 的位置 | 指针 |
char *strrchr(cSTR, int c) | str 最后出现c 的位置 | 指针 |
char *strstr(cSTR1, cSTR2) | str1 中首次次出现字符串str2 的位置 | 指针 |
char *strpbrk(cSTR1, cSTR2) | str1 中首个个属于str2 的字符的位置 | 指针 |
size_t strspn(cSTR1, cSTR2) | str1 中第一个不属于str2 的字符的索引 | 整数 |
char *strerror(int errnum) | 根据错误号errnum索引错误名 详见errno.h |
比较函数
比较函数 | 返回 |
---|---|
int memcmp(vSTR1, vSTR2, size_t n) | 比较str1 和str2 的前n个字节 |
int strncmp(cSTR1, cSTR2, size_t n) | 比较str1 和str2 的前n个字符 |
int strcmp(cSTR1, cSTR2) | 比较str1 和str2 |
size_t strcspn(cSTR1, cSTR2) | str1 开头连续不含str2 中字符的个数 |
注意
有关字符串str1
和str2
的比较中:
- 若二者相等,则返回0
- 若str1<str2,则返回值小于0
- 若str1>str2,则返回值大于0
复制和追加
下面用于字符串复制的函数,均返回一个指向目标字符串的指针。
复制 | |
---|---|
char *strcpy (char *dest, vSTR) | 将str 复制到dest |
char *strncpy (char *dest, cSTR, size_t n) | 把str 前n 个字符复制到 dest |
void *memset (void *str, int c, size_t n) | 将str 的前n 个字符设为c |
void *memcpy (void *dest, vSTR, size_t n)void * memmove (void *dest, vSTR, size_t n) | 将str 的前n 个字节复制到dest |
其中,strncpy
是对字符串的操作,而memcpy
是对内存块的操作。
如果内存块发生重叠,memmove
可以保证源字符串被覆盖之前,将重叠区域的字节复制到目标区域,所以比memcpy
更加安全。
所谓追加,无非是将一个字符串的内容复制到另一个字符串的结尾,本质上也可称为广义的复制。
追加 | |
---|---|
char *strcat(char *dest, cSTR) | 把str 追加到dest 结尾。 |
char *strncat(char *dest, cSTR, size_t n) | 把str 的前n 个字符追加到dest 结尾 |
本地函数
这里所谓的本地函数,就是受到locale.h
中LC_COLLATE
影响的函数,其功能和返回值取决于当前所在的地区。string.h
中共有两个本地函数,分别是用于字符串比较的strcoll
和用于更改字符串格式的strxfrm
。
对于前者,若我们想对一组汉字按照拼音进行排序,那么就要用到strcoll
,其声明为
int strcoll(cSTR1, cSTR2)
做一个测试
//testStrcoll.c
#include <stdio.h>
#include <string.h>
#include <locale.h>
void printStrcoll(const char *str1, const char *str2){
if(strcoll(str1,str2)>0)
printf("%s>%s\n",str1, str2);
else
printf("%s<%s\n",str1, str2);
}
int main (void)
{
printf ("默认比较:");
printStrcoll("甲","乙");
setlocale (LC_ALL, "");
printf ("拼音比较:");
printStrcoll("甲","乙");
return 0;
}
编译运行结果,由于我实在不熟悉汉字编码顺序,所以其内码比较和拼音比较的结果是一样的。另外,本程序用的是gcc11.2
进行编译的,低于10的版本可能会出现汉字乱码的情况。
>gcc testStrcoll.c
>a.exe
默认比较:甲>乙
拼音比较:甲>乙
另一个本地函数声明为
size_t strxfrm(char *dest, cSTR, size_t n)
其功能就是简单的将str
的前n
个字符转换为本地形式后复制到dest
中,返回值是被转换的字符长度。
关于setlocale
函数,详情请阅通过locale.h设置美元的格式。