C语言的学习离不开各种库函数的运用,例如:字符串函数中的strlen、strcpy;内存函数中的memcpy、memmove……本文就常见的字符串函数与内存函数展开,介绍各函数的用法。
函数原型:size_t strlen ( const char * str );
strlen用于计算字符串长度,该函数接收一个地址,从该地址向后访问,直到遇到’\0’结束为止,计算’\0’之前的字符个数。
需要注意的是:
strlen的返回类型是size_t,是一个无符号整数。
例如:strlen(“abc”)-strlen(“abcdef”),表面上看上去结果是-3,但实际上两个无符号数相减的结果还是无法符号数,-3在内存中的补码是11111111 11111111 11111111 11111101,被视作无符号数的时候是一个很大的正数。
函数原型:char* strcpy(char * destination, const char * source );
strcpy用于将源字符串的内容,复制到目标字符串里,同时会将源字符串末尾的’\0’复制过去。
需要注意以下几点:
(1)源字符串必须以’\0’结束;
(2)目标字符串要有足够大的空间;
(3)目标字符串必须是可变的,例如常量字符串就不可以作为目标字符串,因为不能修改里面的内容。
函数原型:char * strcat ( char * destination, const char * source );
strcat找到目标字符串’\0’处,自该位置起,将源字符串(包括末尾的’\0’)附到目标字符串后。
需要注意以下几点:
(1)源字符串必须以’\0’结束;
(2)目标字符串要有足够大的空间;
(3)目标字符串必须是可变的,例如常量字符串就不可以作为目标字符串,因为不能修改里面的内容。
函数原型:int strcmp ( const char * str1, const char * str2 );
strcmp用于比较两个字符串的大小,产生三种结果:
返回值 | 含义 |
---|---|
<0 | str1 |
==0 | str1==str2 |
>0 | str1>str2 |
需要注意:
strcmp比较的是对应字符的大小,与字符串长度是无关的。
例如:strcmp(“ab”,“ASDWAEFGAG”),返回值是1。理由是:在比较第一个字符的时候,'a’的ASCII码值大于’A’的ASCII码值,因此就认为字符串"ab"大于字符串"ASDWAEFGAG"。
这一类字符串函数相较于先前的加入了控制字符个数的变量,使得这些字符串函数更加灵活。
函数原型:char * strncpy ( char * destination, const char * source, size_t num );
strncpy相较于strcpy,增加了size_t num,即需要拷贝的字符个数。该函数能够将源字符串中设定的位置开始,将num个字符拷贝到目标字符串设定的位置。
需要注意:
当拷贝的字符个数超过源字符串设定位置开始的字符长度,则会则会在剩余内存单元上放置’\0’,直至个数达到num个。
函数原型:char * strncat ( char * destination, const char * source, size_t num );
strncat相较于strcat,增加了size_t num,即需要拷贝的字符个数。该函数能够将源字符串自设定的位置开始,将num个字符拷贝到目标字符串后,并在最后附上’\0’。
需要注意:
1、若num的个数超过源字符串自设定的位置开始的字符个数,则会在附完字符串后,再在最后附上1个’\0’;
2、有时可能会有下述情况:
char arr1[30] = "hello\0xxxxxxx";
char arr2[] = "world";
strncat(arr1, arr2, 7);
printf("%s\n", arr1);
上述情况中,hello后面有一个’\0’,无论num是否超过了arr2的字符个数,都会在hello后面附上,再在最后补一个’\0’。
函数原型:int strncmp ( const char * str1, const char * str2, size_t num );
strncmp相较于strcmp,增加了size_t num,即需要比较的字符个数。该函数能够将源字符串与目标字符串自设定的位置开始,比较num个字符,产生的可能结果同strcmp。
函数原型:char *strstr( const char *string, const char *strCharSet );
strstr函数中,前一个参数为总串,后一个参数为子串,该函数查找总串中是否存在该子串,若存在则返回出现的第一个字符的地址,否则就返回NULL。
函数原型:char *strtok( char *strToken, const char *strDelimit );
strtok函数主要用于分割字符串,第一个参数是需要分割的字符串,其中包含了多个由分隔符分分隔的标记,第二个参数为分隔符的集合;
strtok在字符串中找到下一处标记,将该标记后的分隔符用’\0’代替,并返回一个指向该标记的指针(由于strtok会改变原字符串,因此建议事先临时拷贝一份字符串);
strtok第一个参数若不为NULL,则会寻找第一个标记,并保存该标记在字符串中的位置;若为NULL,则会从上次保存的地址开始,寻找下一处标记;若无法找到标记的时候,则会返回NULL。
分隔后的字符串可通过for循环来打印:
int main()
{
char arr[] = "[email protected]";
char* sep = "@.";
char* str = NULL;
for (str = strtok(arr, sep); str != NULL; str = strtok(NULL, sep))
{
printf("%s\n", str);
}
return 0;
}
函数原型:char *strerror( int errnum );
strerror用于将错误码转换成对应的错误信息。
在使用时,strerror内的参数通常会设定为errno,并包含头文件:#include
errno是一个全局的错误变量,当本次库函数使用发生错误时,errno会记录本次发生的错误码;当下一次库函数使用发生错误时,errno又会记录下次发生的错误码。
由于内存函数是直接对内存进行操作,因此内存函数相较于字符串函数,其作用范围更加广泛,除了字符串外,整型数组、结构体等都是可操作对象。
函数原型:void *memcpy( void *dest, const void *src, size_t count );
memcopy函数从src位置开始,将count总字节的数据拷贝到dest的内存位置。
memcpy主要针对无重复内存的拷贝。
函数原型:void *memmove( void *dest, const void *src, size_t count );
memmove函数从src位置开始,将count总字节的数据拷贝到dest的内存位置。
memmove主要针对重复内存的拷贝
函数原型:int memcmp( const void *buf1, const void *buf2, size_t count );
memcmp函数比较buf1和buf2开始的count个字节,结果同strcmp和strncmp。
memcmp比较的是内存对应位置上的字节大小。
函数原型:void *memset( void *dest, int c, size_t count );
memset函数是以字节为单位给dest开始的内存空间赋值c,一共复制count个字节。