字符串+内存函数(C语言)-创新互联

目录

10年专注成都网站制作,成都企业网站建设,个人网站制作服务,为大家分享网站制作知识、方案,网站设计流程、步骤,成功服务上千家企业。为您提供网站建设,网站制作,网页设计及定制高端网站建设服务,专注于成都企业网站建设,高端网页制作,对成都会所设计等多个领域,拥有多年建站经验。

函数介绍:

字符串函数:

strlen

一道迷惑笔试题:

strcpy

strcat

strcmp

strncpy

strncat

strncmp

strstr

strtok

strerror

字符分类函数:

iscntrl 

isspace

isdigit

isxdigit

islower

isupper

isalpha

isalnum

ispunct

isgraph

isprint

tolower

toupper

内存函数:

memcpy

memmove

memcmp

memset

库函数的模拟实现

模拟实现strlen

模拟实现strcpy

模拟实现strcat

模拟实现strstr

模拟实现strcmp

模拟实现memcpy

模拟实现memmove


对C语言中的几个常用的库函数进行解释说明

并彻底了解如何使用

了解原理,并进行模拟实现

函数介绍: 字符串函数:
strlen

计算字符串长度函数

函数原型:size_t  strlen(const char* str)

返回值:size_t   就是  unsigned int 无符号整型

 返回的是'\0‘之前字符的个数 

参数:const char* str  

 是一个char*的指针 且用const修饰

 const修饰的是*str

表示指针指向的内容是不可被修改的

函数作用:计算的是字符串长度

计算'\0'之前字符的个数

函数的用途:看以下代码:

#include#includeint main()
{
	//创建一个数组 用来封装字符串
	char str[] = "abcdefghjk";
	
	//调用strlen函数,用一个size_t 无符号整型来接收
	//将str数组名表示首元素地址,也就是字符串的首地址传过去
	size_t len = strlen(str);

	//打印,从传过去的位置开始,遇到'\0'之前,字符的个数
	printf("%u\n", len);

	return 0;
}
一道迷惑笔试题:
#include#includeint main()
{
	const char* str1 = "abcdef";
	const char* str2 = "bbb";

	if (strlen(str2) - strlen(str1) >0)
	{
		printf("str2>str1\n");
	}
	else
	{
		printf("srt1>str2\n");
	}

//在判断的时候,strlen(str2)的值为3
//strlen(str1)的值为6
//而 3 和 6 都是size_t类型
//3-6 的实际结果为:-3
// -3 :
// 原码:10000000 00000000 00000000 00000011
// 反码:11111111 11111111 11111111 11111100
// 补码:11111111 11111111 11111111 11111101
// 
//但因为是无符号整型,将-3的补码实际解读的时候
//是按照无符号数来解读的,因为正数的 原码,反码,补码相同
//所以将-3的补码当做原码解读,是一个很大的数
//该数必定大于0 所以必定指向if里面的语句

	return 0;
}

解析:

答案:str2>str1

在判断的时候,strlen(str2)的值为3
strlen(str1)的值为6
而 3 和 6 都是size_t类型
3-6 的实际结果为:-3
-3 :
原码:10000000 00000000 00000000 00000011
反码:11111111 11111111 11111111 11111100
补码:11111111 11111111 11111111 11111101

但因为是无符号整型,将-3的补码实际解读的时候
是按照无符号数来解读的,因为正数的 原码,反码,补码相同
所以将-3的补码当做原码解读,是一个很大的数
该数必定大于0 所以必定指向if里面的语句

strcpy

字符串拷贝函数

函数原型:char * strcpy ( char * destination, const char * source );

参数:char * destination, const char * source

将source指向的字符串复制到destination指向的数组中

包括终止字符'\0’也要赋值过去

返回值:char*  

返回的是sourec指向的那一片空间的地址

函数作用:将源头src指向字符串的内容赋值到目的地dest指向字符串中

 在赋值的时候会将字符'\0’也赋值过去

       为避免溢出,destination指向的数组的大小应足够长

以包含与source相同的字符串(包括终止空字符),

并且不应与source在内存中重叠。

函数的使用:看以下代码:

#include#includeint main()
{
	//将str2的内容拷贝到str1中
   //拷贝的时候会将'\0'也拷贝过去
  //str1的空间要足够大要装的下str2的内容!
	char str1[20] = "zzzzzzzzzzzzzz";
	char str2[] = "abcde";
	strcpy(str1, str2);
	printf("%s\n", str1);

	//将s2的内容拷贝到s1中
	//拷贝的时候会将'\0'也拷贝过去
	//s1的空间要足够大要装的大s2的内容
	char s1[] = "xxxxxxxxxx";
	char s2[] = "fghijk";
	strcpy(s1, s2);
	printf("%s\n", s1);

	//将p2指向的常量字符串的内容拷贝到p2中
	//拷贝的时候会将'\0'也拷贝过去
	//p1的空间要足够大要装的大p2的内容
	char p1[20] = "yyyyyyyyyyyyyyyyyy";
	char* p2 = "lmnopq";
	strcpy(p1, p2);
	printf("%s\n", p1);

	return 0;
}
strcat

字符串追加函数

函数原型:char * strcat ( char * destination, const char * source );

返回值:char*

返回的是追加完成之后

destination的首地址

参数:char * destination, const char * source

 destination是目的地字符串的首地址

 source 是源头字符串的首地址

函数作用:

将source指向的字符串内容

追加到destination指向的字符串后面

追加时:destination中的'\0'被source的第一个字符覆盖

destination指向的空间要足够大

要容纳下追加之后的新字符串

函数用途:看以下代码       

#include#includeint main()
{
	//将str2的内容追加到str1的后面
	//在追加的时候str1最后的‘\0’字符被str2的第一个字符覆盖
	//然后进行追加,追加时会将str2的'\0'也追加进去
	//str1的空间要足够大,要能容纳下追加后的新字符串
	char str1[50] = "abcdefg";
	char str2[] = "hijklmn";
	strcat(str1, str2);
	printf("%s\n", str1);

	//将p2指向的常量字符串内容追加到p1的后面
	//追加时p1的'\0'字符被p2的首字符覆盖
	//追加时会将p2的'\0'也追加进去
	//p1的空间要足够大,能容纳下追加后的新字符串
	char p1[20] = "abc";
	char* p2 = "defgk";
	strcat(p1, p2);
	printf("%s\n", p1);

	return 0;
}

 

strcmp

字符串比较函数

函数原型:int strcmp ( const char * str1, const char * str2 );

返回值:int

   返回的是一个有符号整型数

 可返回负数,0,正数

参数:const char * str1, const char * str2

 str1指向一个字符串,

 str1里面存放的是字符串的首地址

 用const修饰说明字符串的内容不可被修改

 str2也指向一个字符串,

 str2里面存放的是字符串的首地址

 用const修饰说明字符串的内容不可被修改

 

函数的作用:

     str1字符串与str2字符串从首字符的位置开始

     一个字符一个字符对应向后一一比较,

     在比较字符的时候比较的是其ASCII码值,

     若对应比较两个字符相等则一直向后比较,

     直到碰到字符不等的情况就停止比较,

     然后返回这两个不等字符的比较结果,

     当str1的字符大于str2的字符 则返回大于0的数字,

     若两个字符串比较完了,各字符都相同,

     且长度相等的情况下,则这两个字符串相等

     str1等于str2时返回0,

     str1的字符小于str2的字符时 返回小于0的数

函数用途:如下代码:

#include#includeint main()
{
	//字符串比较
	//str1 与 str2 进行比较
	//从首字符开始向后一一比较
	//在比较的时候比较的是字符的ASCII码值
	//若对应的字符相等,则继续向后比较
	//若不等,则停止比较,返回他们的比较结果
	//若两个字符串比较完都相等,且长度一样长,说明str2和str2相等
	//返回值:
	//第一个字符串大于第二个字符串,则返回大于0的数字
	//第一个字符串等于第二个字符串,则返回0
	//第一个字符串小于第二个字符串,则返回小于0的数字

	char str1[] = "abcde";
	char str2[] = "abcfk";
	int n = strcmp(str1, str2);
	if (n == 0)
	{
		printf("str1 == str2");
	}
	else if (n >0)
	{
		printf("str1 >str2");
	}
	else
	{
		printf("str1< str2");
	}

	return 0;
}

strncpy

字符串拷贝函数(指定字节数拷贝)

函数原型:char * strncpy ( char * destination, const char * source, size_t num );

返回值:char *

 返回的是一个char* 的指针

 返回的是拷贝完成后的destination指向的空间

参数:char * destination, const char * source, size_t num

 目的地字符串:

 destination 是指向一个字符串空间的指针

 源头字符串:

 soure是一个指向一个字符串空间的指针

 const修饰说明soure指向的字符串不可被修改

 num是一个sizt_t 无符号整型的数字

函数的作用:

     将soure指向的字符串中num个字节的内容

     复制到destination指向的字符串空间

     如果source指向的字符串的长度小于num,

     则拷贝完源字符串之后,在目标的后边追加0,

     直到追加够num个结束

     destination 指向的空间要足够大

     至少能容纳下拷贝后新的字符串

函数用途:如下代码:

#include#includeint main()
{
	//拷贝num个字符从源字符串到目标空间。
	//如果源字符串的长度小于num,则拷贝完源字符串之后,
	//在目标的后边追加0,直到num个

	char str1[] = "yyyyyyyyyyyyyyyyyyy";
	char str2[] = "hello";
	strncpy(str1, str2, 5);
	printf("%s\n", str1);

	//当s2的长度

strncat

字符串追加函数(指定字节数追加)

函数原型:char * strncat ( char * destination, const char * source, size_t num );

返回值:char *

  返回的是一个char*的指针

返回追加完成之后destination指向的空间

参数:char * destination, const char * source, size_t num

 目的地字符串:

 destination 是指向一个字符串空间的指针

 源头字符串:

 soure是一个指向一个字符串空间的指指针

 const修饰 说明soure指向的字符串不可被修改

 num是一个sizt_t 无符号整型的数字

函数的作用:

     将soure指向的字符串中num个字节的内容

  追加到destination指向的字符串空间

     destination指向字符串的最后的'\0'字符

     会被soure指向的字符串的首字符所覆盖

     如果source指向的字符串的长度大于num,

     则追加完num个字符之后,在后边自动加上'\0'

     如果source指向的字符串的长度小于num,

  则只追加完source指向的字符串内容(包含'\0’)

     就结束结束追加

     destination 指向的空间要足够大

     至少能容纳下追加后新的字符串

函数用途:如下代码:

#include#includeint main()
{
	//str2 大于 num 的情况
   //会自动在末尾加上'\0'
	//在追加的时候,str1的'\0'会被str2的首字符所覆盖
	char str1[50] = "uvwxy";
	char str2[] = "abcdefg";
	strncat(str1, str2, 5);
	printf("%s\n", str1);

	//str2 小于 num 的情况
	//只追加完str2包含'\0’字符就结束追加
	//在追加的时候,s1的'\0'会被s2的首字符所覆盖
	char s1[50] = "wasche";
	char s2[] = "hello world";
	strncat(s1, s2, 13);
	printf("%s\n", s1);

	return 0;
}

strncmp

字符串比较函数(指定字节数比较)

函数原型:int strncmp ( const char * str1, const char * str2, size_t num );

返回值:int

   返回的是一个有符号整型数

 可返回负数,0,正数

参数:const char * str1, const char * str2, size_t num

 str1指向一个字符串,

 str1里面存放的是字符串的首地址

 用const修饰说明字符串的内容不可被修改

 str2也指向一个字符串,

 str2里面存放的是字符串的首地址

 用const修饰说明字符串的内容不可被修改

 num是一个无符号整数,表示字节数

函数的作用:

  对str1和str2字符串,指定num个字节进行比较

     str1字符串与str2字符串从首字符的位置开始

  比较到num个字节结束

     一个字符一个字符对应向后一一比较,

     在比较字符的时候比较的是其ASCII码值,

     若对应比较两个字符相等则一直向后比较,

     直到碰到字符不等的情况就停止比较,

     然后返回这两个不等字符的比较结果,

     当str1的字符大于str2的字符 则返回大于0的数字,

     若两个字符串比较num个字节之后,

     各字符都相同,则这两个字符串相等

     str1等于str2时返回0,

     str1的字符小于str2的字符时 返回小于0的数

     若字符串的长度小于num,则比较完字符'\0'就结束比较

函数用途:如下代码:

#include#includeint main()
{
	char str1[] = "abcdefghijklm";
	char str2[] = "abcdefgxyz";
	//比较前六个字符是否相等
	int n = strncmp(str1, str2, 6);
	if (n == 0)
	{
		printf("str1 == str2\n");
	}
	else if (n >0)
	{
		printf("str1 >str2\n");
	}
	else
	{
		printf("str1< str2\n");
	}


	//比较前8个字符是否相等
	n = strncmp(str1, str2, 8);
	if (n == 0)
	{
		printf("str1 == str2\n");
	}
	else if (n >0)
	{
		printf("str1 >str2\n");
	}
	else
	{
		printf("str1< str2\n");
	}

	//比较前11个字符是否相等
	n = strncmp(str1, str2, 11);
	if (n == 0)
	{
		printf("str1 == str2\n");
	}
	else if (n >0)
	{
		printf("str1 >str2\n");
	}
	else
	{
		printf("str1< str2\n");
	}

	return 0;
}

strstr

字符串找子串函数

函数原型:char * strstr ( const char *str1, const char * str2);

返回值:char *

返回一个字符指针

 返回找到子串的首字符的地址

找不到返回NULL

参数:const char *str1, const char * str2

 str1指向一个字符串,

 str1里面存放的是字符串的首地址

 用const修饰说明字符串的内容不可被修改

 str2也指向一个字符串,

 str2里面存放的是字符串的首地址

 用const修饰说明字符串的内容不可被修改

函数的作用:

  寻找在str1指向的常量字符串里

     是否包含str2指向的字符串

     若包含则返回str2第一次出现的地址

     若不包含则返回NULL

函数用途:如下代码:

#include#includeint main()
{
	//查找str2是否是str1的子串
	//若是则返回str2第一次出现的位置
	//若不是则返回NULL
	char str1[] = "abcdefgjklcdefgmn";
	char str2[] = "cdef";
	char* p = strstr(str1, str2);
	if (p == NULL)
	{
		printf("str2 不是 str1 的子串\n");
	}
	else
	{
		printf("str2 是 str1 的子串\n");
		//用%s打印的时候会从str2在str1中第一次出现的位置开始,直到遇到'\0'结束
		printf("%s\n", p);
	}

	return 0;
}

strtok

字符串分割函数

函数原型:char * strtok ( char * str, const char * sep );

返回值:char *

  返回一个字符指针

  返回用分割符号分割后字符串的首地址

参数:char * str, const char * sep

str是一个指向要被分割的字符串的空间

sep指向的是分割符号的字符串空间

用const修饰说明sep指向的内容不可被修改

函数的作用:

sep里面传过来的是分隔符的字符串

在第一次调用的时候

str里面传过来的是要被分割字符串的首地址

在查找分隔符的时候会将分隔符的位置改为'\0'

在第二次调用的时候

str里面传入一个空指针,

此时查找分隔符的位置会在第一次分隔符的下一个字符开始查找

会找到下一个分隔符,再将分隔符的位置改为'\0‘

以此类推有几个分隔符就查找几次

sep参数是个字符串,定义了用作分隔符的字符集合
第一个参数指定一个字符串,

它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
strtok函数找到str中的下一个标记,

并将其用 \0 结尾,

返回一个指向这个标记的指针。

(注:
    strtok函数会改变被操作的字符串,

           所以在使用strtok函数切分的字符串

        一般都是临时拷贝的内容并且可修改。)
strtok函数的第一个参数不为 NULL ,

函数将找到str中第一个标记,

strtok函数将保存它在字符串中的位置。
strtok函数的第一个参数为 NULL ,

函数将在同一个字符串中被保存的位置开始,

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

函数用途:如下代码:

#include#includeint main()
{
	char str[] = "hello@world&string#strtok";//被分割的字符串
	char ep[] = "@&#";//分隔符字符串

	//第一次调用 会将找到的分割符的位置改为'\0'
	char* p = strtok(str, ep);
	printf("%s\n", p);

	//第二次调用传入空指针 会将找到的分割符的位置改为'\0'
	p = strtok(NULL, ep);
	printf("%s\n", p);

	//第三次调用也传入空指针 会将找到的分割符的位置改为'\0'
	p = strtok(NULL, ep);
	printf("%s\n", p);

	//第四次调用也传入NULL 会将找到的分割符的位置改为'\0'
	p = strtok(NULL, ep);
	printf("%s\n", p);


	上述我们打印分割的字符串总共调用了四次
	代码写的有点繁琐,我们可以用一个for循环直接调用打印
	//char* ret = NULL;
	//for (ret = strtok(str, ep);ret!=NULL; ret = strtok(NULL, ep))
	//{
	//	printf("%s\n", ret);
	//}

	return 0;
}

strerror

获取错误信息函数

函数原型:char * strerror ( int errnum );

返回值:char *

  返回一个字符指针

  返回的是错误信息是字符串

参数:int errnum

参数是一个整数

传入的是一个错误码

函数的作用:

  返回一个字符串,而这个字符串

  就是一串错误信息

  而参数是一个整数,是一个错误码

  每一个错误码都有一个对应的错误信息

函数用途:如下代码:

#include#include#includeint main()
{
	//随便传入一个错误码,打印出其错误信息
	printf("%s\n", strerror(12));

	//具体应用
	//FILE是一个文件指针,fopen是打开文件
	//在当前目录下打开text.txt文件进行读操作
	//若打开失败返回NULL
	FILE* pf = fopen("text.txt", "r");
	if (pf == NULL)
	{
		printf("打开失败错误信息为:%s",strerror(errno));
	}
	else
	{
		printf("打开成功\n");
	}

	return 0;
}

字符分类函数:

头文件包含:#include

iscntrl 

字符控制函数

函数原型:int iscntrl ( int c );

函数的作用:

  传入一个字符,

判断是否是控制字符

若是则返回非0数(也就是ture)

若不是则返回0(也就是false)

函数用途:

#include#includeint main()
{
	char c = 0;
	scanf("%c", &c);
	int ret = iscntrl(c);
	if (ret == 0)
	{
		printf("%c不是控制字符\n", c);
	}
	else
	{
		printf("%c 是控制字符\n", c);
	}

	return 0;
}
isspace

空白字符:‘空格’,‘\f’换页,'\n'换行,

     '\r'回车,制表符‘\t’,垂直制表符'\v'

函数原型:int isspace ( int c );

函数作用:

  传入一个字符,

判断是否是空白字符

若是则返回非0数(也就是ture)

若不是则返回0(也就是false)

函数用途:

#include#includeint main()
{
	//空白字符:‘空格’,‘\f’换页,'\n'换行,'\r'回车,制表符‘\t’,垂直制表符'\v'
	char c = '\n';
	int ret = iscntrl(c);
	if (ret == 0)
	{
		printf("%c不是空白字符\n", c);
	}
	else
	{
		printf("%c 是空白字符\n", c);
	}

	return 0;
}
isdigit

十进制数字0~9

函数原型:int isdigit ( int c );

函数作用:

  传入一个字符,

判断是否是0~9的字符

若是则返回非0数(也就是ture)

若不是则返回0(也就是false)

函数用途:

#include#includeint main()
{
	char c = 0;
	scanf("%c", &c);
	int ret = isdigit(c);
	if (ret == 0)
	{
		printf("%c不是0~9字符\n", c);
	}
	else
	{
		printf("%c 是0~9字符\n", c);
	}

	return 0;
}
isxdigit
十六进制数字,包括所有十进制数字,小写字母a~f,大写字母A~F

函数原型:int isdigit ( int c );

函数作用:

  传入一个字符,

判断是否是十六进制数

小写字母a~f,大写字母A~F的字符

若是则返回非0数(也就是ture)

若不是则返回0(也就是false)

函数用途:

#include#includeint main()
{
	char c = 0;
	scanf("%c", &c);
	int ret = isxdigit(c);
	if (ret == 0)
	{
		printf("%c NO is 十六进制\n", c);
	}
	else
	{
		printf("%c YES 十六进制\n", c);
	}

	return 0;
}
islower

小写字母:a~z

函数原型:int islower ( int c );

函数作用:

  传入一个字符,

判断是否是小写字母:a~z

若是则返回非0数(也就是ture)

若不是则返回0(也就是false)

函数用途:

#include#includeint main()
{
	char c = 0;
	scanf("%c", &c);
	int ret = islower(c);
	if (ret == 0)
	{
		printf("%c NO is 小写字母\n", c);
	}
	else
	{
		printf("%c YES 小写字母\n", c);
	}

	return 0;
}
isupper

大写字母A~Z

函数原型:int isupper ( int c );

函数作用:

  传入一个字符,

判断是否是大写字母:A~Z

若是则返回非0数(也就是ture)

若不是则返回0(也就是false)

函数用途:

#include#includeint main()
{
	char c = 0;
	scanf("%c", &c);
	int ret = isupper(c);
	if (ret == 0)
	{
		printf("%c NO is 大写字母\n", c);
	}
	else
	{
		printf("%c YES 大写字母\n", c);
	}

	return 0;
}
isalpha

字母a~z或者A~Z

函数原型:int isalpha ( int c );

函数作用:

  传入一个字符,

判断是否是大写或者小写字母

若是则返回非0数(也就是ture)

若不是则返回0(也就是false)

函数用途:

#include#includeint main()
{
	char c = 0;
	scanf("%c", &c);
	int ret = isalpha(c);
	if (ret == 0)
	{
		printf("%c NO is 字母\n", c);
	}
	else
	{
		printf("%c YES 字母\n", c);
	}

	return 0;
}
isalnum

字母或者数字,A~Z ,a~z,0~9

函数原型:int isalnum ( int c );

函数作用:

  传入一个字符,

判断是否是

大写或者小写字母或者是数字字符

若是则返回非0数(也就是ture)

若不是则返回0(也就是false)

函数用途:

#include#includeint main()
{
	char c = 0;
	scanf("%c", &c);
	int ret = isalnum(c);
	if (ret == 0)
	{
		printf("%c NO is 字母或数字\n", c);
	}
	else
	{
		printf("%c YES 字母或数字\n", c);
	}

	return 0;
}
ispunct

标点符号,任何不属于数字或者字母的图形字符(可打印)

函数原型:int ispunct ( int c );

函数作用:

  传入一个字符,

判断是否是

  不属于数字或者字母的图形字符

若是则返回非0数(也就是ture)

若不是则返回0(也就是false)

函数用途:

#include#includeint main()
{
	char c = 0;
	scanf("%c", &c);
	int ret = ispunct(c);
	if (ret == 0)
	{
		printf("%c NO is 它属于数字或字母\n", c);
	}
	else
	{
		printf("%c YES  它不属于字母或数字\n", c);
	}

	return 0;
}
isgraph

任何图形字符

函数原型:int isgraph ( int c );

函数作用:

  传入一个字符,

判断是否是图形字符

若是则返回非0数(也就是ture)

若不是则返回0(也就是false)

函数用途:

#include#includeint main()
{
	char c = 0;
	scanf("%c", &c);
	int ret = isgraph(c);
	if (ret == 0)
	{
		printf("%c NO is 它不是图形字符\n", c);
	}
	else
	{
		printf("%c YES  它是图形字符\n", c);
	}

	return 0;
}
isprint

任何可打印字符,包括图形字符和空白字符

函数原型:int isprint ( int c );

函数作用:

  传入一个字符,

判断是否是可打印的字符

  包含图形字符和空白字符

若是则返回非0数(也就是ture)

若不是则返回0(也就是false)

函数用途:

#include#includeint main()
{
	char c = 0;
	scanf("%c", &c);
	int ret = isprint(c);
	if (ret == 0)
	{
		printf("%c NO is 它不是可打印的字符\n", c);
	}
	else
	{
		printf("%c YES  它是可打印的字符\n", c);
	}

	return 0;
}
tolower

字母大写转小写

函数原型:int tolower ( int c );

函数作用:

  传入一个字符,

判断是否是大写字母A~Z

  若是将其转为对应小写字母

函数用途:

#include#include#includeint main()
{
	//将字符串的大写字母全部转为小写字母
	char str[] = "abcDEfGjK";
	int i = 0;
	for (i = 0; i< strlen(str); i++)
	{
		if (isupper(str[i])!=0)//判断是否是大写字母
		{
			str[i] = tolower(str[i]);//大写转小写
		}
	}
	printf("%s\n", str);

	return 0;
}
toupper

字母小写转大写

函数原型:int toupper ( int c );

函数作用:

  传入一个字符,

判断是否是小写字母a~z

  若是将其转为对应大写字母

函数用途:

#include#include#includeint main()
{
	//将字符串的小写字母全部转为大写字母
	char str[] = "abcDEfGjK";
	int i = 0;
	for (i = 0; i< strlen(str); i++)
	{
		if (islower(str[i])!=0)//判断是否是小写字母
		{
			str[i] = toupper(str[i]);//小写转大写
		}
	}
	printf("%s\n", str);

	return 0;
}

内存函数:
memcpy

内存拷贝函数

函数原型:void * memcpy ( void * destination, const void * source, size_t num );

返回值:void *

  返回值是一个任意类型的指针

 返回拷贝好的内存空间的起始地址

参数:void * destination, const void * source, size_t num

目的地:

destination是一个任意类型的指针

源头:

source是一个任意类型的指针

  用const修饰,

说明source指向的内存空间的内容不可修改

字节数:

num是一个无符号整型

函数的作用:

将source 指向的空间

里面的num个字节的数据

复制到destination指向的空间中

返回值,返回的是:

拷贝好之后 destination指向的空间的地址

  destination指向的内存空间要足够大

  至少能容纳下拷贝之后的数据

  这个函数遇到'\0'时根本就不会停下来

  直到拷贝够num字节数就停止

  memcpy函数不能胜任重叠拷贝

  自己拷贝自己

函数用途:如下代码:

#include#include// 定义结构体
struct {
	char name[40];
	int age;
} person, person_copy;
//创建结构体全局变量 person,和 per_copy

int main()
{
	char myname[] = "Pierre de Fermat";
	//创建一个字符串
	
	//将myname整个字符串的内容,拷贝到结构体变量person 的成员变量 name 空间中
	memcpy(person.name, myname, strlen(myname) + 1);
	//再给变量person的成员变量 age 赋值为46
	person.age = 46;

	//将变量person 的空间的内容,全部拷贝 到变量 person_copy的空间中
	memcpy(&person_copy, &person, sizeof(person));
	//将变量 person_copy 空间中的内容打印出来 
	printf("person_copy: %s, %d \n", person_copy.name, person_copy.age);

	return 0;
}

memmove

内存拷贝函数(指定字节数)

函数原型:void * memmove ( void * destination, const void * source, size_t num );

返回值:void *

  返回值是一个任意类型的指针

 返回拷贝好的内存空间的起始地址

参数:void * destination, const void * source, size_t num

目的地:

destination是一个任意类型的指针

源头:

source是一个任意类型的指针

  用const修饰,

说明source指向的内存空间的内容不可修改

字节数:

num是一个无符号整型

函数的作用:

将source 指向的空间

里面的num个字节的数据

复制到destination指向的空间中

返回值,返回的是:

拷贝好之后 destination指向的空间的地址

  destination指向的内存空间要足够大

  至少能容纳下拷贝之后的数据

  这个函数遇到'\0'时根本就不会停下来

  直到拷贝够num字节数就停止

  memmove函数可以胜任重叠拷贝

  自己可以拷贝自己

函数用途:如下代码:

#include#includeint main()
{
	//创建字符串数组并初始化
	char str[] = "memmove can be very useful......";

	//str+20 取到的是字符u的地址
	//str+15 取到的是字符v的地址
	//从v字符还是往后拷贝11个字节的数据到 str+20的位置
	//自己拷贝自己 重叠拷贝
	memmove(str + 20, str + 15, 11);

	//打印重叠拷贝后的str
	puts(str);

	return 0;
}

memcmp

内存比较函数

函数原型:int memcmp ( const void * ptr1,const void * ptr2,size_t num );

返回值:int

返回一个有符号整数

返回小于0的数

返回等于0的数

返回大于0的数

参数:const void * ptr1,const void * ptr2,size_t num

目的地:

ptr1指向任意类型的一块内存空间

用const修饰

说明ptr1指向的空间的内容不可被修改

源头:

ptr2指向任意类型的一块内存空间

用const修饰

说明ptr2指向的空间的内容不可被修改

num是一个无符号整型

表示字节个数

函数作用:

从ptr1和ptr2分别指向空间首地址开始

一个字节一个字节,一一对应进行比较

比较num个字节,

当ptr1大于ptr2返回大于0的数

当ptr1等于ptr2返回数字0

当ptr1小于ptr2返回小于0的数

函数用途:如下代码:

#include#includeint main()
{
	//创建两个字符串
	char buffer1[] = "DWgaOtP12df0";
	char buffer2[] = "DWGAOTP12DF0";

	//将buffer1 跟 buffer2 的 前sizeof(buffer1) 个字节 进行比较
	//一个字节 一个字节 往后一一比较 要是相同往后继续比较
	//只要遇到不等的字节 就停止比较,返回这两个字节比较的结果
	//buffer1 大于 buffer2 返回大于0的数字
	//buffer1 等于 buffer2 返回数字0
	//buffer1 小于 buffer2 返回小于0的数
	int n = 0;
	n = memcmp(buffer1, buffer2, sizeof(buffer1));

	if (n >0) 
		printf("'%s' is greater than '%s'.\n", buffer1, buffer2);
	else if (n< 0) 
		printf("'%s' is less than '%s'.\n", buffer1, buffer2);
	else
		printf("'%s' is the same as '%s'.\n", buffer1, buffer2);

	return 0;
}

memset

内存填充函数

函数原型:void * memset ( void * ptr, int value, size_t num );

返回值:void *

 返回任意类型的指针

 返回被修改后的内存空间的地址

参数:void * ptr, int value, size_t num

ptr是一个任意类型的指针

指向一片任意类型的空间

value是一个有符号整型

表示要修改的值

num是一个无符号整型

表示要修改的字节数

函数作用:

将ptr指向的内存块

  前num个字节的内容设置为value

  从ptr的位置开始向后num个字节

  的内容修改成value

函数用途:如下代码

#include#includeint main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	//数组名表示数组首元素地址
	//将arr指向的内存块的前20个字节,每个字节的内容都设置为0
	memset(arr, 0, 20);
	int i = 0;
	for (i = 0; i< sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");

	char str[] = "xxxxxxxxx";
	//将str指向的内存块的前5个字节,每个字节的内容都设置为'a’
	memset(str, 'a', 5);
	printf("%s\n", str);

	return 0;
}

库函数的模拟实现
模拟实现strlen

函数原型:size_t strlen(const char* str);

原理:strlen函数是计算字符串的长度

 也就是计算'\0'之前的字符的个数

模拟实现:

实现1:

#includesize_t my_strlen(const char* str)
{
	size_t count = 0;
	while (*str != '\0')
	{
		count++;
		str++;
	}
	return count;
}
int main()
{
	char str[] = "abcdefgh";
	size_t len = my_strlen(str);
	printf("%d\n", len);

	return 0;
}

实现2:

#include//递归方式实现
size_t my_strlen(const char* str)
{
	if (*str != '\0')
	{
		return 1 + my_strlen(str+1);
	}
	return 0;
}

int main()
{
	char str[] = "abcdefgh";
	size_t len = my_strlen(str);
	printf("%d\n", len);

	return 0;
}

实现3:

#includesize_t my_strlen(const char* str)
{
	char* p = str;
	while (*str++);
	return str - p - 1;
}
int main()
{
	char str[] = "abcdefgh";
	size_t len = my_strlen(str);
	printf("%d\n", len);

	return 0;
}

模拟实现strcpy

函数原型:char * strcpy ( char * destination, const char * source );

原理:strcpy就是将source指向空间的内容

 复制到destination指向的空间里

 在复制的同时会将source的'\0'也复制过去

 复制完成后将str1返回

模拟实现:

#include#include 

//模拟实现strcpy
char* my_strcpy(char* str1, const char* str2)
{
	assert(str1 && str2);
	char* p = str1;
	while (*str1++ = *str2++);

	return p;
}

int main()
{
	char str1[50] = "xxxxxxxxxxxxxxxxxxxx";
	char str2[] = "abcdefg";
	
	//将str2的内容赋值到str1中
	//str1的空间要足够大
	my_strcpy(str1, str2);
	printf("%s\n", str1);

	return 0;
}

模拟实现strcat

函数原型:char * strcat ( char * destination, const char * source );

原理:将source指向的字符串的内容

 追加到destination指向的字符串的后面

 追加的时候destination字符串的'\0'字符

 会被source字符串的首字符覆盖

 且会将source字符串的'\0'也追加上来

 且返回追加完成后的destination

模拟实现;

#include#include 

//模拟实现 strcat
char* my_strcat(char* dest, const char* src)
{
	assert(dest && src);
	char* p = dest;
	while (*dest)
	{
		dest++;
	}
	while ((*dest++ = *src++));

	return p;
}

int main()
{
	char str1[50] = "abcdef";
	char str2[] = "ghijklmn";

	//将str2字符串的内容追加到str1后面
	//在追加的时候会将str1字符串的'\0'覆盖掉
	my_strcat(str1, str2);
	printf("%s\n", str1);

	return 0;
}

模拟实现strstr

函数原型:const char * strstr ( const char * str1, const char * str2 );

原理:寻找str1这个字符串中是否包含str2字符串

若是包含则返回str2第一次出现的位置

否则返回NULL

也就是判断str2是否是str1的子串

模拟实现:

#include#include 

//模拟实现strstr函数
char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);
	char* p = (char*)str1;
	char* s1 = NULL;
	char* s2 = NULL;
	if (*str2 == '\0')
	{
		return (char*)str1;
	}
	while (*p)
	{
		s1 = p;
		s2 = (char*)str2;
		while (*s1 && *s2 && !(*s1 - *s2))
		{
			s1++;
			s2++;
		}
		if (!*s2)
		{
			return p;
		}
		p++;
	}
	return NULL;
}

int main()
{
	char str1[] = "kkkabcdefghijklmnabcdefgxyz";
	char str2[] = "abcdef";

	//查找str2是否是str1的子串
	//若是返回str2第一次出现的位置
	//不是则返回NULL
	char* p = my_strstr(str1, str2);
	if (p == NULL)
	{
		printf("不是子串\n");
	}
	else
	{
		printf("是子串\n");
		printf("从返回的地址处开始打印:%s\n", p);
	}

	return 0;
}

模拟实现strcmp

函数原型:int strcmp ( const char * str1, const char * str2 );

原理: 让str1字符串与str2字符串

 从首字符开始一个字符一个字符向后比较

 若两个字符相等则继续向后比较

 直到出现两个字符不等的情况下停止比较

 并且返回这两个不同字符比较的结果

 若str1大于str2返回大于0的数

 若str1等于str2返回等于0的数

 若str1小于str2返回小于0的数

模拟实现:

#include#include 

//模拟实现strcmp函数
int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 && str2);

	while (*str1 && *str2)
	{
		if (*str1 == *str2)
		{
			str1++;
			str2++;
		}
		else
		{
			return (*str1 - *str2);
		}
	}

	return (*str1 - *str2);
}

int main()
{
	char str1[] = "abcdefg";
	char str2[] = "abcdhjk";

	int ret = my_strcmp(str1, str2);
	if (ret == 0)
	{
		printf("str1 = str2\n");
	}
	else if (ret >0)
	{
		printf("str1 >str2\n");
	}
	else
	{
		printf("str1< str2\n");
	}
	return 0;
}

模拟实现memcpy

函数原型:void * memcpy ( void * destination, const void * source, size_t num );

原理:将source指向的内存块中

 num个字节的内容复制到

 destination指向的内存块中

 返回复制完成后的destination

一般情况下不能胜任重叠拷贝

也就是自己拷贝自己

模拟实现:

#include#include 

//模拟实现memcpy
void* my_memcpy(void* dest, void* src, size_t num)
{
	assert(dest && src);
	void* p = dest;
	while (num--)
	{
		*(char*)dest = *(char*)src;
		++(char*)dest;
		++(char*)src;
	}
	return p;
}

int main()
{
	//拷贝整型
	int arr[] = { 1,2,3,4,5 };
	int brr[] = { 6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	my_memcpy(arr,brr,8);
	int i = 0;
	for (i = 0; i< sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");

	//拷贝字符串
	char str1[] = "xxxxxxxxxx";
	char str2[] = "abcde";
	my_memcpy(str1, str2, 5);
	printf("%s\n", str1);

	return 0;
}

模拟实现memmove

函数原型:void * memmove ( void * destination, const void * source, size_t num );

原理:将source指向的内存块中

 num个字节的内容复制到

 destination指向的内存块中

 返回复制完成后的destination

 完全胜任重叠拷贝

 可以自己拷贝自己

模拟实现:

#include#include 

//模拟实现,memmove
//可实现重叠拷贝
//当destsrc时从后向前
//当dest=src时从前向后 从后向前

void* my_memmove(void* dest, void* src, size_t num)
{
	void* p = dest;
	assert(dest && src);
	if (dest >src)
	{
		dest = (char*)dest + num-1;
		src = (char*)src + num-1;
		while (num--)
		{
			*(char*)dest = *(char*)src;
			dest=(char*)dest-1;
			src=(char*)src-1;
		}
	}
	else
	{
		while (num--)
		{
			*(char*)dest = *(char*)src;
			++(char*)dest;
			++(char*)src;
		}
	}
	return p;
}

int main()
{
	//拷贝整型
	int arr[] = { 6,7,8,9,10 };
	int brr[] = { 1,2,3,4,5 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	my_memmove(arr, brr, 12);
	int i = 0;
	for (i = 0; i< sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");

	//拷贝字符串
	char str1[] = "yyyyyyyyyy";
	char str2[] = "abcdef";
	my_memmove(str1, str2, 4);
	printf("%s\n", str1);

	//重叠拷贝
	int prr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int s = sizeof(prr) / sizeof(prr[0]);
	my_memmove(prr + 5, prr, 12);
	int j = 0;
	for (j = 0; j< s; j++)
	{
		printf("%d ", prr[j]);
	}
	return 0;
}

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


分享文章:字符串+内存函数(C语言)-创新互联
本文路径:http://myzitong.com/article/dgidgo.html