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

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

在这里插入图片描述

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

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

1.strlen函数

在这里插入图片描述

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

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

#include <stdio.h>
#include<string.h>
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;
}

在这里插入图片描述

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

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

#include<stdio.h>
#include<assert.h>
#include<windows.h>
 
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;
}

在这里插入图片描述

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

2.strcpy

在这里插入图片描述

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

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

#include<stdio.h>
#include<string.h>
#include<assert.h>

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;
}

在这里插入图片描述

我们这里定义两个字符数组,将这两个数组的地址传到我们自定义的函数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;
}

在这里插入图片描述

在这里插入图片描述

在这个函数我们要知道连接函数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;
}

在这里插入图片描述

我们这里将两个数组的地址传到函数中,我们进入循环中,如果第一个字符的值都相等,如果此时的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;
}

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

int main()
{
    
    
	char arr1[20] = "abc\0xxxxxxxxxxxxxx";
	char arr2[] = "defghi";
	strncat(arr1, arr2, 10);
	printf("%s\n", arr1);

	return 0;
}

在这里插入图片描述

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

6.strstr

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

#include<stdio.h>
#include<assert.h>
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;
}

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

在做这个题的时候我们需要用到多个指针,因为我们要两个指针指向刚开始的位置,用另外的指针去移动,在用指针给储存起来,在这里我们的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[] = "[email protected]";

	char buf[200] = {
    
    0};//"[email protected]"
	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;
}

在这里插入图片描述

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

8. strerror

在这里插入图片描述

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

#include<errno.h>
int main()
{
    
    
	int i = 0;
	for (i = 0; i < 10; i++)
	{
    
    
		printf("%d: %s\n", i, strerror(i));
	}

	return 0;
}

在这里插入图片描述

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

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

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Lehjy/article/details/133037045