C语言中有许多有意思而且非常实用的内存函数,我们一起来看一下这些函数是怎么使用和实现的
strtok
这个函数应该是C语言中不常见到的一个函数,我给大家介绍介绍它的功能是什么,以及他是如何使用的。
char * strtok ( char * str, const char * delimiters );
这是这个函数的参数和返回类型,这个函数可以切割一个字符串,把一个字符串分成若干份,而切割的地方放入’\0’,这么说比较抽象,我用代码给大家演示
char arr[] = "jronggui@bitedu.com";
char buf[200] = { 0 };
strcpy(buf, arr);
const char* p = "@.";
char* str = strtok(buf, p);
printf("%s\n", str);
str = strtok(NULL, p);
printf("%s\n", str);
str = strtok(NULL, p);
printf("%s\n", str);
我们如果切割arr就会使arr字符数组发生变化,所以我们可以复制到buf数组中,而字符指针p中放的是分隔字符,只要遇到’@‘或者’.‘就会把它换成’\0’。第一次调用函数第一个参数传的是数组首元素的地址,第二个参数是存放标记字符的指针p,返回的是切割这个字符串的起始位置,这个函数会记住第一次遇见分隔字符后面的位置,方便下次调用的时候可以找到,同理第二次调用之后函数也会记住第三次调用的起始位置,一直到这个字符串真正结束,结束之后会返回空指针。
我们看一下这个代码的运行结果:
而这个代码是有缺陷的,如果这个字符数组很长,我们怎么知道有几个分隔符呢?所以我们需要改进一下
int main() {
char arr[] = "jronggui@bitedu.com";
char buf[200] = { 0 };
strcpy(buf, arr);
const char* p = "@.";
/*char* str = strtok(buf, p);
printf("%s\n", str);
str = strtok(NULL, p);
printf("%s\n", str);
str = strtok(NULL, p);
printf("%s\n", str);*/
char* str = NULL;
for (str = strtok(buf, p); str != NULL; str = strtok(NULL, p)) {
printf("%s\n", str);
}
return 0;
}
这样只要这个函数返回的不为空指针,那就一直打印。
strerror
这个函数的功能是把错误代码转换成信息,例如:
memcpy和memmove的区别
memcpy和memmove本质上都是复制一个空间内的元素到另一个空间,但是二者是有一些区别的,我们可以先看一下memcpy和memmove怎么使用的,然后我们可以模仿实现一下。
memcpy
void * memcpy ( void * destination, const void * source, size_t num );
这是memcpy函数的参数和返回类型,传进去两个指针分别给destination和source,还有一个size_t(unsigned int)类型的数字。
这个函数怎么用呢?就是把source这个指针指向的内容复制num个字节到起始位置为destination指向的空间内。
我们可以看一下代码:
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = {0};
memcpy(arr2, arr1, 20);
int i = 0;
for (i = 0; i < 10; i++) {
printf("%d ", arr2[i]);
}
这个函数我们也可以模拟实现一下:
#include <assert.h>
void* my_mecopy(void* dest, void* src, size_t num) {
void* ret = dest;
assert(dest);
assert(src);
while (num--) {
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
memmove
这个函数跟momcpy使用方式是一样的
//这是参数列表和返回值
void * memmove ( void * destination, const void * source, size_t num );
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = {0};
int i = 0;
memmove(arr2, arr1, 20);
for (i = 0; i < 10; i++) {
printf("%d ", arr2[i]);
}
区别
memcpy和memmove这两个函数看起来使用方式没有区别,而且都可以实现复制,但是真的是一样的吗?答案是否定的。
我们可以做一个小小的测试,让数组元素自己给自己复制,例如:
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = {0};
my_mecopy(arr1+2, arr1, 20);
int i = 0;
for (i = 0; i < 10; i++) {
printf("%d ", arr1[i]);
}
这个复制就出问题了,这个问题当然也是看编译器对函数的实现,有的会出错,而有的不会,这时候就要格外小心了。
而memmove用数组自己给自己复制的结果就不会出错了,我们看看代码:
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int i = 0;
memmove(arr1+2, arr1, 20);
for (i = 0; i < 10; i++) {
printf("%d ", arr1[i]);
}
return 0;
所以用的时候还是尽量用memmove就可以。
这是几个简单的库函数的使用和一些实现,希望对您有所帮助。