C语言_字符函数

目录

1.strtok函数:

2.strerror错误报告函数:

3.字符分类函数:

4.memcpy内存拷贝函数:

5.memmove函数:

6.memcmp内存比较函数:

7.memset内存设置函数:


1.strtok函数

分隔函数;简单来说就是www.555648@qq.com , 我使用strtok函数可以将邮箱分隔为www    555648    qq   com  其中分隔符为  . @    .    所以函数定义参数时sep为“.@.”;

参数定义方法:char  strtok(char *str,const char *sep);其中sep函数是一个字符串,定义了用作分隔符的字符集合;

int main()
{
	char arr[] = "zpw@bitedu.tech";
	char *p = "@.";
	strtok(arr, p);
	return 0;
}

strtok函数在使用时,会将字符串拷贝一份,切割的过程发生在拷贝的字符串上;第一次调用这个函数,函数收到字符串的首元素地址,寻找sep中第一个切割标志符,第一个字符串不为NULL时,返回第一个字符串,并且保留在切割字符的位置;第二次调用这个函数时,从上一次切割字符的位置进行寻找,找下一个sep标志符;从第二次切割开始,不能再次调用arr,从第二次开始,以后每次都需要调用NULL;

int main()
{
	char arr[] = "zpw@bitedu.tech";
	char *p = "@.";
	char buff[1024] = { 0 };
	strcpy(buff, arr);
	char *ret=strtok(arr, p);
	printf("%s\n", ret);
	ret = strtok(NULL, p);
	printf("%s\n", ret);
	ret = strtok(NULL, p);
	printf("%s\n", ret);
	return 0;
}

打印结果:zpw  /  bitedu  /  tech  ;

上述程序太过于单纯;当我们拿到一个字符串时,我们不可能去字符串里面找有多少个分隔符,也就是sep,我们就strtok多少次;

int main()
{
	char arr[] = "zpw@bitedu.tech";
	char *p = "@.";
	char *ret = NULL;
	for (ret = strtok(arr, p); ret != NULL; ret = strtok(NULL, p))
	{
		printf("%s\n", ret);
	}
	return 0;
}

在此,我们巧妙的使用一个for循环,同时也是警醒我们,for循环并不是单纯的i=0;i<100;i++来使用的;首先定义空指针ret,for循环,初始化ret=第一次分割,限制条件,ret不等于空指针,我们知道strtok函数一旦返回NULL,意味着分割完成,所有设定的sep分割符都已经找到,所以知道不返回NULL,我就循环,每循环一次,我就打印一次ret;每循环一次,下一次的strtok的arr需要设置为NULL;

2.strerror错误报告函数

参数定义方法:char *strerror(int errnum);此函数使用必须定义头文件;#include <errno.h>;

该函数的功能就是:C语言中定义错误码;每一种错误码对应一种错误信息,C语言为了保证用户能够认出不同错误码所对应的错误信息;故引入该函数;

int main()
{
	char *str = strerror(4);
	printf("%s\n", str);
	return 0;
}
//0--No error
//1--Operation not permitted
//2--No such file or directory
//3--No such process
//4--Interrupted function call

以上程序显示结果:不同错误码对应的错误信息不同;

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

int main()
{
	char *str = strerror(errno);
	printf("%s\n", str);
	return 0;
}

erron是一个全局的错误码值;当C语言的库函数在执行过程,一旦发现错误,就会把对应的错误码赋值给erron,进而产生错误信息;

3.字符分类函数:

iscntrl---任何控制字符;isdigit---十进制数字0-9;isxdigit---十六进制数字;islower---小写字母a-z;isspace---空白字符;isupper---大写字母A-Z;isalpha---字母a-z;isslnum---字母或者数字;ispunct---标点符号;isgraph---任何图形字符;isprint---任何可打印字符;

以上字符分类函数在函数定义范围内则返回为真;否则返回0;

大小写字符打印函数:tolower:大写转到小写;toupper:小写转到大写;

int main()
{
	char ret = toupper('a');
	printf("%c\n", ret);
	return 0;

}

再一次注意:%s打印字符串;%c打印字符;

4.memcpy内存拷贝函数:

函数使用定义:void *memcpy(void *destination,const void* source,size_t num);1---要拷贝的目的地;2---把什么拷贝到目的地,也就是要拷贝的东西,const修饰,要拷贝的东西不可以发生改变;3---因为是void,没有返回类型;所以定义要拷贝的字节数目,单位是字节;切记:第三个参数单位是字节;

int main()
{
	int arr1[] = { 1, 2, 3, 4, 5 };
	int arr2[5] = { 0 };
	
	memcpy(arr2, arr1, sizeof(arr1));
	return 0;
}
struct S
{
	char name[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(arr4, arr3, sizeof(arr3));
	return 0;
}

mencpy内存拷贝函数相比于strcpy字符串拷贝函数的区别:strcpy字符串拷贝函数只能拷贝char字符串类型,而memcpy内存拷贝函数的函数类型为void,可以拷贝任意类型的函数;

void* my_memcpy(void *destination,const void *source,size_t num)
{
	void *ret = destination;
	assert(destination != NULL);
	assert(source != NULL);

	while (num--)
	{
		*(char*)destination = *(char *)source;
		++(char *)destination;
		++(char *)source;
	}
	return ret;
}

自主定义的my_memcpy内存拷贝函数;内存拷贝函数含有三个变量---地址,来源,需要拷贝字符的个数;来源切记需要const修饰,保证来源不会发生改变;函数类型均为void,保证任何类型的函数均可以进行拷贝;但是需要注意,void * 不可以直接赋值去拷贝,必须强制类型转化以后才可以;这里强制类型转换为char *;每一次拷贝拷贝一个字符;最后需要特别注意的是:内存拷贝传过去的是你要拷贝的首元素的地址,所以需要用指针来接收首元素的地址;指针是不能++的;强制类型转换成char* 以后存有优先级的问题,所以改变前置++;

memcpy内存拷贝函数的局限性:比如我定义int arr[]={1,2,3,4,5,6,7,8,9,10};我想把12345拷贝到34567的地址上,当内存重复时,mencpy内存拷贝函数是无法完成的;原因在于该函数源函数是用const修饰的,并且强制类型转换为char* ,一个字符一个字符的拷贝,当1拷贝到3地址上,2拷贝到4地址上,考虑到把3拷贝到5地址时,3地址上的存放的不再是3,而是1,此拷贝过程会把1重新拷贝到5的地址上,后续过程会重复此操作;所以想要拷贝重复的地址时,考虑memmove考虑内存重叠的情况;

5.memmove函数:

函数定义 void* memmove(void* destination,const void*source,size_t num);和memcpy函数定义相同;

int main()
{
	int i = 0;
	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	memmove(arr+2, arr, 20);
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

memmove可以处理地址重复的现象;可以完成上述将12345拷贝到45678地址上;C语言标准:memcpy只要处理不重叠的内存拷贝就可以;memmove处理重叠内存的拷贝;

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

void* my_memmove(void *destination,const void *source,size_t num)
{
	void *ret = destination;
	assert(destination != NULL);
	assert(source != NULL);
	if (destination < source)
	{
		while (num--)
		{
			*(char*)destination = *(char *)source;
			++(char *)destination;
			++(char *)source;
		}
	}
	else 
	{
		while (num--)
		{
			*((char*)destination+num) = *((char *)source+num);
		}
	}
	return ret;
}
int main()
{
	int i = 0;
	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	my_memmove(arr+2, arr, 20);
	for (i = 0; i < 9; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

自定义:memmove函数;存在三种情况:目的地在源函数左侧;目的地和源函数重叠;目的地在源函数的右侧;其中重叠和目的地在源函数的右侧是一种情况;

6.memcmp内存比较函数:

函数定义 :int memcmp(const void* ptr1,const void* ptr2,size_t num);比较从ptr1和ptr2开始的num个字节;单位是字节;特别注意

int main()
{
	int arr1[] = { 1, 2, 3, 4, 5, 6 };
	int arr2[] = { 1, 2, 5, 6, 7, 5 };
	int ret=memcmp(arr1, arr2, 8);
	printf("%d ", ret);
	return 0;
}

 前两个数相同,返回值为0;

比较前两个数;因为是整型,int含有4个字节;所以第三个参数为8;再次强调,第三个参数单位是字节;

int main()
{
	int arr1[] = { 1, 2, 3, 4, 5, 6 };
	int arr2[] = { 1, 2, 5, 6, 7, 5 };
	int ret=memcmp(arr1, arr2, 12);
	printf("%d ", ret);
	return 0;
}

比较前三个数,第一个小于第二个,返回值为-1;

int main()
{
	int arr1[] = { 1, 2, 3, 7, 5, 6 };
	int arr2[] = { 1, 2, 3, 6, 7, 5 };
	int ret=memcmp(arr1, arr2, 16);
	printf("%d ", ret);
	return 0;
}

比较前四个数,第一个数大于第二个数,返回值为1;综上情况,相等返回0;小于则返回小于0的数;大于则返回大于0的数;

7.memset内存设置函数:

函数参数:void *memset(void* dest,int c,size_t count);dest---目的地;c---设置的字符是什么;count---设置的c数字,即设置多少;

int main()
{
	char arr[10] = "";
	memset(arr, '#', 8);
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值