c语言十八:字符串处理

字符串处理

  • 一 测试字符串长度函数
    • 1.1 strlen
  • 二 字符串拷贝函数
    • 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 字符串分割函数
      • 5.5.1 例子
  • 六 sprintf组包
  • 七 sscanf解包
  • 八 sscanf高级用法
    • 8.1 高级用法一:使用%*s %*d跳过提取的内容(不要提取到的内容)
    • 8.2 高级用法二:使用%ns %nd提取提取指定宽度n字符串或数值
    • 8.3 高级用法三:支持集合操作

  1. 以str开头的函数都是遇到’\0’结束;
  2. 以str开头的函数都用头文件string.h;

一 测试字符串长度函数

1.1 strlen

函数原型:int strlen(const char *str)
功能:计算字符串的长度,不含'\0'
参数:存放字符串的内存空间的首地址
[root@ansible9 ~]# cat test.c
#include 
#include 
#include 
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 ~]# ./a.out 
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 ~]# cat test.c
#include 
#include 
#include 
int main(int arg, char *argv[])
{
	char s[]="abc\0def";
	char d[128]="\0";
	strcpy(d,s);
	printf("%s\n",d);
}
[root@ansible9 ~]# ./a.out 
abc

2.1.2 自己写一个strcpy函数

[root@ansible9 ~]# cat test.c
#include 
#include 
#include 
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 ~]# ./a.out 
abc

2.2 strncpy

函数原型:char *strncpy(char *dest, const char *src, int num)
功能:将src所指向的字符串的前num个字符复制到dest所指向的内存空间
返回值:返回dest字符串的首地址
注意:'\0'不拷贝

2.2.1 例子

[root@ansible9 ~]# cat test.c
#include 
#include 
#include 
int main(int arg, char *argv[])
{
	char s[]="abc\0def";
	char d[128]="\0";
	strncpy(d,s,2);
	printf("%s\n",d);
}
[root@ansible9 ~]# ./a.out 
ab

2.2.2 自己写一个strncpy函数

[root@ansible9 ~]# cat my_test.c 
#include 
#include 
#include 
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 ~]# ./a.out 
ab

三 字符串拼接函数

3.1 strcat

函数原型:char *strcat(char *dest, const char *src)
功能:将src的字符串拼接到dest末尾
返回值:dest的首地址

3.1.1 例子

[root@ansible9 ~]# cat test.c
#include 
#include 
#include 
int main(int arg, char *argv[])
{
	char s[]="abc\0def";
	char d[128]="123\0999";
	strcat(d,s);
	printf("%s\n",d);
}
[root@ansible9 ~]# ./a.out 
123abc

3.1.2 自己写一个strcat函数

[root@ansible9 ~]# cat my_test.c 
#include 
#include 
#include 
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 ~]# ./a.out 
123abc

3.2 strncat

函数原型:char *strncat(char *dest, const char *src, size_t n);
功能:将src字符串的前n个字符拼接到dest末尾
返回值:dest的首地址

3.2.1 例子

[root@ansible9 ~]# cat test.c 
#include 
#include 
#include 
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 ~]# ./a.out 
123ab

3.2.2 自己写一个strncat函数

[root@ansible9 ~]# cat my_test.c 
#include 
#include 
#include 
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 ~]# ./a.out 
123ab

四 字符串比较函数

4.1 strcmp

函数原型:int strcmp(const char *s1, const char *s2);
功能:将s1和s2指向的字符串,逐个字符比较
返回值:
	>0:表示s1>s2
	<0:表示s1

4.1.1 例子

[root@ansible9 ~]# cat test.c 
#include 
#include 
#include 
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 ~]# ./a.out 
-3
0
99

4.1.2 自己写一个strcmp函数

[root@ansible9 ~]# cat my_test.c 
#include 
#include 
#include 
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 ~]# ./a.out 
-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 ~]# cat test.c 
#include 
#include 
#include 
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 ~]# ./a.out 
0
0
0

4.2.2 自己写一个strncmp函数

[root@ansible9 ~]# cat my_test.c 
#include 
#include 
#include 
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 ~]# ./a.out 
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 ~]# cat test.c
#include 
#include 
#include 
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.out 
a#cabc
#cabc

[root@ansible9 ~]# cat test.c
#include 
#include 
#include 
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.out 
a#ca#c

5.1.2 自己写一个strchr函数

[root@ansible9 ~]# cat test.c
#include 
#include 
#include 
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.out 
a#cabc

5.2 strstr 字符串匹配函数

函数原型:char *strstr(const char *str1, const char *str2);
功能:在字符串str1查找字符串str2出现的位置
返回值:返回第一次出现str2时的地址;如果没有找到返回NULL

5.2.1 例子:搜索字符串abc并替换成字符串###

[root@ansible9 ~]# cat test.c
#include 
#include 
#include 
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 ~]# ./a.out 
1###2###

5.2.2 自己写一个strstr函数

[root@ansible9 ~]# cat test.c
#include 
#include 
#include 
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 ~]# ./a.out
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 ~]# cat test.c
#include 
#include 
#include 
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 ~]# gcc -Wall test.c
[root@ansible9 ~]# ./a.out
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 ~]# cat test.c
#include 
#include 
#include 
int main(int arg, char *argv[])
{
	printf("%d\n",atoi("123abc456"));
	printf("%ld\n",atol("123abc456"));
	printf("%f\n",atof("123.456abc666"));
}
[root@ansible9 ~]# gcc test.c
[root@ansible9 ~]# ./a.out 
123
123
123.456000

5.4.2 自己写一个atoi, atol, atof函数

[root@ansible9 ~]# cat test.c
#include 
#include 
#include 
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 ~]# gcc test.c
[root@ansible9 ~]# ./a.out 
1912277282
1912277282
1234567891234
1234567891234

5.5 strtok 字符串分割函数

函数原型:char *strtok(char s[], const char* delim);
功能:将字符串分割成一个个小片段
参数s:指向要分割的字符串
参数delim:以什么字符来做分隔符,可以是多个字符
工作原理:当在s指向的字符串中发现参数delim中包含的分割符时,用'\0'替换该分隔符,当连续出现多个时只替换第一个。在第一次调用时,strtok必须给参数s,往后的调用则将参数s设置成NULL,每次调用成功则返回指向被分割出片段的指针。

c语言十八:字符串处理_第1张图片

5.5.1 例子

[root@ansible9 ~]# cat test.c
#include 
#include 
#include 
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 ~]# gcc test.c
[root@ansible9 ~]# ./a.out 
第一次分割得到的字符串:hehe
第二次分割得到的字符串:heihei
第三次分割得到的字符串:wo
第4次分割得到的字符串:ni
第5次分割得到的字符串:(null)
第6次分割得到的字符串:(null)

c语言十八:字符串处理_第2张图片

[root@ansible9 ~]# cat test.c
#include 
#include 
#include 
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组包

c语言十八:字符串处理_第3张图片
c语言十八:字符串处理_第4张图片

[root@ansible9 ~]# cat test.c
#include 
#include 
#include 
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 ~]# ./a.out 
2022年3月22日

七 sscanf解包

c语言十八:字符串处理_第5张图片

%d: 只能提取'0''9'
%c:提取一个字符
%f:提取浮点数
%s:提取一个字符串,遇到空格,回车,'\0'停止捕获

[root@ansible9 ~]# cat test.c
#include 
#include 
#include 
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 ~]# ./a.out 
d1=19
d2=a
d3=1.111000
d4=12ab啊啊

八 sscanf高级用法

8.1 高级用法一:使用%*s %*d跳过提取的内容(不要提取到的内容)

[root@ansible9 ~]# cat test.c
#include 
#include 
#include 
int main(int arg, char *argv[])
{
	int data=0;
	sscanf("1234 5678","%*d %d",&data);
	printf("%d\n",data);
}
[root@ansible9 ~]# gcc test.c
[root@ansible9 ~]# ./a.out 
5678

8.2 高级用法二:使用%ns %nd提取提取指定宽度n字符串或数值

[root@ansible9 ~]# cat test.c
#include 
#include 
#include 
int main(int arg, char *argv[])
{
	int data=0;
	sscanf("12abc5678","%*5s%d",&data);
	printf("%d\n",data);
}
[root@ansible9 ~]# ./a.out 
5678

8.3 高级用法三:支持集合操作

%[a-z]:表示匹配a到z中任意字符(尽可能多匹配)
%[aBc]: 匹配aBc,贪婪匹配
%[^a-z]: 表示匹配除a到z外的任意字符(尽可能多匹配)
%[]都是字符串匹配提取

c语言十八:字符串处理_第6张图片
c语言十八:字符串处理_第7张图片
c语言十八:字符串处理_第8张图片

你可能感兴趣的:(c语言,c语言)