重点介绍处理字符和字符串的库函数的使用和注意事项
下面是将要介绍的几个函数:
前面我们学习的那些库函数strcpy、strcat、strcmp等等都是对字符串进行操作的,因此当我们对数组进行操作的时候就不太适用了,接下来我们将要学习内存操作函数对数组里例如整形的类型数据进行操作。
void * memcpy ( void * destination, const void * source, size_t num );
例题1
#define _CRT_SECURE_NO_WARNINGS
#include
#include
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[8] = { 0 };
memcpy(arr2, arr1, 20);//将arr1中前5个数据拷贝到arr2中
return 0;
}
调试分析:
#include
#include
void test2()
{
float arr1[] = { 1.0,2.0,3.0,4.0,5.0 };
float arr2[10] = { 0 };
//把arr1的内容拷贝到arr2里面来
memcpy(arr2, arr1, 12);
}
int main()
{
test2();
return 0;
}
调试分析:
因此我们看到memcpy是根据内存进行拷贝的不考虑类型,只是将从source的位置开始向后复制num个字节的数据到destination的内存位置。
如果source和destination有任何的重叠,复制的结果都是未定义的。
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
void* my_memcpy(void* dest, const void* src, size_t num)
{
void* start = dest;
assert(dest && src);
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return start;
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
my_memcpy(arr1+2, arr1, 20);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
输出结果:
原因是:
所以我们发现,在内存重叠重叠的时候,使用memcpy可能出现意想不到的效果,因此出现内存重叠的时候,我们要使用memmove
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
void* my_memcpy(void* dest, const void* src, size_t num)
{
void* start = dest;
assert(dest && src);
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return start;
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[8] = { 0 };
my_memcpy(arr2, arr1, 20);
return 0;
}
调试结果:
关于涉及到的类型void
void*是通用类型的指针,可以接受任意类型的地址。但是这类指针不能直接进行解引用和+-运算
memcpy 函数的设计者不知道未来程序员使用memcpy拷贝什么类型的数据,因此使用void* 来设计这个函数。同时,之所以用void*是因为我们要根据自己的需求来对类型进行调整,同时类型的调整也影响了复制num字节的包含个数。
void * memmove ( void* destination, const void * source, size_t num );
#define _CRT_SECURE_NO_WARNINGS
#include
#include
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
memmove(arr1+2, arr1, 20);
for (int i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
输出结果:
我们尤其自己实现的时候在重叠拷贝的时候,怎么样去避免像上面memcpy中的要被拷贝的部分却没有发生拷贝呢?如果我们尝试从后往前来避免被覆盖拷贝呢?(把蓝色往红色里面拷贝)
拷贝情况有哪几种呢?因此在我们考虑下,有如下三种情况:
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
void my_memmove(void* dest, const void* src, size_t num)
{
char* start = dest;
assert(dest && src);
if (dest < src)
{
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{
while (num--)
{
*((char*)dest + num) = *((char*)src + num);
}
}
return start;
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
my_memmove(arr1 + 2, arr1, 20);
for (int i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
注意:
在C语言中,memcpy 用来拷贝不重叠的部分,重叠的部分交给 memove来做。
但是两者对拷贝的完成应该是memmove>memcpy,memmove能完成100分,但memcpy只能完成60分,而在vs环境下比较特殊,两者都能完成100分!(这里可以把代码进行复制,用vs的环境和库函数进行验证即可)
#define _CRT_SECURE_NO_WARNINGS
#include
#include
int main()
{
int arr1[] = { 1,2,3,4,5 };//01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00
int arr2[] = { 1,2,3,4,6 };//01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 06 00 00 00
printf("%d\n", memcmp(arr1, arr2, 16));
printf("%d\n", memcmp(arr1, arr2, 17));
return 0;
}
void* memset(void* ptr, int value, size_t num);
将ptr指向的内存块的前num个字节设置为指定值(解释为无符号字符)注意是以字节为单位的来进行设置
数组
#define _CRT_SECURE_NO_WARNINGS
#include
#include
int main()
{
char arr[] = "hello world";
memset(arr, 'x', 6);
printf("%s\n", arr);
return 0;
}
输出结果:
注意是以字节为单位的来进行设置因此我们想将数组的内容全设置为1(这里把每个字节都设置为1),则不可以实现(虽然char类型的数组可以,但还是避免使用)
#define _CRT_SECURE_NO_WARNINGS
#include
#include
int main()
{
int arr[10] = { 0 };//01 01 01 01 01 01 01 01...
memset(arr,1, sizeof(arr));
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%p ", arr[i]);
}
return 0;
}
输出结果
以上的都是对字符串进行操作的函数,接下来我们将介绍关于字符分类的函数。
以下函数的头文件为
函数 | 如果他的参数符合下列条件就返回真 |
iscntrl | 任何控制字符 |
isspace | 空白字符:空格‘ ’,换页‘\f’,换行'\n',回车‘\r’,制表符'\t'或者垂直制表符'\v' |
isdigit | 十进制数字 0~9 |
isxdigit | 十六进制数字,包括所有十进制数字,小写字母a~f,大写字母A~F |
islower | 小写字母a~z |
isupper | 大写字母A~Z |
isalpha | 字母a~z或A~Z |
isalnum | 字母或者数字,a~z,A~Z,0~9 |
ispunct | 标点符号,任何不属于数字或者字母的图形字符(可打印) |
isgraph | 任何图形字符 |
isprint | 任何可打印字符,包括图形字符和空白字符 |
#define _CRT_SECURE_NO_WARNINGS
#include
#include
int main()
{
printf("%d\n", isdigit('x'));
printf("%d\n", isdigit('6'));
printf("%d\n", isspace('x'));
printf("%d\n", isspace(' '));
printf("%d\n", islower('x'));
printf("%d\n", islower('X'));
return 0;
}
输出结果:
int tolower ( int c );
int toupper ( int c );
#define _CRT_SECURE_NO_WARNINGS
#include
#include
int main()
{
printf("%c\n", tolower('X'));
printf("%c\n", toupper('x'));
return 0;
}
输出结果:
#define _CRT_SECURE_NO_WARNINGS
#include
#include
int main()
{
char arr[20] = { 0 };
gets(arr); //接收字符串
int i = 0;
while (arr[i])
{
if (isupper(arr[i]))
{
arr[i] = tolower(arr[i]);
}
printf("%c", arr[i]);
i++;
}
return 0;
}
输出结果
(本节完)