强制类型转换是一种临时状态
后置++的优先级比强制类型转换的优先级要高(53)(01:40)
首先我们介绍
字符分类函数
字符函数有许多中,每一种函数对应识别一种字符,由于种类较多故不一一列举,如果遇到时不清楚对应字符则可以在官网上面查找。
字符分类函数的共同处是:向函数输入一个字符,如果该字符满足该函数的条件,就返回一个非零的整型数字,如果不满足,则返回0。
举例:
#include<ctype.h>
int main()
{
char ch1 = '2';
char ch2 = 'w';
int ret1 = isdigit(ch1);
int ret2 = isdigit(ch2);
printf("%d %d\n", ret1,ret2);
int ret3 = islower(ch1);
int ret4 = islower(ch2);
printf("%d %d\n", ret3, ret4);
return 0;
}
其中isdigit识别的字符是0~9的数字字符
isdigit识别的字符是字符a~w的小写形式。
字符转换函数
字符转换函数主要功能是转换大小写,包含两个函数tolower(大写转小写)和toupper(小写转大写)。
函数声明:
int tolower ( int c );
int toupper ( int c );`
示例:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<ctype.h>
int main()
{
char arr[20] = { 0 };
scanf("%s", arr);
int i = 0;
while (arr[i] != '\0')
{
if (isupper(arr[i]))
{
arr[i] = tolower(arr[i]);
}
printf("%c", arr[i]);
i++;
}
return 0;
}
其中我们在传参的时候参数类型是字符,该字符在经过整型提升后提升为整型,然后被函数接收。
最后实际效果如下:
内存操作函数
memcpy
memcpy与strcpy有何区别?
我们通过一个例子来说明:
我想将arr1的前五个元素拷贝到arr2中。
假如我们用strcpy,strcpy的声明为:char* strcpy(char*dest,const char*src)
,其接收的两个参数两个字符串的地址,而在我们讨论的这种情况下,拷贝的对象是两个整型数组,其指针类型与strcpy参数类型不同,导致其不能正常使用。假如函数接受了整型数组的地址,函数内部实现拷贝也是以字节为单位,(假设数据按照小端存储)整型数据1在内存中存储的形式为,
当函数拷贝完‘01’对应的字符后,下一个拷贝的内存数据是‘00’,循环跳出,停止拷贝,后续数据拷贝无法实现。
此时我们就应该要用到memcpy,这个函数不会碰到‘\0’就停止,只是单纯地将一组数据拷贝到另一组数据中。
memcpy声明:void * memcpy ( void * destination, const void * source, size_t num );
memcpy使用示例:
#include<memory.h>
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[20] = { 0 };
memcpy(arr2, arr1, 20);
return 0;
}
memcpy模拟实现
void* my_memcpy(void* dest, const void* src, size_t num)
{
void* ret = dest;
assert(dest && src);
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
这其中值得注意的是:
由于(char*)将数据类型强制类型转换的效果是临时的,所以我们不能将循环体结构内容
直接写成*(char*)dest++ = *(char*)src++;
因为在解引用操作之后dest/src类型又变成了void*,而void类型的数据是不能直接进行++或解引用的操作(因为void类型的指针指向对象的数据类型大小不确定,指针移动的单位长度不确定)
memmove
我们还是用例子来引入memmove
我们想将蓝色方框内的五个元素按顺序用绿色方框内的元素替换。这时如果使用memcpy的话,在拷贝1到3的位置时,原位置上的数据被改成了1,但是在循环走将到原来3的位置的数据拷贝到数字5的位置时,arr[2]的值已经被改成了1,故arr[4]的值就被改成了1,这与我们最初的想法arr[4]=3不符合。故此种条件下memcpy函数不适用。
因此我们创造了memmove函数,它被创建专门用来将一组数据中的某个区域内的元素拷贝到另一个区域。
memmove声明:void * memmove ( void * destination, const void * source, size_t num );
使用方法示例:
memmove模拟实现
void* my_memmove(void* dest, const void* src, size_t num)
{
void* ret = dest;
if (src > dest)
{
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{
while (num--)
{
*((char*)dest + num) = *((char*)src + num);
}
}
return ret;
}
我们memmove的思路是将其分两种情况,在红线之前使用从后向前拷贝的方法,红线之后使用从前向后拷贝的方法,这样就不会出现我们上面说到的重叠位置数据覆盖的情况。
memcmp
memcmp是内存比较函数,它与strcmp的实现逻辑十分相似
声明:int memcmp( const void *buf1, const void *buf2, size_t count );
该函数通过参数中所给的地址对内存内的两个数据进行以字节为单位的比较(其中count为比较的字节总数),若前者大于后者,返回一个大于0的数字,前者小于后者,返回一个小于0的数据,等于的话就返回0。
示例:
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[] = { 1,3 };
printf("%d\n", memcmp(arr1, arr2, 4));
printf("%d\n", memcmp(arr1, arr2, 8));
printf("%d\n", memcmp(arr2, arr1, 8));
return 0;
}
memset
void *memset( void *dest, int c, size_t count );
该函数的作用是完成对内存的重置,
其中dest是作用的内存数据的地址,c是重置后字节的数值,count是作用的字节长度
我们通过一个例子来理解它的具体效果
int main()
{
int arr1[10] = { 0 };
memset(arr1, 1, 20);
return 0;
}
该例中前20个字节都被memset函数改成了1(但是对应的每个元素并不是1,在此例中,前五个元素被改成了16843009(int)。
最后
字符函数到此为止就全部介绍完毕了,小编水平有限,只能是很浅的介绍,希望随着以后的学习,我能够将有些知识补充得更加完善。