目录
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#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://njwzjz.com/article/dgidgo.html