开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第4天,点击查看活动详情
前言
本文介绍一下C语言库函数中的一些字符函数和内存函数。
新手一个,水平比较低,还请包涵。
字符函数
所在头文件:<ctype.h>
字符分类函数
判断目标字符是不是对应类型的字符,是的话返回真。
| 函数 | 如果他的参数符合下列条件就返回真 |
|---|---|
| iscntrl | 任何控制字符 |
| isspace | 空白字符:空格‘ ’,换页‘\f’,换行'\n',回车‘\r’,制表符'\t'或者垂直制表符'\v' |
| isdigit | 十进制数字 0~9 |
| isxdigit | 十六进制数字,包括所有十进制数字,小写字母a |
| islower | 小写字母a~z |
| isupper | 大写字母A~Z |
| isalpha | 字母a |
| isalnum | 字母或者数字,a |
| ispunct | 标点符号,任何不属于数字或者字母的图形字符(可打印) |
| isgraph | 任何图形字符 |
| isprint | 任何可打印字符,包括图形字符和空白字符 |
字符转换函数
int tolower ( int c ); //把字符c变成大写字母字符
int toupper ( int c ); //把字符c变成小写字母字符
示例
内存函数
所在头文件:<string.h>
memcpy函数
相关描述
函数原型:void* memcpy (void* destination, const void* source, size_t num);
函数功能:内存拷贝(类同strcpy,而拷贝对象是内存)。
函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
这个函数在遇到 '\0' 的时候并不会停下来。 如果source和destination有任何的重叠,复制的结果都是未定义的。
void*泛型设计,使得各种数据类型通用。
注意:拷贝的应当是两块独立空间的内存,如果是在同一块内存空间上进行拷贝很有可能出错(交叉拷贝)。
参数说明:
目标空间
指向要在其中拷贝内容的目标空间的指针。
源
指向要拷贝的内存空间的指针。
数字
要从源复制的字节数。
size_t是无符号整数类型。
返回类型:void*
示例
#include <stdio.h> #include <string.h> struct { char name[40]; int age; } person, person_copy; int main () { char myname[] = "Pierre de Fermat"; memcpy ( person.name, myname, strlen(myname)+1 ); person.age = 46; memcpy ( &person_copy, &person, sizeof(person) ); printf ("person_copy: %s, %d \n", person_copy.name, person_copy.age ); return 0; }
模拟实现
void* MyMemcpy(void* dest, const void* src, size_t num)
{
assert(dest && src);
void* ret = dest;
while(num--)
{
*(char*)dest = *(char*)src;
(*char)dest++;
(*char)src++;
}
return ret;
}
memmove函数
相关描述
函数原型:void* memmove (void* destination, const void* source, size_t num);
函数功能:用来实现重叠内存之间的数据拷贝。
和memcpy类同,差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
如果源空间和目标空间出现重叠,就得使用memmove函数处理。
参数说明:
目标空间
指向要在其中复制内容的目标空间的指针
源
指向要复制的数据源的指针。
数字
要从源复制的字节数。
size_t是无符号整数类型。
返回类型:void*
示例
模拟实现
在实现memcpy时,我们拷贝数据是从前向后拷贝的,这样的话无法适应所有情况。
根据情况的不同,有时候需要从前向后拷贝数据,有时候则需要从后向前拷贝数据。
当指针dest在指针src前面且两指针指向空间有所重叠时,需要从前向后拷贝数据:
当指针dest在指针src后面且两指针指向空间有所重叠时,需要从后向前拷贝数据:
当两个指针指向的空间没有重叠部分时,从前向后还是从后向前拷贝都没关系:
基于上述分析,为了利于实现,这里就认为:只要dest小于src就从前向后拷贝,大于就从后向前拷贝。
代码
void* MyMemmove(void* dest, const void* src, size_t num)
{
assert(dest && src);
void* ret = dest;
while(num--)
{
if(dest < src)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
else
{
*((char*)dest + num) = *((char*)src + num);
}
}
return ret;
}
memcmp函数
相关描述
函数原型:int memcmp (const void* ptr1, const void* ptr2, size_t num);
函数功能:比较从ptr1和ptr2指针开始的num个字节的内容相不相等,类同strncmp。
返回值如下:
参数说明:
ptr1
指向内存块的指针。
ptr2
指向内存块的指针。
数字
要比较的字节数。
返回类型:int
示例
模拟实现
int MyMemcmp(const void* ptr1, const void* ptr2, size_t num)
{
assert(ptr1 && ptr2);
if (0 == num)
{
return 0;
}
while (--num && (*((char*)ptr1)++ == *((char*)ptr2)++));
return *(char*)ptr1 - *(char*)ptr2;
}
memset函数
相关描述
函数原型:void* memset (void* ptr, int value, size_t num);
函数功能:填充内存块。
将ptr指针所指向的目标内存块的num个字节的内容全部用value填充。
返回值也是ptr的值。
参数说明:
ptr
指向要填充的内存块的指针。
value
要设置的值。该值作为int传递,但该函数使用此值的无符号char转换来填充内存块(因为一次填充的只有一个字节)。
num
要设置为该值的字节数。
size_t是无符号整数类型。
返回类型:void*
注意
填充是以字节为单位的,也就是把value的值填充到每一个字节的内容去。
所以想要填充char数组以外的数组的话结果可能会出乎意料。
常用用法示例
初始化数组为全0
char str[100]; memset(str,0,100);清空结构体或结构体数组为全0
typedef struct Stu { char name[20]; int cno; }Stu; int main() { Stu stu1; memset(&stu1, 0, sizeof(stu1)); Stu stu2[10]; //结构体数组 memset(&stu2, 0, sizeof(stu2)); }