c语言标准库详解(七):字符串函数<string.h>
头文件<string.h>中定义了两组字符串函数。第一组函数的名字以 str 开头;第二组函数的名字以 mem 开头。除函数 memmove 外,其它函数都没有定义重叠对象间的复制行为。比较函数将把参数作为 unsigned char 类型的数组看待。
第一组
在下表中,变量 s 和 t 的类型为 char *;cs 和 ct 的类型为 const char *;n 的类型为 size_t;c 的类型为 int(将被转换为 char 类型)。
函数名 | 功能 |
---|---|
char *strcpy(s,ct) | 将字符串 ct(包括’\0’)复制到字符串 s 中,并返回 s |
char *strncpy(s,ct,n) | 将字符串 ct 中最多 n 个字符复制到字符串 s 中,并返回 s。如果 ct 中少于 n 个字符,则用’\0’填充 |
char *strcat(s,ct) | 将字符串 ct 连接到 s 的尾部,并返回 s |
char *strncat(s,ct,n) | 将字符串 ct 中最多前 n 个字符连接到字符串 s 的尾部,并以’\0’结束;该函数返回 s |
int strcmp(cs,ct) | 比较字符串 cs 和 ct;当 cs<ct 时,返回一个负数;当 cs==ct 时,返回 0;当 cs>ct 时,返回一个正数 |
int strncmp(cs,ct,n) | 将字符串 cs 中至多前 n个字符与字符串 ct 相比较。当 cs<ct 时,返回一个负数:当 cs==ct 时,返回0;当 cs>ct 时,返回一个正数 |
char *strchr(cs,c) | 返回指向字符 c 在字符串 cs 中第一次出现的位置的指针;如果 cs 中不包含 c,则该函数返回 NULL |
char *strrchr(cs,c) | 返回指向字符 c 在字符串 cs 中最后一次出现的位置的指针;如果 cs 中不包含 c,则该函数返回 NULL |
size_t strspn(cs,ct) | 返回字符串 cs 中包含 ct 中的字符的前缀的长度 |
size_t strcspn(cs,ct) | 返回字符串 cs 中不包含 ct 中的字符的前缀的长度 |
char *strpbrk(cs,ct) | 返回一个指针,它指向字符串 ct 中的任意字符第一次出现在字符串 cs 中的位置;如果 cs 中没有与 ct 相同的字符,则返回 NULL |
char *strstr(cs,ct) | 返回一个指针,它指向字符串 ct 第一次出现在字符串 cs 中的位置;如果 cs 中不包含字符串 ct,则返回 NULL |
size_t strlen(cs) | 返回字符串 cs 的长度 |
char *strerror(n) | 退回一个指针,它指向与错误编号 n 对应的错误信息字符串(错误信息的具体内容与具体实现相关) |
char *strtok(s,ct) | strtok函数在s中搜索由ct中的字符界定的记号。详细信息参见下面的讨论 |
对 strtok(s, ct)进行一系列调用,可以把字符串 s 分成许多记号,这些记号以 ct 中的字符为分界符。第一次调用时,s 为非空。它搜索 s,找到不包含 ct 中字符的第一个记号,将 s 中的下一个字符替换为’\0’,并返回指向记号的指针。随后,每次调用 strtok 函数时(由 s 的值是否为 NULL 指示),均返回下一个不包含 ct 中字符的记号。当 s 中没有这样的记号时,返回 NULL。每次调用时字符串 ct 可以不同。
特别要注意分割处理后原字符串 str 会变,变成第一个子字符串
说白了,这个函数有状态
示例(除strtok外):
#include <stdio.h>
#include <string.h>
void printStr(char* src){
int i=0;
while(src[i]!='\0'){
printf("%c",src[i]);
i++;
}
printf("\n");
}
int main(){
char str1[512];
char str2[1024];
strcpy(str2,"Make America Great Again!");
printStr(str2);
strcpy(str1,"CNN Fake News!");
printStr(str1);
strncpy(str2,str1,6);
printStr(str2);
strcat(str2,str1);
printStr(str2);
printf("%d\n",strcmp(str1,str2));
printf("%d\n",strncmp(str1,str2,6));
printf("%c\n",*strchr(str2,'A'));
printf("%d\n",*strrchr(str2,'G'));
printf("%d\n",strspn(str2,str1));
printf("%d\n",strcspn(str2,"Human Right"));
printf("%d\n",strlen(str2));
}
输出:
PS G:\CSAPP> & 'c:\Users\swy\.vscode\extensions\ms-vscode.cpptools-0.27.0\debugAdapters\bin\WindowsDebugLauncher.exe' '--stdin=Microsoft-MIEngine-In-qgzcdwvk.gxf' '--stdout=Microsoft-MIEngine-Out-wj0yyhuh.y4x' '--stderr=Microsoft-MIEngine-Error-kyu4s343.tmb' '--pid=Microsoft-MIEngine-Pid-unlymjir.kfu' '--dbgExe=G:\x86_64-8.1.0-release-posix-sjlj-rt_v6-rev0\mingw64\bin\gdb.exe' '--interpreter=mi'
Make America Great Again!
CNN Fake News!
CNN Famerica Great Again!
CNN Famerica Great Again!CNN Fake News!
-1
0
A
71
6
3
39
PS G:\CSAPP>
示例(strtok):
#include <string.h>
#include <stdio.h>
int main () {
char str[80] = "This is a fan of-Quentin-Tarantino";
const char s[2] = "-";
char *token;
/* 获取第一个子字符串 */
token = strtok(str, s);
/* 继续获取其他的子字符串 */
while( token != NULL ) {
printf( "%s\n", token );
token = strtok(NULL, s);
}
printf("\n%s\n",str);
return(0);
}
输出:
PS G:\CSAPP> & 'c:\Users\swy\.vscode\extensions\ms-vscode.cpptools-0.27.0\debugAdapters\bin\WindowsDebugLauncher.exe' '--stdin=Microsoft-MIEngine-In-xns41bft.qby' '--stdout=Microsoft-MIEngine-Out-w212wzzk.mpb' '--stderr=Microsoft-MIEngine-Error-b1wdpiu5.l2i' '--pid=Microsoft-MIEngine-Pid-ojoy1rfn.zmg' '--dbgExe=G:\x86_64-8.1.0-release-posix-sjlj-rt_v6-rev0\mingw64\bin\gdb.exe' '--interpreter=mi'
This is a fan of
Quentin
Tarantino
This is a fan of
PS G:\CSAPP>
第二组
以 mem 开头的函数按照字符数组的方式操作对象,其主要目的是提供一个高效的函数接口。在下表列出的函数中,s 和 t 的类型均为 void * , cs 和 ct 的类型均为 const void * ,n 的类型为 size_t,c 的类型为 int(将被转换为 unsigned char 类型)
函数名 | 功能 |
---|---|
void *memcpy(s,ct,n) | 将字符串 ct 中的 n 个字符拷贝到 s 中,并返回 s |
void *memmove(s,ct,n) | 该函数的功能与 memcpy 相似,所不同的是,当对象重叠时,该函数仍能正确执行 |
int memcmp(cs,ct,n) | 将 cs 的前 n 个字符与 ct 进行比较,其返回值与 strcmp的返回值相同 |
void *memchr(cs,c,n) | 返回一个指针,它指向 c 在 cs 中第一次出现的位置。如果 cs 的前 n 个字符中找不到匹配,则返回 NULL |
void *memset(s,c,n) | 将 s 中的前 n 个字符替换为 c,并返回 s |
示例与前面差不多,就不写了⑧