strtok函数的规则:
1.参数1是指定一个字符串,它包含0个或多个由参数2字符串中一个或多个分隔符分割的标记
2.参数2是个字符串,定义了用作分隔符的字符集合。
3.strtok函数找到参数1的下一个标记,并将其用\0结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可以修改。)
4.strtok函数的第一个参数不为NULL,函数将找到参数1中第一个标记,strtok将保存它在字符串中的位置
5.strtok函数的第一个参数为NULL,函数将在同一个字符串中被保存的位置开始,查找下一个标记
6.如果字符串中不存在更多的标记,则返回NULL指针。
结合下面的例子:
当执行strtok函数后,如下图:
实际上,我们切割时并不清楚需要切割几次,因此我们需要通过循环进行切割
分析:很明显,第一次打印abcd。第二次打印ef是因为,参数1为NULL,根据规则,它会从上一次保存的位置继续查找标记,第三次打印也是如此。
strerror是将错误码翻译成错误信息,返回错误信息的字符串的起始地址。
strerror里的参数是整形,上面是各种类型的错误信息。
C语言中使用库函数的时候,如果发生错误,会将错误码放在errno的变量中,errno是一个全局变量,可以直接使用的。如上图,我们暂时不用管别的,我们只需要知道strerror里的errno存放错误码即可。
这里,我们再简单介绍下另一个类似的函数perror。
perror函数是直接打印错误码所对应的错误信息。perror==printf+strerror。
我们简单修改下上面的代码,发现:perror里面的内容,是我们自定义的信息,在打印完我们的信息后,他会自动在后面补上:号然后加上错误信息。因此也可以知道,perror的好处就是比较方便,会自动识别错误信息。但是他也会自动打印出错误信息。
字符分类函数有如下:
因为每个函数的使用方式基本相同,我们就举一个来简单说明:
当我们使用上面的函数时,我们需用引用头文件<ctype.h>,如果函数内为真则返回不等于0的数,如果为假,则返回0。
字符转换函数有tolower和toupper。他们的返回值和参数都是int,即字符的ASCII值。如下图,如果参数是小写则转换成大写,如果是大写,则不变。
memcpy函数跟strcpy函数有相似之处,不过memcpy可以拷贝任何类型。mencpy的参数1是目标空间,参数2是原始空间,参数3是拷贝的个数,单位是字节,这里指的是把arr2的前5个元素拷贝到arr1中(因为一个整形是4个字节,5个就是20个字节)。
void* my_memcpy(void* dest, const void* src, size_t sz)
{
assert(dest && src);
while (sz--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
上方是memcpy的模拟实现。
如上图,如果我们想把前五个数(1,2,3,4,5),从第3个数开始的5个数(3,4,5,6,7)拷贝过去,我们希望得到的结果是{1,2,1,2,3,4,5,8,9,10}。可是最后的结果却不是。这是因为在拷贝的重叠部分被改变了。
前面的拷贝是不重叠内存的拷贝,可以用memcpy。如果是重叠内存的拷贝,可以用memmove函数。
memmove函数的返回值和参数与memcpy的一模一样,如上图,使用它就能达到我们所想要的结果。
void* my_memmove(void* dest, const void* src, size_t sz)
{
assert(dest && src);
void* ret = dest;
if (dest < src)
{
//前->后
int i = 0;
for (i = 0; i < sz; i++)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{
//后->前
while (sz--)
{
*((char*)dest + sz) = *((char*)src + sz);
}
}
return ret;
}
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
memmove(arr+2, arr, 20);
int i;
for (i = 0; i < 10; i++)
printf("%d ", arr[i]);
return 0;
}
上方是模拟memmove函数的实现。
分析: 当原始空间的地址大于目标空间地址时,我们需要从前往后拷贝原始字符串到目标空间。
否则,我们就需要从后往前进行拷贝,这样就不会因为重叠而导致结果达不到预期。while循环中,sz--,起初sz是20,进入循环内变成19,强转后的dest+sz刚好指向最后一个字节,就能从后往前进行拷贝。
memset函数是用来设置内存的,以字节为单位进行设置。如上图,参数1是起始地址,参数2是要设置的内容,参数3是设置的字节个数。
memcmp函数与strcmp函数类似,不过strcmp函数只能进行字符串的比较,memcmp是内存块的比较,可以比较任意类型的数据。如下图:
参数1和参数2与strcmp的一样,参数3指比较前n个字节个数的数据,因为int占4个字节,比较前3个元素,大小相同则返回0。
如上图,我们比较大小的时候,不能单纯比较数字,而要看他们在内存中是怎样的,这样才能得出正确结果。