字符串+内存函数(C语言)

目录

函数介绍:

字符串函数:

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

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

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

	return 0;
}

一道迷惑笔试题:

#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");
	}

//在判断的时候,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 <stdio.h>
#include <string.h>

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

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

int 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 是指向一个字符串空间的指针

           源头字符串:

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

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

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

函数的作用:

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

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

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

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

                直到追加够num个结束

                destination 指向的空间要足够大

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

函数用途:如下代码:

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

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

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

	//当s2的长度<num时
	char s1[] = "xxxxxxxxxxxxxxxxxxxxxx";
	char s2[] = "abcd";
	strncpy(s1, s2, 6);
	printf("%s\n", s1);

	char p1[20] = "zzzzzzzzzzzzzzzzzzz";
	char* p2 = "efgh";
	strncpy(p1, p2, 5);
	printf("%s\n", p1);

	return 0;
}

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

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

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

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

int 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 <stdio.h>
#include <string.h>
#include <errno.h>

int 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 <ctype.h>

iscntrl 

字符控制函数

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

函数的作用:

        传入一个字符,

        判断是否是控制字符

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

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

函数用途:

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

int 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 <stdio.h>
#include <ctype.h>

int 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 <stdio.h>
#include <ctype.h>

int 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 <stdio.h>
#include <ctype.h>

int 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 <stdio.h>
#include <ctype.h>

int 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 <stdio.h>
#include <ctype.h>

int 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 <stdio.h>
#include <ctype.h>
int 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 <stdio.h>
#include <ctype.h>
int 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 <stdio.h>
#include <ctype.h>
int 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 <stdio.h>
#include <ctype.h>
int 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 <stdio.h>
#include <ctype.h>
int 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 <stdio.h>
#include <ctype.h>
#include <string.h>

int 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 <stdio.h>
#include <ctype.h>
#include <string.h>

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

// 定义结构体
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 <stdio.h>
#include <string.h>
int 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 <stdio.h>
#include <string.h>
int 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 <stdio.h>
#include <string.h>

int 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:

#include <stdio.h>

size_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 <stdio.h>
//递归方式实现
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:

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

//模拟实现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 <stdio.h>
#include <assert.h>

//模拟实现 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 <stdio.h>
#include <assert.h>

//模拟实现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 <stdio.h>
#include <assert.h>

//模拟实现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 <stdio.h>
#include <assert.h>

//模拟实现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 <stdio.h>
#include <assert.h>

//模拟实现,memmove
//可实现重叠拷贝
//当dest<srt时从前向后
//当dest>src时从后向前
//当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;
}

  • 10
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值