【C语言】字符函数,字符串函数和内存函数

目录

一.字符函数

1.字符分类函数

2.字符转换函数

二.字符串函数

1.strlen函数的使用和模拟实现

2.strcpy函数的使用和模拟实现

3.strcat函数的使用和模拟实现

4.strcmp函数的使用和模拟实现

5.strncpy函数的使用

6.strncat函数的使用

7.strncmp函数的使用

8.strstr的使⽤和模拟实现

9. strtok函数的使⽤

10.strerror函数的使⽤

三.内存函数

1. memcpy使⽤和模拟实现

2. memmove使⽤和模拟实现

3. memset函数的使⽤

4. memcmp函数的使⽤


一.字符函数

1.字符分类函数

C语⾔中有⼀系列的函数是专⻔做字符分类的,也就是⼀个字符是属于什么类型的字符的。 这些函数的使⽤都需要包含⼀个头⽂件是 ctype.h

这些函数用法十分相似,都是判断函数返回值是否为函数指定的内容,若是则为真,返回一个非0的数;否则为假,返回值为0。

我们用islower函数来句一个简单的例子:

75a894b00cc0435da3cc8fee00061cb5.png

islower函数的作用是判断一个字符是否为小写的形式。在这里,我们可以看到islower函数参数类型是整形,返回值也是整形。我们可以猜想islower函数的原理就是将字符的ASCII的值返回。如果返回值是97到122,则说明字符是小写的形式,我们写一段代码演示一下:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<ctype.h>

int main()
{
	char str1 = 'a';
	char str2 = 'A';
	int i = islower(str1);
	int j = islower(str2);
	int k = islower(97);
	printf("%d  %d  %d", i, j, k);
	return 0;
}

5438ff76c32d402893bb58fa37dcf015.png

观察运行结果,可以证明我们的猜想正确。

关于字符分类函数,几个函数的用法基本上相同,其他就不做过多介绍了。

2.字符转换函数

C语言提供了两个字符转换函数,分别是:

int tolower ( int c ); //将参数传进去的⼤写字⺟转⼩写 
int toupper ( int c ); //将参数传进去的⼩写字⺟转⼤写

这两个函数的作用是实现大小写字母的相互转换。

同样,我们以toupper函数举例

db992b59041e4fceb0654416b449dcaa.png

toupper函数的作用是将小写字母转换为大写字母,参数和返回值都为整形,我们同样可以猜想toupper函数的运行原理就是先判断ASCII值是否在97到122之间,再将字符的ASCII值减去32在返回,代码如下:

#define _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
#include<ctype.h>

int main()
{
	char i = toupper('a');
	char j = toupper(97);
	printf("%c  %c", i, j);
	return 0;
}

efc3e290e66e41ee80f23b11d5182b47.png

根据运行结果,证明我们的猜想正确。

我们还可以利用toupper函数以及上面介绍的islower函数来实现一个字符串的字母大写的转换,代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <ctype.h>
int main()
{
	int i = 0;
	char str[] = "Hello World!!";
	char c;
	while (str[i])
	{
		c = str[i];
		if (islower(c))
			c = toupper(c);
		putchar(c);
		i++;
	}
	return 0;
}

4df540341ef5463f9e6e7968b2e96993.png

二.字符串函数

1.strlen函数的使用和模拟实现

strlen函数在我之前的一篇博客中介绍过,为了避免重复,就不做介绍了,链接如下:

3种strlen函数的模拟实现-CSDN博客

2.strcpy函数的使用和模拟实现

752d57c432c84546b55ce1961ccdae59.png

strcpy函数的作用是将一个字符串拷贝到另一个字符串中:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
	char str1[] = "hello";
	char str2[20] = "**************";
	strcpy(str2, str1);
	printf("%s", str2);
	return 0;
}

efda2401c530423a97c7c581e5dfbfc4.png

模拟实现:

​
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<assert.h>
char* my_strcpy(char* Str2, const char* Str1)
{
	assert(Str1 && Str2);
	char* ret = Str2;
	while (*Str2++ = *Str1++)
	{
		;
	}
	return ret;
}
int main()
{
	char str1[] = "abcdef";
	char str2[20] = "******************";
	char* ret=my_strcpy(str2, str1);
	printf("%s\n", ret);
	return 0;
}

​

c043a2e1c8b24d2a95d303b2a0c8d4c2.png

3.strcat函数的使用和模拟实现

d40a6cd6229e4f5dbd088c6ee1181845.png

strcat函数的作用是将一个字符串追加到另一个字符串上,

​
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
	char str1[20] = "hello ";
	char* str2 = "world";
	strcat(str1, str2);
	printf("%s\n", str1);
	return 0;
}

​

4f0ab645139f4f31be44e7a31170b49c.png

模拟实现:

​
#define _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
#include<assert.h>
char* my_strcat(char* Str1, char* Str2)
{
	assert(Str1 && Str2);
	char* ret = Str1;
	while (*Str1)
	{
		Str1++;
	}
	while (*Str1++ = *Str2++)
	{
		;
	}
	return ret;
}
int main()
{
	char str1[20] = "hello ";
	char str2[] = "world";
	char* i=my_strcat(str1, str2);
	printf("%s\n", str1);
	printf("%s\n", i);
	return 0;
}

​

396fcd0629a849de947401c3f96c5e22.png

4.strcmp函数的使用和模拟实现

c30572c22cbf4c6ea9748d30275a1bb3.png

strcmp函数的作用是比较两个字符串的大小,大小比较是一一对应进行比较的,比较的是每个字符的ASCII值,如果第一个参数大于第二个参数,返回值是一个大于0的数字;等于的话,返回值是一个的等于0的数字;小于的话,返回值是一个小于0的数字。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
	char str1[] = "abcdef";
	char str2[] = "abcdff";
	int i = strcmp(str1, str2);
	printf("%d", i);
	return 0;
}

b5167e65064548f481af62cb70873ec7.png

模拟实现:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<assert.h>
int my_strcmp(char* Str1, char* Str2)
{
	assert(Str1 && Str2);
	while (*Str1 == *Str2)
	{
		Str1++;
		Str2++;
	}
	if (*Str1 > *Str2)
	{
		return 1;
	}
	else if (*Str1 == *Str2)
	{
		return 0;
	}
	else
	{
		return -1;
	}
}
int main()
{
	char str1[] = "abcdef";
	char str2[] = "abcddf";
	int i=my_strcmp(str1, str2);
	printf("%d", i);
	return 0;
}

c1658410172640aebc733948269b3b4b.png

5.strncpy函数的使用

5dbe7302791242b1a80ee280e4f82ade.png

strncpy函数的用法与strcpy函数相似,不过strncpy函数多了一个参数,这个参数用来限定拷贝字符串的数量:

​
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
	char str1[] = "hello world";
	char str2[20] = "******************";
	strncpy(str2, str1, 9);
	printf("%s\n", str2);
	return 0;
}

​

5921bb6f04e64efcba582b004823cd4b.png

6.strncat函数的使用

4a2bbc14c9ad4710a77fdd9b57ddc9f5.png

strncat函数同样可以设置追加字符串的数量

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>

int main()
{
	char str1[20] = "hello ";
	char* str2 = "world!!!!!!!!!";
	strncat(str1, str2, 5);
	printf("%s\n", str1);
	return 0;
}

be07cc69771c4d45b22bb8bb46ec9e3f.png

7.strncmp函数的使用

strncmp函数的作用同样是比较两个字符串的大小,第三个参数限制比较字符串的长度。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
	char str1[] = "abcdefg";
	char str2[] = "abcdeee";
	int ret=strncmp(str1, str2,6);
	printf("%d", ret);
	return 0;
}

8.strstr的使⽤和模拟实现

strstr函数的作用是返回字符串str2在字符串str1出现的位置。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>;
int main()
{
	char str1[] = "This is an apple";
	char* str2 = "is";
	char* str = strstr(str1, str2);
	printf("%s", str);
	return 0;
}

模拟实现:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
char* my_strstr(const char* Str1, const char* Str2)
{
	const char* cur = Str1;
	const char* s1 = NULL;
	const char* s2 = NULL;
	if (*Str2 == '\0')
		return (char*)Str1;
	while (*cur)
	{
		s1 = cur;
		s2 = Str2;
		while (*s1 !='\0' && *s2!='\0' && *s1 == *s2)
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
		{
			return cur;
		}
		cur++;
	}
	return NULL;
}
int main()
{
	char str1[20] = "This is an apple";
	char* str2 = "is";
	char* i = my_strstr(str1, str2);
	printf("%s",i);
	return 0;
}

9. strtok函数的使⽤

strtok函数的作用是将一段字符串用某个字符分割开。

sep参数指向⼀个字符串,定义了⽤作分隔符的字符集合。

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

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

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

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

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

基本用法如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
	char str1[] = "3iigfwggaui.sadvbyu.avhuc.hayvofaf";
	const char* str2 = ".";
	char* i = NULL;
	i = strtok(str1, str2);
	printf("%s\n", i);
	i = strtok(NULL, str2);
	printf("%s\n", i);
	i = strtok(NULL, str2);
	printf("%s\n", i);
	i = strtok(NULL, str2);
	printf("%s\n", i);
	return 0;
}

这种写法比较麻烦且没有自动性,我们可以使用for循环

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
	char str1[] = "3iigfwggaui.sadvbyu.avhuc.hayvofaf";
	const char* str2 = ".";
	char* i = NULL;
	i = strtok(str1, str2);
	for (; i != NULL;i = strtok(NULL, str2))
	{
		printf("%s\n",i);
	}
	return 0;
}

10.strerror函数的使⽤

strerror函数的作用是把参数部分错误码对应的错误信息的字符串地址返回来。

在不同的系统和C语⾔标准库的实现中都规定了⼀些错误码,⼀般是放在 errno.h 这个头⽂件中说明的,C语⾔程序启动的时候就会使⽤⼀个全⾯的变量errno来记录程序的当前错误码,只不过程序启动的时候errno是0,表⽰没有错误,当我们在使⽤标准库中的函数的时候发⽣了某种错误,就会讲对应的错误码,存放在errno中,⽽⼀个错误码的数字是整数很难理解是什么意思,所以每⼀个错误码都是有对应的错误信息的。strerror函数就可以将错误对应的错误信息字符串的地址返回。

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

三.内存函数

1. memcpy使⽤和模拟实现

memcpy函数的作用是函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。(注:因为拷贝的是内存,所以如果遇到´\0´并不会停下来)

如果source和destination有任何的重叠,复制的结果都是未定义的。也就是说,memcpy函数只能用于不同的字符串的拷贝。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
	short arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	short arr2[10] = { 0 };
	memcpy(arr2, arr1, 10);
	short i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}

模拟实现:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<assert.h>
void* my_memcpy(void* Arr2, void* Arr1, size_t num)
{
	assert(Arr1 && Arr2);
	while (num--)
	{
		*(char*)Arr2 = *(char*)Arr1;
		Arr2=(char*)Arr2+1;
		Arr1=(char*)Arr1+1;
	}
}
int main()
{
	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 ", arr2[i]);
	}
	return 0;
}

2. memmove使⽤和模拟实现

memmove函数的用法和memcpy函数相似,但是memmove函数处理的源内存块和⽬标内存块是可以重叠的。

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

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	memmove(arr+2, arr, 20);
	for(int i = 0; i < 10;i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

模拟实现:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<assert.h>
void* my_memmove(void* Arr1, void* Arr2, size_t num)
{
	assert(Arr1 && Arr2);
	if (Arr1 < Arr2)
	{
		while (num--)
		{
			*(char*)Arr1 = *(char*)Arr2;
			Arr1 = (char*)Arr1 + 1;
			Arr2 = (char*)Arr2 + 1;
		}
	}
	else
	{
		Arr1 = (char*)Arr1 + num-1;
		Arr2 = (char*)Arr2 + num-1;
		while (num--)
		{
			*(char*)Arr1 = *(char*)Arr2;
			Arr1 = (char*)Arr1 - 1;
			Arr2 = (char*)Arr2 - 1;
		}
	}
}
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	my_memmove(arr1+2, arr1, 20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

3. memset函数的使⽤

memset是⽤来设置内存的,将内存中的值以字节为单位设置成想要的内容。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	memset(arr,0, 24);
	for (int i = 0; i<10; i++)
	{
		printf("%d ", arr[i]);
    }
	return 0;
}

4. memcmp函数的使⽤

memcmp用来比较两个字符串的大小,⽐较从ptr1和ptr2指针指向的位置开始,向后的num个字节。若ptr1大于ptr2,返回一个大于0的数字,等于返回0,小于返回一个小于0的数字。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8 };
	int arr2[10] = { 1,2,3,4,5,5,5,5 };
	int ret=memcmp(arr1, arr2, 30);
	printf("%d", ret);
	return 0;
}

  • 28
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值