#10库函数#

1.strlen

size_t strlen ( const char * str );

参数:

str -- 要计算长度的字符串。

返回值: 

该函数返回字符串的长度。

注意函数的返回值为size_t,是无符号的( 易错 )

可以写成int 各有利弊

写成size_t时 不会出现负数情况

写成int 当相减时 可以为负数

但size_t就一直为正数 会出现一些错误

if((strlen("abc")-strlen("abcdef"))>0)//小心返回类型 
{
    printf("hehe\n");
}
else//写int不会出现这种错误 size_t可以保证结果不为负数 各有利弊 
{
    printf("haha\n");
}

strlen库函数的使用

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[]="abcdef";
	int len=strlen(arr);
	printf("len=%d\n",len);
	return 0;
}

6

strlen自定义函数的实现

#include<stdio.h>
#include<assert.h>
#include<string.h>
int my_strlen(const char* str)//库里面返回类型是size_t 其实也就是unsigned int无符号整型 
{
	int count=0;
	assert(str!=NULL);
	while(*str!='\0')
	{
		count++;
		str++;
	}
	return count;
}
int main()
{
	int len=my_strlen("abcdef");
	printf("%d\n",len);
    return 0;
}

6

2.strcpy

char* strcpy(char * destination, const char * source );

参数:

dest -- 指向用于存储复制内容的目标数组。

src -- 要复制的字符串。

返回值:

该函数返回一个指向最终的目标字符串 dest 的指针。

源字符串必须以 '\0' 结束。

会将源字符串中的 '\0' 拷贝到目标空间。

目标空间必须足够大,以确保能存放源字符串。

目标空间必须可变。

strcpy库函数

#include<stdio.h>
#include<assert.h>
#include<string.h>
int main()
{
	char arr1[]="abcdef";
	char arr2[]="bit";
	strcpy(arr1,arr2);
	printf("%s\n",arr1);
	return 0;
}

bit

strcpy自定义函数

#include<stdio.h>
#include<assert.h>
#include<string.h>
char* my_strcpy(char* dest,const char* src)
{
	assert(dest!=NULL);
	assert(src!=NULL);
	char* ret=dest;
	//拷贝src指向的字符串到dest指向的空间 包含'\0' 
	//while(*src!='\0')
	//{
	//	*dest=*src;//b放到a上
	//	dest++;
	//	src++; 
	//}
	//*dest=*src//'\0'
	//简化 
	while(*dest++=*src++)
	{
		;
	}
	//赋值的同时往后走 当\0赋值的时候  \0的ascii码值为0 表达式为假 跳出循环  
	return ret; 
	//返回目的空间的起始地址 
}
int main()
{
	char arr1[]="abcdef";//arr1元素个数大于arr2 
	//char arr1[]="abcdefghi"//这是常量字符串 改变不了 错误 
	char arr2[]="bit";
	//char arr2[]={'b','i','t'}错误 无\0 
	my_strcpy(arr1,arr2);
	//第一个参数目的地地址 第二个参数是源头
	//为了copy后只打印bit 要把\0放到d的位置
	printf("%s\n",arr1);
	return 0;
} 

bit

3.strcat

char * strcat ( char * destination, const char * source );

参数:

dest -- 指向目标数组,该数组包含了一个 C 字符串,且足够容纳追加后的字符串。

src -- 指向要追加的字符串,该字符串不会覆盖目标字符串。

返回值:

该函数返回一个指向最终的目标字符串 dest 的指针。

源字符串必须以 '\0' 结束。

目标空间必须有足够的大,能容纳下源字符串的内容。

目标空间必须可修改。

strcat库函数

#include<stdio.h>
#include<assert.h>
#include<string.h>
int main()
{
	//char arr1[30]="hello\0xxxxxxx";//有x变为\0 说明是追加过去的\0 
	char arr1[30]="hello";
	char arr2[]="world";//arr2里面也要有\0 因为arr2的\0可以追加过去 
	strcat(arr1,arr2);//不具体规定元素个数的追加 空间过小不行 arr1元素个数变成30 
	printf("%s\n",arr1);
	return 0;
}

helloworld

strcat自定义函数

char* my_strcat(char* dest,const char* src)
{
	char* ret=dest;
	assert(dest!=NULL);
	assert(src);
	//1.找到目的字符串的'\0'
	while(*dest!='\0')
	{
		dest++;
	}
	//2.追加
	while(*dest++=*src++)
	{
		;
	}
	return ret; 
}
int main()
{
	char arr1[30]="hello";
	char arr2[]="world";
	my_strcat(arr1,arr2);
	printf("%s\n",arr1);
	return 0;
}

helloworld

4.strcmp

int strcmp ( const char * str1, const char * str2 );

参数:

str1 -- 要进行比较的第一个字符串。

str2 -- 要进行比较的第二个字符串。

返回值:

如果返回值小于 0,则表示 str1 小于 str2。

如果返回值大于 0,则表示 str1 大于 str2。

如果返回值等于 0,则表示 str1 等于 str2。

strcmp库函数

#include<stdio.h>
#include<assert.h>
#include<string.h>
int main()
{
	char* p1="abcdef";
	char* p2="sqwer";
	int ret=strcmp(p1,p2);
	//比较的是字符的ASCII码值 相同接着往下比较 
	printf("%d\n",ret);//编译器不同 得到的结果不同 因此写判断条件的时候写>0 <0 =0
	if(ret>0)
	{
		printf("p1>p2\n");
	}
	else if(ret<0)
	{
		printf("p1<p2\n");
	}
	else
	{
		printf("p1=p2\n");
	}
} 

p1<p2

strcmp自定义函数

#include<stdio.h>
#include<assert.h>
#include<string.h>
int my_strcmp(const char* str1,const char* str2)//比较 不希望改变
{
	assert(str1&&str2);
	//比较
	while(*str1&&(*str1==*str2))//相等且str1不为\0继续比较 如果没有*str1两边都为\0时无法跳出循环 
	{
		str1++;
		str2++;
	}
	//if(*str1>*str2)
	//	return 1;
	//else
	//	return -1;
	return (*str1-*str2);
}
int main()
{
	char* p1="abcdef";
	char* p2="abqwe";
	int ret=my_strcmp(p1,p2);
	printf("ret=%d\n",ret);
	if(ret>0)
	{
		printf("p1>p2\n");
	}
	else if(ret<0)
	{
		printf("p1<p2\n");
	}
	else
	{
		printf("p1=p2\n");
	} 
	return 0;
} 

p1<p2

5.strncpy

char * strncpy ( char * destination, const char * source, size_t num );

参数:

dest -- 指向用于存储复制内容的目标数组。

src -- 要复制的字符串。

n -- 要从源中复制的字符数。

返回值:

该函数返回最终复制的字符串。

拷贝num个字符从源字符串到目标空间。

如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。

strncpy库函数

#include<stdio.h>
#include<assert.h>
#include<string.h>
int main()
{
	char arr1[10]="abcdef";
	char arr2[]="hello bit";
	strncpy(arr1,arr2,4);//增加个数 相对安全 只copy4个 
	//char arr1[10]="abcdef";
	//char arr2[]="bit";
	//strncpy(arr1,arr2,6);//长度过长 不够 剩下用\0填充
	printf("%s\n",arr1);
	return 0;
} 

字节数够打印hellef

字节数不够会补充\0 打印bit

strncpy自定义函数

#include<stdio.h>
#include<assert.h>
#include<string.h>
char *my_strncpy(char *dest, const char *src, size_t count)//copy字节数
{
    char *ret = dest;//起始地址不变 给一个中间指针变量
    while (count--) 
	{
        if ((*dest= *src) != 0)//赋值的同时保证不是\0 
            src++;//向后挪动一个字符
        dest++;//也向后挪动一个字符
    }
    return ret;//返回起始地址
}
int main()
{
	char arr1[10]="abcdef";
	char arr2[]="bit";
	my_strncpy(arr1,arr2,2);
    //my_strcnpy(arr1,arr2,4);
	printf("%s\n",arr1);
	return 0;
} 

字节数够的时候(2) bicef

字节数不够的时候(4) bit 后面会补\0 

6.strncat

char * strncat ( char * destination, const char * source, size_t num );

参数:

dest -- 指向目标数组,该数组包含了一个 C 字符串,且足够容纳追加后的字符串,包括额外的空字符。

src -- 要追加的字符串。

n -- 要追加的最大字符数。

返回值:

该函数返回一个指向最终的目标字符串 dest 的指针。

strncat库函数

#include<Stdio.h>
#include<string.h>
#include<assert.h>
int main()
{
	char arr1[30]="hello\0xxxxxxxx";//追加完之后会主动放\0 
	char arr2[]="world";
	strncat(arr1,arr2,3);//追加个数过多 加完后再补一个\0就不管了  
	printf("%s\n",arr1);
	return 0;
}

hellowor

strncat自定义函数

#include<stdio.h>
#include<assert.h>
#include<string.h>
char* my_strncat(char * dest, const char *src, size_t n)
{
    assert(dest);
    assert(src);
    char *ret=dest;//保留起始地址
	//找到\0 
    while(*dest)
    {
        dest++;
    }
    //开始追加 
    while(n--)
    {
        *dest++=*src++;
    }
    //追加完后补上\0 
    *dest = '\0';
    return ret;
}
int main()
{
	char arr1[30]="hello";//追加完之后会主动放\0 
	char arr2[]="world";
	my_strncat(arr1,arr2,3);//追加个数过多 加完后再补一个\0就不管了 
	printf("%s\n",arr1);
	return 0;
}

hellowor

7.strncmp

int strncmp ( const char * str1, const char * str2, size_t num );

参数:

str1 -- 要进行比较的第一个字符串。

str2 -- 要进行比较的第二个字符串。

n -- 要比较的最大字符数。

返回值:

如果返回值 < 0,则表示 str1 小于 str2。

如果返回值 > 0,则表示 str1 大于 str2。

如果返回值 = 0,则表示 str1 等于 str2。

strncmp库函数

#include<stdio.h>
#include<assert.h>
#include<string.h>
int main()
{
	const char* p1="abcdef";
	const char* p2="abcqwer";
	int ret=strncmp(p1,p2,3);//比较字节数 比较前3个 返回0 比较前4个 返回负数 
	printf("%d\n",ret);
	if(ret>0)
	{
		printf("p1>p2\n");
	}
	else if(ret<0)
	{
		printf("p1<p2\n");
	}
	else
	{
		printf("p1=p2\n");
	} 	
	return 0;
}

p1=p2

strncmp自定义函数

#include<stdio.h>
#include<assert.h>
#include<string.h>
int my_strncmp(const char* str1,const char* str2,size_t num)
{
    assert(str1&&str2);
	//--num比较字节数减少 减到0后跳出循环 比较完
	//*str1==*str2 如果不等 就直接跳出循环 比较对应字符的ASCII 也包括str2先到\0 这种情况 
	while(--num&&*str1&&(*str1==*str2))//*str1不为\0 如果继续自加比较 如果不加这个条件 当两边同时是\0时不能跳出循环 
	{ 
		str1++;
		str2++;
	}
	//返回  看差值 
    return (*str1-*str2);
}
int main()
{
	const char* p1="abcdef";
	const char* p2="abcqwer";
	int ret=strncmp(p1,p2,3);//比较前3个 返回0 比较前4个 返回负数 
	printf("%d\n",ret);
	if(ret>0)
	{
		printf("p1>p2\n");
	}
	else if(ret<0)
	{
		printf("p1<p2\n");
	}
	else
	{
		printf("p1=p2\n");
	} 	
	return 0;
}

p1=p2

8.strstr

char * strstr ( const char *str1, const char * str2);

参数:

str1 -- 要被检索的 C 字符串。

str2 -- 在 str1 字符串内要搜索的小字符串。(子字符串)

返回值:

该函数返回在str1 中第一次出现 str2字符串的位置,如果未找到则返回 null。

strstr库函数

#include<stdio.h>
#include<assert.h>
#include<string.h>
int main()
{
	char *p1="abcdefghi";
	char *p2="def";
	char *ret=strstr(p1,p2);
	//出现两次的话会返回第一次出现的首字符地址 
	//返回的是子串首字符地址 
	if(ret==NULL)
	{
		printf("子串不存在");
	}
	else
	{
		printf("%s\n",ret);//打印defghi 
	}
	return 0;
}

defghi


strstr自定义函数

#include<stdio.h>
#include<assert.h>
#include<string.h>
char* my_strstr(const char* p1,const char* p2)
{
	assert(p1!=NULL);
	assert(p2!=NULL);
	char *s1=p1;
	char *s2=p2;
	char *cur=p1;//如果用p1和p2走的话 不能记住原始地址 返回地址 而且会遇到特殊情况 
	if(*p2=='\0')//特殊情况:abbbcdef bbc 这样的话 无法找出来 所以创建第三第四个指针 进行遍历 
	{
		return (char*)p1;
	}
	while(*cur)
	{
		s1=cur;//s1需要回来 再次进行遍历 
		s2=(char*)p2;
		while(*s1&&*s2&&(*s1==*s2))//*s1 *s2!='\0'
		{
			s1++;
			s2++;
		}
		if(*s2=='\0')
		{
			return cur;//找到子串 
		}
		if(*s1=='\0')
		{
			return NULL;//当s1字符数量<s2字符数量 提前终止 
		}
		cur++;
	}
	return NULL;//找不到子串 
}
int main()
{
	char *p1="abbbcdef";
	char *p2="bbc";
	char *ret=my_strstr(p1,p2);
	if(ret==NULL)
	{
		printf("子串不存在");
	}
	else
	{
		printf("%s\n",ret);//打印bbcdef 
	}
	return 0;
} 

bbcdef

9.strtok

char * strtok ( char * str, const char * sep );

参数:

str -- 要被分解成一组小字符串的字符串。

sep -- 包含分隔符的 C 字符串。

返回值:

该函数返回被分解的第一个子字符串,如果没有可检索的字符串,则返回一个空指针。

sep参数是个字符串,定义了用作分隔符的字符集合

第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标 记。

strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注: strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容 并且可修改。)

strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串 中的位置。

strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标 记。

如果字符串中不存在更多的标记,则返回 NULL 指针。

strtok库函数

int main()
{
	//192.168.31.121
	//192.168.31.121-strtok
	//zpw@bitedu.tech
	//zpw bitedu tech
	char arr[]="zpw@bitedu.tech";
	char*p="@.";
	//会把@和.改成\0 然后从起始字符开始打印
	char buf[1024]={0};
	strcpy(buf,arr);
	char* ret=NULL;
	for(ret=strtok(arr,p);ret!=NULL;ret=strtok(NULL,p))//以后总传空指针 
	{
		printf("%s\n",ret);
	}
	//会记住上次改成\0的位置 下次从后面开始 类似于static 
	//切割buf中的字符串 切割不了会返回空指针 
	return 0;
}

zpw

bitedu

tech

10.strerror

char * strerror ( int errnum );

参数:

errnum -- 错误号,通常是 errno

返回值:

该函数返回一个指向错误字符串的指针,该错误字符串描述了错误 errnum。

#include <errno.h>//必须包含的头文件\

sterror库函数

#include<stdio.h>
#include<assert.h>
#include<string.h>
#include<errno.h> 
int main()
{
	//错误码-错误信息 
	//0     -No error
	//1     -Operation not permitted
	//2     -No such file or directory
	//3 4 5等也有
	//errno是一个全局的错误码的变量
	//当C语言的库函数在执行过程中 发生了错误 就会把对应的错误码 赋值到errno中 
	//char*str=strerror(errno);//把错误码翻译成错误信息 
	//printf("%s\n",str); 
	//打开文件
	FILE* pf=fopen("test.txt","r");
	if(pf==NULL)
	{
		printf("%s\n",strerror(errno));
	}
	else
	{
		printf("open file success\n");
	}
	return 0;
}

No such file or directory

11.字符分类函数

 #include<ctype.h>头文件

#include<stdio.h>
#include<ctype.h>
int main()
{
	//char ch='w';
	//int ret=islower(ch);//判断是不是小写 小写就返回非0 大写就返回0 
	//printf("%d\n",ret);
	//char ch=tolower('Q');//大写变小写 如果小写的话就不变 
	//char ch=toupper('q');//小写变大写 
	//putchar(ch);
	//大写全部变小写 
	char arr[]="I Am A Student";
	int i=0;
	while(arr[i])
	{
		if(isupper(arr[i]))
		{
			arr[i]=tolower(arr[i]);
		}
		i++;
	}
	printf("%s\n",arr);
	return 0;
}

i am a student

12.memcpy

void * memcpy ( void * destination, const void * source, size_t num );

参数:

str1 -- 指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。

str2 -- 指向要复制的数据源,类型强制转换为 void* 指针。

num -- 要被复制的字节数。

返回值:

该函数返回一个指向目标存储区 str1 的指针。

函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。

这个函数在遇到 '\0' 的时候并不会停下来。

如果source和destination有任何的重叠,复制的结果都是未定义的。(某些编译器下可以解决重叠问题)

memcpy库函数

#include<stdio.h>
#include<assert.h>
#include<string.h>
struct S
{
	char namr[20];
	int age; 
};
int main()
{
	int arr1[]={1,2,3,4,5};
	int arr2[5]={0};
	struct S arr3[]={{"张三",20},{"李四",30}};
	struct S arr4[3]={0};
	memcpy(arr2,arr1,sizeof(arr1));//整型数组的copy
	memcpy(arr4,arr3,sizeof(arr3));//结构体的copy
	int i=0;
	for(i=0;i<5;i++)
	printf("%d ",arr2[i]);
	for(i=0;i<3;i++)
	printf("\n%s",arr4[i]);
}

1 2 3 4 5

张三

李四

memcpy自定义函数

#include<stdio.h>
#include<assert.h>
#include<string.h>
struct S
{
	char namr[20];
	int age; 
};

void* my_memcpy(void* dest,const void* src,size_t num)
{
	void* ret=dest;
	assert(dest!=NULL);
	assert(src!=NULL);
	while(num--)
	{
		*(char*)dest=*(char*)src;
		(char*)dest++;//强转之后再加加 前置加加会报错 可能是编译器原因 
		(char*)src++;//++优先级低于*  
	}
	return ret;//返回起始地址 
}
 
int main()
{
	int arr1[]={1,2,3,4,5};
	int arr2[5]={0};
	struct S arr3[]={{"张三",20},{"李四",30}};
	struct S arr4[3]={0};
	my_memcpy(arr4,arr3,sizeof(arr3));
	my_memcpy(arr2,arr1,sizeof(arr1));
	int i=0;
	for(i=0;i<5;i++)
	printf("%d ",arr2[i]);
	for(i=0;i<3;i++)
	printf("\n%s",arr4[i]);
	return 0;
}

1 2 3 4 5

张三

李四

C语言标准要求:
memcpy 只要处理不重叠的内容copy就可以(库里的memcpy可解决重叠问题 自定义没有实现)
memmove 处理重叠内存的copy 遇到重叠情况可用memmove

13.memmove

void * memmove ( void * destination, const void * source, size_t num );

参数:

str1 -- 指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。

str2 -- 指向要复制的数据源,类型强制转换为 void* 指针。

num -- 要被复制的字节数。

返回值:

该函数返回一个指向目标存储区 str1 的指针。

和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。

如果源空间和目标空间出现重叠,就得使用memmove函数处理。

memmove库函数

#include<stdio.h>
#include<assert.h>
#include<string.h>
int main()
{
	//1 2 3 4 5拷贝到3 4 5 6 7 
	int arr[]={1,2,3,4,5,6,7,8,9,10}; 
	//my_memcpy(arr+2,arr,20);//源头和目的地在同一空间 会重叠 copy不成功 
	//memcpy(arr+2,arr,20);//库里面可以实现 库里面memcpy和memmove是一样的效果 
	memmove(arr+2,arr,20);//处理重叠状态 
	int i=0;
	for(i=0;i<10;i++)
	{
		printf("%d ",arr[i]);
	}
	return 0;
} 

1 2 1 2 3 4 5 8 9 10

memmove自定义函数

#include<stdio.h>
#include<assert.h>
#include<string.h>
void* my_memmove(void* dest,void* src,size_t count)
{
	void* ret=dest;
	assert(dest!=NULL);
	assert(src!=NULL);
	if(dest<src)
	{
		//前->后
		while(count--)
		{
			*(char*)dest=*(char*)src;
			(char*)dest++;
			(char*)src++;	
		}	
	}
	else
	{
		//后->前
		while(count--)
		{
			*((char*)dest+count)=*((char*)src+count);
		}
		return ret; 
	}
	//或者
	/*if(dest<src||dest>(char*)src+count)
	{
		//前-后 
	}
	else
	{
		//后-前 
	} */
}
//头文件string.h 
int main()
{
	//1 2 3 4 5拷贝到3 4 5 6 7 
	int arr[]={1,2,3,4,5,6,7,8,9,10}; 
	//my_memcpy(arr+2,arr,20);//源头和目的地在同一空间 会重叠 copy不成功 
	//memcpy(arr+2,arr,20);//库里面可以实现 库里面memcpy和memmove是一样的效果 
	//memmove(arr+2,arr,20);//处理重叠状态 
	my_memmove(arr+2,arr,20);
	int i=0;
	for(i=0;i<10;i++)
	{
		printf("%d ",arr[i]);
	}
	return 0;
} 

1 2 1 2 3 4 5 8 9 10

14.memcmp

int memcmp ( const void * ptr1, const void * ptr2, size_t num );

参数:

str1 -- 指向内存块的指针。

str2 -- 指向内存块的指针。

num-- 要被比较的字节数。

返回值:

如果返回值 < 0,则表示 str1 小于 str2。

如果返回值 > 0,则表示 str1 大于 str2。

如果返回值 = 0,则表示 str1 等于 str2。

memcmp库函数

#include<stdio.h>
#include<string.h>
int main()
{
	int arr1[]={1,2,3,4,5};
	int arr2[]={1,2,5,4,3};
	int ret=memcmp(arr1,arr2,9);
	printf("%d\n",ret);
	if(ret>0)
	{
		printf("arr1>arr2\n");
	}
	else if(ret<0)
	{
		printf("arr1<arr2\n");
	}
	else
	{
		printf("arr1=arr2\n");
	} 
	return 0;
}

arr1<arr2

15.memset

void* memset(void *str,int c,size_t n)

参数:

str -- 指向要填充的内存块。

c -- 要被设置的值。该值以 int 形式传递,但是函数在填充内存块时是使用该值的无符号字符形式。

n -- 要被设置为该值的字符数。

返回值:

该值返回一个指向存储区 str 的指针。

memset库函数

int main()
{
    char str[50];
    strcpy(str,"This is string.h library function");
    puts(str);
    memset(str,'$',7);
    puts(str)
    //int arr[10]={0};
	//最后一个参数是10个字节的意思
	//改成01 01 01 01 01 01 01 01 01 01 00 00 00 00
	//相当于结果是01 01 01 01十六进制变为十进制
	//错误写法 
	return 0;
}

This is string.h library function

$$$$$$$ string.h library function

#10库函数#完

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力的小恒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值