• C语言字符串函数的详解


    一.字符串具体有哪些

    求字符串的长度
    strlen
    长度不受限制的字符串函数
    strcpy
    strcat
    strcmp
    长度受限制的字符串函数介绍
    strncpy
    strncat
    strncmp
    字符串查找
    strstr
    strtok
    错误信息报告
    strerror

    字符操作

    内存操作函数
    memcpy
    memmove
    memset
    memcmp

    二.具体的函数的介绍

    1.strlen

    size_t strlen ( const char * str );
    /*
    具体语法
    字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包
    含 '\0' )。
    size_t strlen ( const char * str );
    参数指向的字符串必须要以 '\0' 结束。
    注意函数的返回值为size_t,是无符号的( 易错 )
    */
    
    具体的使用
    int main() {
    
    	char arr[] = "abc\0";
    	printf("%d\n", strlen(arr));
    	char brr[] = { 'a','b','c','\0'};
    	printf("%d\n",strlen(brr));
    	return 0;
    
    模拟实现strlen
    size_t my_strlen(const char* str)
    {
    	assert(str);
    	const char* start = str;
    	const char* end = str;
    	while (*end != '\0')
    	{
    		end++;
    	}
    	return end - start;
    }
    
    int main()
    {
    	char arr[] = "abcdef";
    	int len = my_strlen(arr);
    	printf("%d\n", len);
    	return 0;
    }
    

    2.长度受限制的字符串函数介绍

    拷贝字符串
    strcpy
    剪切字符串
    strcat
    比较字符串
    strcmp
    下面让我一个一个去看这些方法的用法

    • strcpy
    char* strcpy(char * destination, const char * source );
    /*
    Copies the C string pointed by source into the array pointed by destination, including the
    terminating null character (and stopping at that point).
    源字符串必须以 '\0' 结束。
    会将源字符串中的 '\0' 拷贝到目标空间。
    目标空间必须足够大,以确保能存放源字符串。
    目标空间必须可变。
    
    */
    
    

    具体用法

    int main()
    {
    	char arr[10] = "xxxxxxxxx";
    	const char* p = "abcdef";
    	char arr2[] = { 'b', 'i', 't','\0'};
    
    	strcpy(arr, p);
    	strcpy(arr, arr2);
    
    	printf("%s\n", arr);
    
    	return 0;
    }
    '
    运行

    这里我们监视变量就可以看出它是如何复制字符串的
    在这里插入图片描述

    模拟实现strcpy
    这里模拟实现拷贝字符串的方法,是用指针相对调用而形成的

    char* my_strcopy(char* dest,const char*src) {
    	assert(dest);
    	assert(src);
    	char* ret = dest;
    	while (*dest++ = *src++)
    	{
    		
    		;
    	}
    
    
    	return dest;
    }
    int main() {
    	char arr1[20] = "abc";
    	char arr2[] = "helloworld";
    	my_strcopy(arr1, arr2);
    	printf("%s\n", arr1);
    	return 0;
    }
    

    strcat函数的具体说明
    这个函数以"\0"为标识的 进行追加的。

    char * strcat ( char * destination, const char * source );
    源字符串必须以 '\0' 结束。
    目标空间必须有足够的大,能容纳下源字符串的内容。
    目标空间必须可修改。
    

    具体的用法

    追加字符串
    int main() {
    	char arr1[20] = "hello";
    	char arr2[20] = "world";
    	strcat(arr1,arr2);
    	printf("%s\n",arr1);
    	return 0;
    

    我们看图说话,目前看来可以说是以“\0”为追加的。
    在这里插入图片描述

    strcat的模拟实现

    char* my_strcat(char*dest ,const char*src) {
    	//1.找目标函数的\0
    	char* cur = dest;
    	while (*cur!='\0') {
    		cur++;
    	
    	}
    	//2..拷贝源头数据到\0之后
    	while (*cur++ = *src++) {
    		;  
    	}
    }
    int main() {
    	char arr1[20] = "hello \0xxxxxxxxxx";
    	char arr2[] = "world";
    	my_strcat(arr1,arr2);
    	printf("%s\n",arr1);
    
    
    	return 0;
    }
    '
    运行

    strcmp 字符串的比较
    这个函数就十分的简单,我就简单的说明一下,这个字符串比较函数,实际上就是一个一个字节字节的比对。
    具体的使用

    /*
    实际上是一个字节一个字节的比较
    实际上比较对应位置上字符的大小,而并非长度
    */
    int main() {
    	char arr1[] = "abcdef";
    	char arr2[] = "abq";
    	int ret = strcmp(arr1,arr2);
    	printf("%d\n",ret);
    	return 0;
    
    }
    '
    运行

    具体的函数实现

    int my_strcmp(const char* s1, const char* s2) {
    	assert(s1 && s2);
    	while (*s1 == *s2) 
     {
    		if (*s1=='\0') 
    		{
    			return 0;
    		}
    		s1++;
    		s2++;
    	}
    	if (*s1 > *s2) {
    
    		return 1;
    	}
    	else {
    		return -1;
    	}
    }
    //字符串比较函数的实现
    int main() {
    	char arr1[] = "abc";
    	char arr2[] = "abq";
    	int ret=my_strcmp(arr1,arr2);
    	if (ret > 0) {
    		printf("arr1>arr2");
    	}
    	else if (ret < 0) {
    		printf("arr1);
    	}
    	else {
    		printf("arr1==arr2");
    	}
    	return 0;
    }
    

    这三组函数,长度受限制,顾名思义,我们做操作的时候,可以指定数量
    strncpy

    char * strncpy ( char * 目标, const char *, size_t num );
    从字符串中复制字符
    将source的前num个字符 复制到destination。如果在复制num个字符之前找到源C 字符串的结尾(由空字符表示) ,则用零填充目标,直到总共写入了num个字符。如果source长于num ,则不会在目标 末尾隐式附加空字符。因此,在这种情况下,目的地不应被视为以空结尾的 C 字符串(这样读取它会溢出)。目的地和
    
    int main()
    {
    	char arr1[20] = "abcdefghi";
    	char arr2[] = "xxxx";
    	strncpy(arr1, arr2, 8);
    	printf("%s\n", arr1);
    
    	return 0;
    }
    

    strncat

    
    int main()
    {
    	char arr1[20] = "abcdef\0qqqqqq";
    	char arr2[] = "xyz";
    	strncat(arr1, arr2, 2);
    	printf("%s\n", arr1);
    
    	return 0;
    }
    '
    运行

    strncmp

    int main()
    {
    	int ret = strncmp("abcdef", "abc", 4);
    	printf("%d\n", ret);
    
    	return 0;
    }
    
    '
    运行

    3.字符串查找

    strstr

    char * strstr ( const char *str1, const char * str2);
    定位子串
    返回指向 str1 中第一次出现str2的指针,如果str2不是 str1 的一部分,则返回空指针。 匹配过程不包括终止的空字符,但它会停在那里。
    
    

    这里大概的意思是,记录字串第一次出现的位置
    具体用法

    int main() {
    
    	char arr1[] = "abcdef";
    	char arr2[] = "bcd";
    	char* p = strstr(arr1, arr2);
    	if (p == NULL) {
    		printf("不存在");
    	}
    	else
    	{
    		printf("%s\n",p);
    	}
    }
    

    strstr 模拟实现
    这个方法不好理解,我画个图大家理解一下

    char* my_strstr(const char* str1, const char* str2)
    {
    	const char* s1 = str1;
    	const char* s2 = str2;
    	const char* p = str1;
    	if (*str2 == '\0')
    	{
    		return str1;
    	}
    	while (*p)
    	{
    		s1 = p;
    		s2 = str2;
    		while (*s1 != '\0' && *s2 != '\0' && (*s1 == *s2))
    		{
    			s1++;
    			s2++;
    		}
    		if (*s2 == '\0')
    		{
    			return (char*)p;//找到了
    		}
    		p++;
    	}
    	return NULL;//找不到子串
    }
    int main()
    {
    	char arr1[] = "abcdefabcdef";
    	char arr2[] = "fab";
    
    	char* p = my_strstr(arr1, arr2);
    	if (p == NULL)
    	{
    		printf("不存在\n");
    	}
    	else
    	{
    		printf("%s\n", p);
    	}
    	return 0;
    }
    

    3.内存操作函数
    memcpy

     memcpy 的函数用法
    int main() {
    	int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    	int arr2[10] = { 0 };
    	memcpy(arr2, arr, 20);
    	float arr1[] = { 1.0f,2.0f,3.0f,4.0f };
    	float arr2[] = { 0.0 };
    	return 0;
    }
    

    具体模拟实现

    // 如何自己实现memcpy
    void* my_memcpy(void* dest,void* src,size_t num) {
    	assert(dest);
    	assert(src);
    	void* ret = dest;
    	while (num--)
    	{
    		*(char*)dest = *(char*)src;
    		dest = (char*)dest + 1;
    		src = (char*)src + 1;
    	}
    	return ret;
    	
    }
    int main() {
    
    	int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    	int arr2[10] = { 0 };
    	my_memcpy(arr2, arr, 20);
    	int i = 0;
    	for (i = 0; i < 10; i++) {
    	
    		printf("%d",arr2[i]);
    	
    	}
    	float arr3[] = { 1.0f,2.0f,3.0f,4.0f };
    	float arr4[] = { 0.0 };
    	my_memcpy(arr4, arr3, 20);
    	return 0; 
    }
    

    这里我们引入一个问题,如果我们自己拷贝自己的话
    是否会成功吗?
    试一试就知道了

    int main()
    {
    	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
    	memcpy(arr1 + 2, arr1, 20);
    	//memmove(arr1+2, arr1, 20);
    
    	//int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
    	//int arr2[10] = { 0 };
    	//my_memcpy(arr2, arr1, 20);
    	int i = 0;
    	for (i = 0; i < 10; i++)
    	{
    		printf("%d ", arr1[i]);
    	}
    }
    '
    运行

    运行截图
    在这里插入图片描述
    你看,我们这里,就出现了自己拷贝自己的问题,
    简单来说,就是,我们正常拷贝的时候,会出现以下情况
    在这里插入图片描述

    所以我们拷贝数据有时候不能从前往后拷贝,有时候会覆盖,这样我们可以考虑从后向前拷贝,我把这样的情况分为以下三种情况
    在这里插入图片描述

    改进之后的代码,如下

    void* my_memcpy(void* dest,void* src,size_t num) {
    	assert(dest);
    	assert(src);
    	void* ret = dest;
    	if (dest < src) 
    	{//前->后
    		while (num--)
    				{
    					*(char*)dest = *(char*)src;
    					dest = (char*)dest + 1;
    					src = (char*)src + 1;
    				}
    	
    	}
    
    	else { //从后向前
    		while (num--) 
    		{
    			*((char*)dest + num) = *((char*)src + num); 
    		}
    	
    	}
    	return ret;
    	
    }
    
    int main() {
    
    	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    	my_memcpy(arr+2, arr, 20);
    	int i = 0;
    	for (i = 0; i < 10; i++) {
    	
    		printf("%d ",arr[i]);
    	
    	}
    
    	return 0; 
    }
    
    

    memmove

    void * memmove ( void * dst, const void * src, size_t count) {
            void * ret = dst;
            if (dst <= src || (char *)dst >= ((char *)src + count)) {
                    /*
                     * Non-Overlapping Buffers
    比特就业课-专注IT大学生就业的精品课程 比特主页:https://m.cctalk.com/inst/s9yewhfr 比特就业课
    本章完
                     * copy from lower addresses to higher addresses
                     */
                    while (count--) {
                            *(char *)dst = *(char *)src;
                            dst = (char *)dst + 1;
                            src = (char *)src + 1;
                   }
           }
            else {
                    /*
                     * Overlapping Buffers
                     * copy from higher addresses to lower addresses
                     */
                    dst = (char *)dst + count - 1;
                    src = (char *)src + count - 1;
                    while (count--) {
                            *(char *)dst = *(char *)src;
                            dst = (char *)dst - 1;
                            src = (char *)src - 1;
                   }
           }
            return(ret);
    }
    

    memset

    具体用法

    int main() {
    	int arr[] = { 1,2,3,4,5 };
    	memset(arr, 0, 8);
    	return 0;
    }
    '
    运行

    memcmp

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

    具体用法

    memcmp的使用
    int main() {
    	int arr2[] = { 1,2,3,0,0 };
    	int arr1[] = { 1,2,3,4,5 };
    	int ret=memcmp(arr1, arr2,12);
    	printf("%d\n",ret);
    	return 0;
    
    }
    

    模拟实现

    void * memcpy ( void * dst, const void * src, size_t count) {
            void * ret = dst;
     assert(dst);
       assert(src);
            /*
             * copy from lower addresses to higher addresses
             */
            while (count--) {
                    *(char *)dst = *(char *)src;
                    dst = (char *)dst + 1;
                    src = (char *)src + 1;
           }
            return(ret);
    }
    
  • 相关阅读:
    项目实训-vue(十二)
    解决SSH连接自动断开的问题
    分布式事务方案
    Qt QWebEngineView 忽略https验证
    Java导出带格式的Excel数据到Word表格
    Java判断字符串是否是有效的括号
    json能够存储图片吗?
    练习:空心金字塔(纯手打玩玩)
    基于Python实现一个在线加密解密网站系统
    尚硅谷设计模式学习(十四)模板方法模式
  • 原文地址:https://blog.csdn.net/qq_45726327/article/details/126966045