重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
目录
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
#include int main() { //创建一个数组 用来封装字符串 char str[] = "abcdefghjk"; //调用strlen函数,用一个size_t 无符号整型来接收 //将str数组名表示首元素地址,也就是字符串的首地址传过去 size_t len = strlen(str); //打印,从传过去的位置开始,遇到'\0'之前,字符的个数 printf("%u\n", len); return 0; } #include
#include 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
#include 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
#include 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
#include 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 是指向一个字符串空间的指针
源头字符串:
soure是一个指向一个字符串空间的指针
const修饰说明soure指向的字符串不可被修改
num是一个sizt_t 无符号整型的数字
函数的作用:
将soure指向的字符串中num个字节的内容
复制到destination指向的字符串空间
如果source指向的字符串的长度小于num,
则拷贝完源字符串之后,在目标的后边追加0,
直到追加够num个结束
destination 指向的空间要足够大
至少能容纳下拷贝后新的字符串
函数用途:如下代码:
#include
#include int 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
#include 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
#include 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
#include 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
#include 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
#include #include 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
iscntrl字符控制函数
函数原型:int iscntrl ( int c );
函数的作用:
传入一个字符,
判断是否是控制字符
若是则返回非0数(也就是ture)
若不是则返回0(也就是false)
函数用途:
isspace#include
#include 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; } 空白字符:‘空格’,‘\f’换页,'\n'换行,
'\r'回车,制表符‘\t’,垂直制表符'\v'
函数原型:int isspace ( int c );
函数作用:
传入一个字符,
判断是否是空白字符
若是则返回非0数(也就是ture)
若不是则返回0(也就是false)
函数用途:
#include
#include 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)
函数用途:
isxdigit#include
#include 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; }
十六进制数字,包括所有十进制数字,小写字母a~f,大写字母A~F 函数原型:int isdigit ( int c );
函数作用:
传入一个字符,
判断是否是十六进制数
小写字母a~f,大写字母A~F的字符
若是则返回非0数(也就是ture)
若不是则返回0(也就是false)
函数用途:
islower#include
#include 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; } 小写字母:a~z
函数原型:int islower ( int c );
函数作用:
传入一个字符,
判断是否是小写字母:a~z
若是则返回非0数(也就是ture)
若不是则返回0(也就是false)
函数用途:
isupper#include
#include 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; } 大写字母A~Z
函数原型:int isupper ( int c );
函数作用:
传入一个字符,
判断是否是大写字母:A~Z
若是则返回非0数(也就是ture)
若不是则返回0(也就是false)
函数用途:
isalpha#include
#include 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; } 字母a~z或者A~Z
函数原型:int isalpha ( int c );
函数作用:
传入一个字符,
判断是否是大写或者小写字母
若是则返回非0数(也就是ture)
若不是则返回0(也就是false)
函数用途:
isalnum#include
#include 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; } 字母或者数字,A~Z ,a~z,0~9
函数原型:int isalnum ( int c );
函数作用:
传入一个字符,
判断是否是
大写或者小写字母或者是数字字符
若是则返回非0数(也就是ture)
若不是则返回0(也就是false)
函数用途:
ispunct#include
#include 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; } 标点符号,任何不属于数字或者字母的图形字符(可打印)
函数原型:int ispunct ( int c );
函数作用:
传入一个字符,
判断是否是
不属于数字或者字母的图形字符
若是则返回非0数(也就是ture)
若不是则返回0(也就是false)
函数用途:
isgraph#include
#include 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; } 任何图形字符
函数原型:int isgraph ( int c );
函数作用:
传入一个字符,
判断是否是图形字符
若是则返回非0数(也就是ture)
若不是则返回0(也就是false)
函数用途:
isprint#include
#include 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; } 任何可打印字符,包括图形字符和空白字符
函数原型:int isprint ( int c );
函数作用:
传入一个字符,
判断是否是可打印的字符
包含图形字符和空白字符
若是则返回非0数(也就是ture)
若不是则返回0(也就是false)
函数用途:
tolower#include
#include 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; } 字母大写转小写
函数原型:int tolower ( int c );
函数作用:
传入一个字符,
判断是否是大写字母A~Z
若是将其转为对应小写字母
函数用途:
toupper#include
#include #include 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; } 字母小写转大写
函数原型:int toupper ( int c );
函数作用:
传入一个字符,
判断是否是小写字母a~z
若是将其转为对应大写字母
函数用途:
#include
#include #include 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
#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
#include 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
#include 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
#include 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
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
//递归方式实现 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
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
#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 //可实现重叠拷贝 //当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; }
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧