字符函数和内存函数

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第4天,点击查看活动详情

前言

       本文介绍一下C语言库函数中的一些字符函数和内存函数。

       新手一个,水平比较低,还请包涵。

字符函数

所在头文件:<ctype.h>

字符分类函数

      判断目标字符是不是对应类型的字符,是的话返回真。

函数如果他的参数符合下列条件就返回真
iscntrl任何控制字符
isspace空白字符:空格‘ ’,换页‘\f’,换行'\n',回车‘\r’,制表符'\t'或者垂直制表符'\v'
isdigit十进制数字 0~9
isxdigit十六进制数字,包括所有十进制数字,小写字母af,大写字母AF
islower小写字母a~z
isupper大写字母A~Z
isalpha字母az或AZ
isalnum字母或者数字,az,AZ,0~9
ispunct标点符号,任何不属于数字或者字母的图形字符(可打印)
isgraph任何图形字符
isprint任何可打印字符,包括图形字符和空白字符

字符转换函数

int tolower ( int c ); //把字符c变成大写字母字符

int toupper ( int c ); //把字符c变成小写字母字符

示例

image.png

内存函数

所在头文件:<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;
}

image.png

模拟实现

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*

示例

image.png

模拟实现

        在实现memcpy时,我们拷贝数据是从前向后拷贝的,这样的话无法适应所有情况。

        根据情况的不同,有时候需要从前向后拷贝数据,有时候则需要从后向前拷贝数据。

        当指针dest在指针src前面且两指针指向空间有所重叠时,需要从前向后拷贝数据:

image.png

         当指针dest在指针src后面且两指针指向空间有所重叠时,需要从后向前拷贝数据:

image.png

        当两个指针指向的空间没有重叠部分时,从前向后还是从后向前拷贝都没关系:

image.png

        基于上述分析,为了利于实现,这里就认为:只要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。

返回值如下:

image.png

参数说明

        ptr1

                 指向内存块的指针。

        ptr2

                 指向内存块的指针。

        数字

                 要比较的字节数。

返回类型:int

示例

image.png

模拟实现

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数组以外的数组的话结果可能会出乎意料。         image.png

常用用法示例

        初始化数组为全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));
}