• C语言字符函数和字符串函数(1)


    大家好,我们又见面了,让大家久等了,我们今天就来学习字符函数和字符串函数

    在这里插入图片描述

    在开启今天的学习之前呢,我来解决一下一些小伙伴平时找不到库函数使用的烦恼,因为我们cplusplus.com最新版本不能够查询函数,我们需要去找我们需要使用的函数,所以就很麻烦,我们可以将它切换成老版本就可以进行查询了。
    在这里插入图片描述

    在这里插入图片描述
    我们只要点击这个红色框就能够切换成老版本了。
    在这里插入图片描述
    然后我们点击红色框输入我们想要知道的函数就可以实现查询了。

    1.strlen函数

    在这里插入图片描述

    我们以前接触过这个函数,这个函数是用来求字符串或字符长度的对吧,求的是‘/0’之前的字符个数。
    我们在这里需要注意的是:
    字符串已经 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数(不包
    含 ‘\0’ )
    参数指向的字符串必须要以 ‘\0’ 结束。
    注意函数的返回值为size_t,是无符号的( 易错 )
    学会strlen函数的模拟实现

    那么我们怎么来使用它呢,我们看到代码:

    #include 
    #include
    int main()
    {
    const char*str1 = "abcdef";
    const char*str2 = "bbb";
    if(strlen(str2)-strlen(str1)>0)
    {
    printf("str2>str1\n");
    }
    else
    {
    printf("srt1>str2\n");
    }
    return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    我们因为str1里面‘\0’前面有六个字符,所以strlen的结果就是6,而str2的结果就只有3,但是我们这里函数的返回类型size_t,也就是无符号数,我们得到的结果是-3,但是我们这里的结果之后也得转化为一个无符号数,就会是一个很大的正数,所以结果就会输出str2>str1。

    那么怎么对这个函数模拟实现呢?

    #include
    #include
    #include
     
    int my_strlen(const char *str)
    {
    	int count = 0;
    	assert(str != NULL);//断言,指针为空,打印出错误信息
    	while (*str++)//遇到'\0'停止,不算'\0'
    	{
    		count++;
    	}
    	return count;
    }
    
    int main()
    {
    	int len=0;
    	char *p = "abcdef";
    	len=my_strlen(p);
    	printf("len=%d\n", len);
    	system("pause");
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    在这里插入图片描述

    这里我们要注意我们的传过去的*p,因为我们只求它的字符个数,所以我们不用改变它,就给它用const进行保护,我们为了防止空指针,所以要给它进行断言,我们在使用断言的时候,我们要加上头文件#include,因为我们这里是要求它的字符个数,所以我们需要碰到一个字符就给它计数,所以我们要定义一个计数器,并且对它初始化,我们接下来就利用循环结构就行,当我们碰到一个字符就计数,碰到‘\0’的时候得到’\0’,它的Ascall值为0,所以我们碰到‘\0’的时候就为假,就跳出循环了,最后在将结果返回主函数进行打印。

    2.strcpy

    在这里插入图片描述

    源字符串必须以 ‘\0’ 结束。
    会将源字符串中的 ‘\0’ 拷贝到目标空间。
    目标空间必须足够大,以确保能存放源字符串。
    目标空间必须可变。
    学会模拟实现。

    接下来我们就给它模拟实现以下:

    #include
    #include
    #include
    
    char* my_strcpy(char* dest, const char* src)
    {
    	char* ret = dest;
    	assert(dest && src);
    
    	while (*dest++ = *src++)
    	{
    		;
    	}
    	return ret;
    }
    
    int main()
    {
    	char arr1[20] = { 0 };
    	char arr2[] = "abc";
    
    	/*my_strcpy(arr1, arr2);
    	printf("%s\n", arr1);*/
    
    
    	printf("%s\n", my_strcpy(arr1, arr2));
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    在这里插入图片描述

    我们这里定义两个字符数组,将这两个数组的地址传到我们自定义的函数my_strcat中,通过两个指针接收,这里我们依然要给它进行断言,因为我们要把第二个数组的元素拷贝到第一个元素当中,所以我们第二个元素是不变的,所以就用const对它进行保护,首先我们用一个循环找到数组的一个末尾,然后再循环将指针str中的内容拷贝到指针dest中,当dest为’/0’时,整个式子的结果为假就跳出循环。再将指针ret储存的数据返回进行打印。

    3.strcat

    在这里插入图片描述

    连接函数
    源字符串必须以 ‘\0’ 结束。
    目标空间必须有足够的大,能容纳下源字符串的内容。
    目标空间必须可修改。
    字符串自己给自己追加,如何

    char* my_strcat(char* dest, const char* src)
    {
    	char* ret = dest;
    	assert(dest && src);
    	//1. 找到目标空间的末尾
    	while (*dest != '\0')
    	{
    		dest++;
    	}
    	//2. 数据追加
    	while (*dest++ = *src++)
    	{
    		;
    	}
    	return ret;
    }
    
    int main()
    {
    	char arr1[20] = "abc";
    	strcat(arr1, arr1);//strncat
    	printf("%s\n", arr1);
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    在这里插入图片描述

    在这里插入图片描述

    在这个函数我们要知道连接函数strcat和拷贝函数strcpy一样,我们要连接的数组是从上一个数组的‘/0’开始,而且第二个数组的‘\0’也会连接到上一个数组作为结束的标志。所以当我们字符串自己给自己追加也会打印出结果。我们在这里也要进行断言,为了防止变成空指针。

    4.strcmp

    在这里插入图片描述

    比较字符串函数:
    第一个字符串大于第二个字符串,则返回大于0的数字
    第一个字符串等于第二个字符串,则返回0
    第一个字符串小于第二个字符串,则返回小于0的数字

    那么我们怎么去比较两个字符串的大小呢?我们其实是比较两个字符串函数之间对应位置字符的ASCLL值的小,如果前一个相同的话就比较下一个,一直比较下去直到比较出大小为止。
    在这里插入图片描述

    int my_strcmp(const char* str1, const char* str2)
    {
    	assert(str1 && str2);
    
    	while (*str1 == *str2)
    	{
    		if (*str1 == '\0')
    			return 0;
    		str1++;
    		str2++;
    	}
    	return *str1 - *str2;
    }
    
    int main()
    {
    	char arr1[] = "abq";
    	char arr2[] = "abc";
    	if (my_strcmp(arr1, arr2) > 0)
    	{
    		printf(">\n");
    	}
    	else
    	{
    		printf("<=\n");
    	}
    
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    在这里插入图片描述

    我们这里将两个数组的地址传到函数中,我们进入循环中,如果第一个字符的值都相等,如果此时的str1=‘/0’的话,那么str2也为’\0’,所以两个字符串大小相等,如果str1!=0,那么我们就进行下一个字符的比较,最后返回str1-str2到主函数中进行判断和打印结果。

    5.strncpy, strncat,strncmp

    我们看到这里的三个函数和上面我们刚学的一些函数有些相似,那么我们就以strcpy和strncpy函数为例来讲解。
    在这里插入图片描述

    我们发现下面这个函数多了一个参数,而且是一个无符号数的参数,那么这个参数具体的作用是什么呢?其实这个参数是进行限制作用的,我们这个拷贝函数,如果给num一个值,那么num就是我们拷贝过去的字符个数。

    int main()
    {
    	char arr1[20] = { 0 };
    	char arr2[] = "abcdefghi";
    	strncpy(arr1, arr2, 3);
    	printf("%s\n", arr1);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述
    因为我们这里传的参数是3,所以我们只拷贝三个字符上去,所以得到的结果是abc。

    int main()
    {
    	char arr1[20] = "abc\0xxxxxxxxxxxxxx";
    	char arr2[] = "defghi";
    	strncat(arr1, arr2, 10);
    	printf("%s\n", arr1);
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    我们这里用的连接函数是10个字符,所以我们全部都可以连接上去。但是我们要注意拷贝的时候如果我们要拷贝10个字符上去,而我们这个数组少于10个字符的时候后面多的位置就会补充’\0’,而我们的连接函数则不会补充’\0’,这就是这两个函数的区别。另外两个也是类似的,这里就不一一进行讲解了。

    6.strstr

    在这里插入图片描述
    上面这个是c++,而下面这个才是我们C语言的库函数。这个函数的作用呢就是在一个字符串里找到我们出现的字符串。也就是说要从我们str1里面找到str2的字符串。

    #include
    #include
    const char* my_strstr(const char* str1, const char* str2)
    {
    	const char* cp;//记录开始匹配的位置
    	const char* s1;//遍历str1指向的字符串
    	const char* s2;//遍历str2指向的字符串
    
    	assert(str1 && str2);
    	if (*str2 == '\0')
    		return str1;
    
    	cp = str1;
    	while (*cp)
    	{
    		s1 = cp;
    		s2 = str2;
    		while (*s1 && *s2 && *s1 == *s2)
    		{
    			s1++;
    			s2++;
    		}
    		if (*s2 == '\0')
    			return cp;
    
    		cp++;
    	}
    	return NULL;
    }
    
    int main()
    {
    	char arr1[] = "abbbcdef";
    	char arr2[] = "bbc";
    
    	const char* ret = my_strstr(arr1, arr2);
    	if (ret == NULL)
    	{
    		printf("找不到\n");
    	}
    	else
    	{
    		printf("%s\n", ret);
    	}
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    在这里插入图片描述
    在这里插入图片描述

    在做这个题的时候我们需要用到多个指针,因为我们要两个指针指向刚开始的位置,用另外的指针去移动,在用指针给储存起来,在这里我们的s1和s2指针是用来遍历的,我们先用if语句进行判断,如果我们的str2为’\0’时,就返回str1,因为我们在集合中就已经知道空集合是任意集合的子集,当我们的str2指针为’\0’时,我们才会将str1的指针用cp来接收,然后我们将cp指针和str2指针分别赋给s1和s2指针,前提是cp不能为不能为’\0’,然后我们进入下一个循环,当s1和s2为’\0’和s1与s2相等时,我们就给他们进行下一个字符的比较,如果不相等我们就跳出循环,跳出循环后要对指针s2进行判断,如果我们的s2指针为’\0’的话,我们就返回cp,cp++我们就下一个字符作为第一个字符开始遍历,如果一直到指针cp为’\0’的时候都没有找到,那就返回NULL空指针。

    7.strtok

    在这里插入图片描述

    sep参数是个字符串,定义了用作分隔符的字符集合
    第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记
    strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
    strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
    strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
    如果字符串中不存在更多的标记,则返回 NULL 指针。

    这个函数的作用是用分隔符将我们的一些字符串给分隔开,而我们将分隔符储存到一个指针sep中,当我们需要用到的时候就给它传参就行了。

    int main()
    {
    	char arr[] = "zpengwei@yeah.net";
    
    	char buf[200] = {0};//"zpengwei@yeah.net"
    	strcpy(buf, arr);
    
    	char* p = "@.";
    	char* s = strtok(buf, p);
    	printf("%s\n", s);
    
    	s = strtok(NULL, p);
    	printf("%s\n", s);
    
    	s = strtok(NULL, p);
    	printf("%s\n", s);
    
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在这里插入图片描述

    我们将分隔符@和.存入一个指针p中,当我们对字符串进行操作的时候我们就取分隔符前面的字符串,并且将分隔符的位置保存下来,然后我们想要对下面的字符串进行打印的话,就要重复对字符串进行该函数操作,不过这里传参不同,我们传参的第一个位置变成了空指针NULL,而我们的就会从上一次标记的地方开始,找到下一个分隔符,将字符串输出

    8. strerror

    在这里插入图片描述

    这个函数的作用是返回错误码,所对应的错误信息。

    #include
    int main()
    {
    	int i = 0;
    	for (i = 0; i < 10; i++)
    	{
    		printf("%d: %s\n", i, strerror(i));
    	}
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    在使用这个函数我们会用到全新的头文件,这个我们要记得,然后由于我们这个函数的作用是返回错误码所对应的信息,我们就可以利用循环来查看0到9的错误码所代表的信息。

    好了,学到这里大家一定都很累了吧,我们今天的学习就到这里了,我们下次再见,谢谢大家。

    在这里插入图片描述

  • 相关阅读:
    Linux命令dmesg介绍和使用
    吴恩达团队2022机器学习课程,来啦
    在bootstrap中,能不能对同一个容器,既使用类row进行网格设计,又使用类d-flex实现弹性盒子的性能?
    Py之PaddleFL:PaddleFL/paddle_fl的简介、安装、使用方法之详细攻略
    Open Street Map Feature内容 (tags.key and value)
    SQLMAP注入参数-其他参数介绍
    计算机毕设(附源码)JAVA-SSM基于的企业人事管理系统
    Android学习笔记 2.4.1 实例——图片浏览器 && 2.4.2 实例——强大的图片按钮
    关于缓存一致性协议、MESI、StoreBuffer、InvalidateQueue、内存屏障、Lock指令和JMM的那点事
    vue项目 H5 动态设置浏览器标题
  • 原文地址:https://blog.csdn.net/Lehjy/article/details/133037045