字符串处理
- 一 测试字符串长度函数
-
- 二 字符串拷贝函数
-
- 2.1 strcpy
-
- 2.1.1 例子
- 2.1.2 自己写一个strcpy函数
- 2.2 strncpy
-
- 2.2.1 例子
- 2.2.2 自己写一个strncpy函数
- 三 字符串拼接函数
-
- 3.1 strcat
-
- 3.1.1 例子
- 3.1.2 自己写一个strcat函数
- 3.2 strncat
-
- 3.2.1 例子
- 3.2.2 自己写一个strncat函数
- 四 字符串比较函数
-
- 4.1 strcmp
-
- 4.1.1 例子
- 4.1.2 自己写一个strcmp函数
- 4.2 strncmp
-
- 4.2.1 例子
- 4.2.2 自己写一个strncmp函数
- 五 字符串变换函数
-
- 5.1 strchr 字符匹配函数
-
- 5.1.1 例子:搜索字符b并替换成字符#
- 5.1.2 自己写一个strchr函数
- 5.2 strstr 字符串匹配函数
-
- 5.2.1 例子:搜索字符串abc并替换成字符串###
- 5.2.2 自己写一个strstr函数
- 5.3 memset 内存空间设置函数
-
- 5.3.1 memset函数不是字符串操作函数是内存操作函数,不会与'\0'停止
- 5.3.2 自己写一个memset函数
- 5.4 atoi atol atof 字符串转换函数
-
- 5.4.1 例子
- 5.4.2 自己写一个atoi, atol, atof函数
- 5.5 strtok 字符串分割函数
-
- 六 sprintf组包
- 七 sscanf解包
- 八 sscanf高级用法
-
- 8.1 高级用法一:使用%*s %*d跳过提取的内容(不要提取到的内容)
- 8.2 高级用法二:使用%ns %nd提取提取指定宽度n字符串或数值
- 8.3 高级用法三:支持集合操作
- 以str开头的函数都是遇到’\0’结束;
- 以str开头的函数都用头文件string.h;
一 测试字符串长度函数
1.1 strlen
函数原型:int strlen(const char *str)
功能:计算字符串的长度,不含'\0'
参数:存放字符串的内存空间的首地址
[root@ansible9 ~]
int main(int arg, char *argv[])
{
char buf1[20]="abc";
printf("buf1的sizeof是:%d\n",(int)sizeof(buf1));
printf("buf1的strlen是:%d\n",(int)strlen(buf1));
printf("%d\n",(int)strlen("abc"));
char buf2[]="abc";
printf("buf2的sizeof是:%d\n",(int)sizeof(buf2));
printf("buf2的strlen是:%d\n",(int)strlen(buf2));
char buf3[]="abc\0de";
printf("buf3的sizeof是:%d\n",(int)sizeof(buf3));
printf("buf3的strlen是:%d\n",(int)strlen(buf3));
printf("%d\n",(int)strlen("abc\0de"));
char buf4[]="abc\123de";
printf("buf4的sizeof是:%d\n",(int)sizeof(buf4));
printf("buf4的strlen是:%d\n",(int)strlen(buf4));
char buf5[]="\0abc";
printf("buf5的sizeof是:%d\n",(int)sizeof(buf5));
printf("buf5的strlen是:%d\n",(int)strlen(buf5));
}
[root@ansible9 ~]
buf1的sizeof是:20
buf1的strlen是:3
3
buf2的sizeof是:4
buf2的strlen是:3
buf3的sizeof是:7
buf3的strlen是:3
3
buf4的sizeof是:7
buf4的strlen是:6
buf5的sizeof是:5
buf5的strlen是:0
二 字符串拷贝函数
2.1 strcpy
函数原型:char *strcpy(char *dest, const char *src)
功能:把src所指向的字符串复制到dest所指向的空间中
返回值:返回dest字符串首地址
注意:遇到'\0'会结束;'\0'也会被拷贝过去
2.1.1 例子
[root@ansible9 ~]
int main(int arg, char *argv[])
{
char s[]="abc\0def";
char d[128]="\0";
strcpy(d,s);
printf("%s\n",d);
}
[root@ansible9 ~]
abc
2.1.2 自己写一个strcpy函数
[root@ansible9 ~]
char * my_strcpy(char *dest, const char *src)
{
char* tmp=dest;
while((*src != '\0') && (*dest=*src) && (src++) && (dest++));
return tmp;
}
int main(int arg, char *argv[])
{
char s[]="abc\0def";
char d[128]="\0";
my_strcpy(d,s);
printf("%s\n",d);
}
[root@ansible9 ~]
abc
2.2 strncpy
函数原型:char *strncpy(char *dest, const char *src, int num)
功能:将src所指向的字符串的前num个字符复制到dest所指向的内存空间
返回值:返回dest字符串的首地址
注意:'\0'不拷贝
2.2.1 例子
[root@ansible9 ~]
int main(int arg, char *argv[])
{
char s[]="abc\0def";
char d[128]="\0";
strncpy(d,s,2);
printf("%s\n",d);
}
[root@ansible9 ~]
ab
2.2.2 自己写一个strncpy函数
[root@ansible9 ~]
char * my_strncpy(char *dest, const char *src, int n)
{
char* tmp=dest;
int i=0;
while((*src != '\0') && (i) && (++i) && (*dest=*src) && (src++) && (dest++));
return tmp;
}
int main(int arg, char *argv[])
{
char s[]="abc\0def";
char d[128]="\0";
my_strncpy(d,s,2);
printf("%s\n",d);
}
[root@ansible9 ~]
ab
三 字符串拼接函数
3.1 strcat
函数原型:char *strcat(char *dest, const char *src)
功能:将src的字符串拼接到dest末尾
返回值:dest的首地址
3.1.1 例子
[root@ansible9 ~]
int main(int arg, char *argv[])
{
char s[]="abc\0def";
char d[128]="123\0999";
strcat(d,s);
printf("%s\n",d);
}
[root@ansible9 ~]
123abc
3.1.2 自己写一个strcat函数
[root@ansible9 ~]
char * my_strcat(char *dest, const char *src)
{
char* tmp=dest;
while(*dest != '\0' && dest++);
while((*src != '\0') && (*dest=*src) && (src++) && (dest++));
*dest='\0';
return tmp;
}
int main(int arg, char *argv[])
{
char s[]="abc\0def";
char d[128]="123\0999";
my_strcat(d,s);
printf("%s\n",d);
}
[root@ansible9 ~]
123abc
3.2 strncat
函数原型:char *strncat(char *dest, const char *src, size_t n);
功能:将src字符串的前n个字符拼接到dest末尾
返回值:dest的首地址
3.2.1 例子
[root@ansible9 ~]
int main(int arg, char *argv[])
{
char s[]="abc\0def";
char d[128]="123\0999";
strncat(d,s,2);
printf("%s\n",d);
}
[root@ansible9 ~]
123ab
3.2.2 自己写一个strncat函数
[root@ansible9 ~]
char * my_strncat(char *dest, const char *src, int n)
{
char* tmp=dest;
while(*dest != '\0' && dest++);
int i=0;
while((*src != '\0') && (i)&&(++i) && (*dest=*src) && (src++) && (dest++));
*dest='\0';
return tmp;
}
int main(int arg, char *argv[])
{
char s[]="abc\0def";
char d[128]="123\0999";
my_strncat(d,s,2);
printf("%s\n",d);
}
[root@ansible9 ~]
123ab
四 字符串比较函数
4.1 strcmp
函数原型:int strcmp(const char *s1, const char *s2);
功能:将s1和s2指向的字符串,逐个字符比较
返回值:
>0:表示s1>s2
<0:表示s1
4.1.1 例子
[root@ansible9 ~]
int main(int arg, char *argv[])
{
char s1[]="abc";
char d1[]="abf";
printf("%d\n",strcmp(s1,d1));
char s2[]="ab\0c";
char d2[]="ab\0f";
printf("%d\n",strcmp(s2,d2));
char s3[]="aba";
char d3[]="ab\0f";
printf("%d\n",strcmp(s3,d3));
}
[root@ansible9 ~]
-3
0
99
4.1.2 自己写一个strcmp函数
[root@ansible9 ~]
int my_strcmp(char* s, char* d)
{
int n=0;
while(1)
{
if(*s == '\0' && *d == '\0')
break;
else if(*s == '\0' || *d == '\0')
{
n=*s - *d;
break;
}
else if (*s != *d)
n=*s - *d;
s++,d++;
}
return n;
}
int main(int arg, char *argv[])
{
char s1[]="abc";
char d1[]="abf";
printf("%d\n",my_strcmp(s1,d1));
printf("%d\n",strcmp(s1,d1));
printf("====================\n");
char s2[]="ab\0c";
char d2[]="ab\0f";
printf("%d\n",my_strcmp(s2,d2));
printf("%d\n",strcmp(s2,d2));
printf("====================\n");
char s3[]="aba";
char d3[]="ab\0f";
printf("%d\n",my_strcmp(s3,d3));
printf("%d\n",strcmp(s3,d3));
printf("====================\n");
char s4[]="ab\0f";
char d4[]="aba";
printf("%d\n",my_strcmp(s4,d4));
printf("%d\n",strcmp(s4,d4));
printf("====================\n");
char s5[]="\0ab\0f";
char d5[]="aba";
printf("%d\n",my_strcmp(s5,d5));
printf("%d\n",strcmp(s5,d5));
printf("====================\n");
}
[root@ansible9 ~]
-3
-3
====================
0
0
====================
97
97
====================
-97
-97
====================
-97
-97
====================
4.2 strncmp
函数原型:int strncmp(const char *s1, const char *s2, size_t n);
功能:将s1和s2指向的字符串的前n个字符,逐个字符比较
返回值:
>0:表示s1>s2
<0:表示s1
4.2.1 例子
[root@ansible9 ~]
int main(int arg, char *argv[])
{
char s1[]="abc";
char d1[]="abf";
printf("%d\n",strncmp(s1,d1,2));
char s2[]="ab\0c";
char d2[]="ab\0f";
printf("%d\n",strcmp(s2,d2));
char s3[]="aba";
char d3[]="ab\0f";
printf("%d\n",strncmp(s3,d3,2));
}
[root@ansible9 ~]
0
0
0
4.2.2 自己写一个strncmp函数
[root@ansible9 ~]
int my_strncmp(char* s, char* d, int i)
{
int n=0;
int x=0;
while(x)
{
if(*s == '\0' && *d == '\0')
break;
else if(*s == '\0' || *d == '\0')
{
n=*s - *d;
break;
}
else if (*s != *d)
n=*s - *d;
s++,d++,x++;
}
return n;
}
int main(int arg, char *argv[])
{
char s1[]="abc";
char d1[]="abf";
printf("%d\n",my_strncmp(s1,d1,2));
printf("%d\n",strncmp(s1,d1,2));
printf("====================\n");
char s2[]="ab\0c";
char d2[]="ab\0f";
printf("%d\n",my_strncmp(s2,d2,2));
printf("%d\n",strncmp(s2,d2,2));
printf("====================\n");
char s3[]="aba";
char d3[]="ab\0f";
printf("%d\n",my_strncmp(s3,d3,2));
printf("%d\n",strncmp(s3,d3,2));
printf("====================\n");
char s4[]="ab\0f";
char d4[]="aba";
printf("%d\n",my_strncmp(s4,d4,2));
printf("%d\n",strncmp(s4,d4,2));
printf("====================\n");
char s5[]="\0ab\0f";
char d5[]="aba";
printf("%d\n",my_strncmp(s5,d5,2));
printf("%d\n",strncmp(s5,d5,2));
printf("====================\n");
}
[root@ansible9 ~]
0
0
====================
0
0
====================
0
0
====================
0
0
====================
-97
-97
====================
[root@ansible9 ~]
五 字符串变换函数
5.1 strchr 字符匹配函数
函数原型: char* strchr(const char *str1, char ch)
功能:在字符串str1中查找字符ch出现的位置
返回值:返回第一次出现ch的地址;如果找不到返回NULL
5.1.1 例子:搜索字符b并替换成字符#
[root@ansible9 ~]
int main(int arg, char *argv[])
{
char str1[]="abcabc";
char ch='b';
char* p=NULL;
p=strchr(str1,ch);
*p='#';
printf("%s\n",str1);
printf("%s\n",p);
}
[root@ansible9 ~]
a
[root@ansible9 ~]
int main(int arg, char *argv[])
{
char str1[]="abcabc";
char ch='b';
char* p=NULL;
do
{
p=strchr(str1,ch);
}
while(p!=NULL && (*p='#'));
printf("%s\n",str1);
}
[root@ansible9 ~]
a
5.1.2 自己写一个strchr函数
[root@ansible9 ~]
char * my_strchr(char* str, char c)
{
char* p=NULL;
while(str)
{
if(*str == c)
{
p=str;
break;
}
str++;
}
return p;
}
int main(int arg, char *argv[])
{
char str1[]="abcabc";
char ch='b';
char* p=NULL;
p=my_strchr(str1,ch);
*p='#';
printf("%s\n",str1);
}
[root@ansible9 ~]
a
5.2 strstr 字符串匹配函数
函数原型:char *strstr(const char *str1, const char *str2);
功能:在字符串str1查找字符串str2出现的位置
返回值:返回第一次出现str2时的地址;如果没有找到返回NULL
5.2.1 例子:搜索字符串abc并替换成字符串###
[root@ansible9 ~]
int main(int arg, char *argv[])
{
char str1[]="1abc2abc\0abc";
char str2[]="abc";
char* p=NULL;
do
{
p=strstr(str1,str2);
}
while(p!=NULL && memset(p,'#',3));
printf("%s\n",str1);
}
[root@ansible9 ~]
1
5.2.2 自己写一个strstr函数
[root@ansible9 ~]
char *my_strstr(const char *str1, const char *str2)
{
//计算字符串str1的字符个数
int n_str1=0;
char* str1_tmp=(char*)str1;
while(*str1_tmp)
{
n_str1++;
str1_tmp++;
}
//计算字符串str2的字符个数
int n_str2=0;
char* str2_tmp=(char*)str2;
while((*str2_tmp++)&&(++n_str2));
//定义指针变量p_start指向字符串str1的第一个字符
char* p_start=(char*)str1;
//定义指针变量p_end指向字符串str1的最后一个字符
char* p_end=(char*)str1+n_str1-1;
//定义一个指针变量结束查找结果
char* find_position=NULL;
//定义一个指针变量作为游标
char* p_cursor=(char*)str1;
while((p_end-p_cursor)>=(n_str2-1))
{
int i=0;
int match_n=0;
for(i=0;i;i++)
{
if(*p_cursor==str2[i])
{
p_cursor++;
match_n++;
}
else
{
p_cursor++;
break;
}
}
if(match_n==n_str2)
{
find_position=p_cursor-n_str2;
break;
}
}
return find_position;
}
int main(int arg, char *argv[])
{
char s1[]="eeabcabcd";
char s2[]="abc";
char *p=my_strstr(s1,s2);
if (p==NULL)
printf("meiyou\n");
else
printf("%s\n",p);
char *p1=strstr(s1,s2);
if (p1==NULL)
printf("meiyou\n");
else
printf("%s\n",p1);
}
[root@ansible9 ~]
abcabcd
abcabcd
5.3 memset 内存空间设置函数
5.3.1 memset函数不是字符串操作函数是内存操作函数,不会与’\0’停止
函数原型:void* memset(void* str, char c, int n)
功能:将str指向的内存空间前n个字节,每个字节用字符c填充;常用于清除指定内存空间,比如数组或malloc的空间
返回值:返回str的地址
5.3.2 自己写一个memset函数
[root@ansible9 ~]
void *my_memset(void *s, int c, size_t n)
{
int i=0;
for(i=0;i;i++)
{
*((char*)s+i)=c;
}
return s;
}
int main(int arg, char *argv[])
{
char* p=(char*)malloc(4);
my_memset(p,'a',3);
printf("%s\n",p);
}
[root@ansible9 ~]
[root@ansible9 ~]
aaa
5.4 atoi atol atof 字符串转换函数
函数原型:int atoi(const char*str);
long atol(const char*str);
double atof(const char*str);
功能:将str所指向的数字字符串转换为int\long\double型数据
5.4.1 例子
[root@ansible9 ~]
int main(int arg, char *argv[])
{
printf("%d\n",atoi("123abc456"));
printf("%ld\n",atol("123abc456"));
printf("%f\n",atof("123.456abc666"));
}
[root@ansible9 ~]
[root@ansible9 ~]
123
123
123.456000
5.4.2 自己写一个atoi, atol, atof函数
[root@ansible9 ~]
int my_atoi(const char*str)
{
int sum=0;
while(*str>='0' && *str<='9')
{
sum*=10;
sum=sum+(*str-'0');
str++;
}
return sum;
}
long my_atol(const char*str)
{
long sum=0;
while(*str>='0' && *str<='9')
{
sum*=10;
sum=sum+(*str-'0');
str++;
}
return sum;
}
int main(int arg, char *argv[])
{
printf("%d\n",atoi("1234567891234abc456"));
printf("%d\n",my_atoi("1234567891234abc456"));
printf("%ld\n",atol("1234567891234abc456"));
printf("%ld\n",my_atol("1234567891234abc456"));
}
[root@ansible9 ~]
[root@ansible9 ~]
1912277282
1912277282
1234567891234
1234567891234
5.5 strtok 字符串分割函数
函数原型:char *strtok(char s[], const char* delim);
功能:将字符串分割成一个个小片段
参数s:指向要分割的字符串
参数delim:以什么字符来做分隔符,可以是多个字符
工作原理:当在s指向的字符串中发现参数delim中包含的分割符时,用'\0'替换该分隔符,当连续出现多个时只替换第一个。在第一次调用时,strtok必须给参数s,往后的调用则将参数s设置成NULL,每次调用成功则返回指向被分割出片段的指针。
5.5.1 例子
[root@ansible9 ~]
int main(int arg, char *argv[])
{
char buf[]="hehe:heihei::wo:ni:::";
//第一次分割
char* p1=strtok(buf,":");
printf("第一次分割得到的字符串:%s\n", p1);
//第二次分割
char* p2=strtok(NULL,":");
printf("第二次分割得到的字符串:%s\n", p2);
//第三次分割
char* p3=strtok(NULL,":");
printf("第三次分割得到的字符串:%s\n", p3);
//第4次分割
char* p4=strtok(NULL,":");
printf("第4次分割得到的字符串:%s\n", p4);
//第5次分割
char* p5=strtok(NULL,":");
printf("第5次分割得到的字符串:%s\n", p5);
//第6次分割
char* p6=strtok(NULL,":");
printf("第6次分割得到的字符串:%s\n", p6);
}
[root@ansible9 ~]
[root@ansible9 ~]
第一次分割得到的字符串:hehe
第二次分割得到的字符串:heihei
第三次分割得到的字符串:wo
第4次分割得到的字符串:ni
第5次分割得到的字符串:(null)
第6次分割得到的字符串:(null)
[root@ansible9 ~]
int main(int arg, char *argv[])
{
char buf[]="hehe:heihei::wo:ni:::";
char* arr[128]={NULL};
int i=0;
//第一次分割
arr[i]=strtok(buf,":");
//第2-n次分割
while(arr[i] != NULL)
{
i++;
arr[i]=strtok(NULL,":");
}
}
六 sprintf组包
[root@ansible9 ~]
int main(int arg, char *argv[])
{
char year[]="2022";
char month='3';
int day=22;
char buf[128]="0";
sprintf(buf,"%s年%c月%d日",year,month,day);
printf("%s\n",buf);
}
[root@ansible9 ~]
2022年3月22日
七 sscanf解包
%d: 只能提取'0'到'9'
%c:提取一个字符
%f:提取浮点数
%s:提取一个字符串,遇到空格,回车,'\0'停止捕获
[root@ansible9 ~]
int main(int arg, char *argv[])
{
char buf[]="我19你a他1.111她12ab啊啊 啊啊";
int d1=0;
char d2='\0';
float d3=0.0f;
char d4[128]="0";
sscanf(buf,"我%d你%c他%f她%s",&d1,&d2,&d3,d4);
printf("d1=%d\n",d1);
printf("d2=%c\n",d2);
printf("d3=%f\n",d3);
printf("d4=%s\n",d4);
}
[root@ansible9 ~]
d1=19
d2=a
d3=1.111000
d4=12ab啊啊
八 sscanf高级用法
8.1 高级用法一:使用%*s %*d跳过提取的内容(不要提取到的内容)
[root@ansible9 ~]
int main(int arg, char *argv[])
{
int data=0;
sscanf("1234 5678","%*d %d",&data);
printf("%d\n",data);
}
[root@ansible9 ~]
[root@ansible9 ~]
5678
8.2 高级用法二:使用%ns %nd提取提取指定宽度n字符串或数值
[root@ansible9 ~]
int main(int arg, char *argv[])
{
int data=0;
sscanf("12abc5678","%*5s%d",&data);
printf("%d\n",data);
}
[root@ansible9 ~]
5678
8.3 高级用法三:支持集合操作
%[a-z]:表示匹配a到z中任意字符(尽可能多匹配)
%[aBc]: 匹配aBc,贪婪匹配
%[^a-z]: 表示匹配除a到z外的任意字符(尽可能多匹配)
%[]都是字符串匹配提取