目录
前言
一、函数介绍
1.strtok
2.strerror
3.perror
4.字符分类函数
5.memcmp
6.memcpy
7.memmove
8.memset
二、函数模拟实现
1.memmove
2.memcpy
总结
前言
接着上一篇博客的内容,我们接着了解剩下的字符串函数,这些函数的内部细节十分有趣
那么我们继续吧。
这个函数是用来切分字符串的,它会改变被切割的字符串
const char *strDelimit这个指针指向的字符串中的字符作为分界符,将strToken切分成一个一个子串;如果strToken为空指针NULL,则函数保存的指针在下一次调用中将作为起始位置strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注: strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容 并且可修改。) strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串 中的位置。 strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。如果字符串中不存在更多的标记,则返回 NULL 指针。
例:
#include
#include
int main()
{
char arr1[] = "wddqdeqd@swujswusuw%nxwnxwuxi&iujiu";
char arr2[] = "@%&";
char arr3[100] = { 0 };
memcpy(arr3, arr1, strlen(arr1));//避免strtok修改原字符串
printf("%s\n", strtok(arr3, arr2));
printf("%s\n", strtok(NULL, arr2));
printf("%s\n", strtok(NULL, arr2));
return 0;
}
我们发现字符串在我们指定的位置断开了。
strrerror这个函数返回错误码所对应的错误信息,我们在使用时必须引入errno(错误码),errno是一个全局变量。我们要包含头文件#include
下面是代码示例:
#include
#include
#include
int main()
{
printf("%s\n", strerror(0));
printf("%s\n", strerror(1));
printf("%s\n", strerror(2));
return 0;
}
我们发现不同的错误码对应着不同的含义。
看到这里我们会感觉strerror这个函数每次被调用完还要打印十分麻烦,这时就要引出perror这个函数。
这个函数相较于strerror简化了打印这步,我们还拿上面的代码演示,在代码中加入perror这个函数
#include
#include
#include
int main()
{
printf("%s\n", strerror(0));
//printf("%s\n", strerror(1));
//printf("%s\n", strerror(2));
perror(0);
return 0;
}
打印出来的·内容一样。
函数 | 如果参数符合下列条件就返回真 |
---|---|
iscntrl | 任何控制字符 |
isspace | 空白字符:空格’ ‘换页'\f'换行'\n'回车'\r'制表符'\t'或者垂直制表符'\v' |
isdigit | 十进制数字0-9 |
isxdigit | 十六进制数字,十进制数字小写字母,大写字母 |
islower | 小写字母a-z |
isupper | 大写字母A-Z |
isalpha | 字母a-z或A-Z |
isalnum | 字母或数字a-z,A-Z,0-9 |
ispunct | 标点符号,任何不属于数字或者字母的圆形字符(可打印) |
isgraph | 任何图形字符 |
isprint | 任何可打印字符,包括图形字符和空白字符 |
字符分类函数是一个大的分类,这些函数的具体细节大体相同,
我们只要以isupper函数为例
这个函数将小写字母转换为大写字母,如果成功调用就返回真值
#include
#include
#include
int main()
{
const char* arr = "AUIEWFDUH11232nnnn,,mnnbbb";
int len = strlen(arr);
for (int i = 0; i < len; i++)
{
if (isupper(arr[i]))
{
printf("%c", arr[i]);
}
}
return 0;
}
这串代码用来找出字符串中的大写字母
接下来,我们来到了内存操作函数
memcmp函数与strcmp函数类似,memcmp函数是比较buf1和buf2前的count个字节
#include
#include
int main()
{
char arr1[] = "0x1122334455";
char arr2[] = "0x1122334456";
printf("%d\n",memcmp(arr1, arr2, 11));
return 0;
}
我们比较前11个字节arr1与arr2是相同的,打印出来的应该是0
结果是-1证明arr1小于arr2
memcpy与strcpy函数类似:函数memcpy从src的位置开始向后复制count个字节的数据到dest的内存位置。 这个函数在遇到 '\0' 的时候并不会停下来。 如果src和dest有任何的重叠,复制的结果都是未定义的
演示:
#include
#include
int main()
{
char arr[] = "Hello World";
memcpy(arr, arr + 5, 5);
printf("%s", arr);
return 0;
}
同时要注意memcpy不会将'\0'复制过来
调用memcpy之后
memset函数内存设置,以字节为单位初始化内存单元,将每个字节都修改为指定值
我们可以通过这个函数快速初始化数组
#include
#include
int main()
{
char arr[5]={0};
memset(arr,'c', sizeof(arr)-1);
printf("%s", arr);
return 0;
}
注意字符串长度必须是sizeof(arr)-1,如果不是这样初始化,就会将字符串末尾的'\0'被替换成c导致数组越界。
#include
#include
void * my_memove(void* dest, const void* src, size_t count)
{
assert(dest && src);
if (count < 0)
return NULL;
char* ret = (char*)dest;
if (dest < src)
{
while (count--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{
while (count--)
{
*((char*)dest + count) = *((char*)src+count);
}
}
return ret;
}
int main()
{
char arr1[] = "Hello bit";
printf("%s", my_memove(arr1, arr1 + 7, 6));
char arr2[] = "********";
//my_memcpy(arr2, arr1, 5);
printf("%s", arr2);
return 0;
}
#include
#include
#include
void* my_memcpy(void* dest, const void* src, size_t count)
{
assert(dest && src);
int lenDest = strlen((char*)dest);
if (lenDest < count || count < 0)
return NULL;
void* ret = dest;
while (count--)
{
*((char*)dest) = *((char*)src);
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
int main()
{
char arr1[] = "Hello bit";
//printf("%s", my_memove(arr1, arr1 + 7, 6));
char arr2[] = "********";
my_memcpy(arr2, arr1, 5);
printf("%s", arr2);
return 0;
}