目录
一.函数介绍
求字符串长度
strlen
size_t strlen ( const char * str );
字符串以 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' )。
参数指向的字符串必须要以 '\0' 结束。
注意函数的返回值为size_t,是无符号的( 易错 ),如下示例:
长度不受限制的字符串函数
1. strcpy
char* strcpy(char * destination, const char * source );
将源指向的 C 字符串拷贝到目标指向的数组中,包括终止字符 '\0'(并在该点停止),是一种覆盖。
源字符串必须以 '\0' 结束,且目标空间必须可修改。
为避免溢出,destination 指向的数组的大小应足够长,以包含与 source 相同的 C 字符串(包括终止字符 '\0' )。
返回指向目标数组的起始地址,即destination,如下示例:
2. strcat
char * strcat ( char * destination, const char * source );
将源字符串的拷贝追加到目标字符串。destination 中的终止字符 '\0' 被 source 的第一个字符覆盖,并且在 destination 中由两者串联形成的新字符串的末尾包含一个结束字符 '\0'。
源字符串必须以 '\0' 结束。
目标空间必须有足够的大,能容纳下源字符串的内容。
目标空间必须可修改。
返回destination,如下示例:
注意:目的地destination和来源source不得重叠,否则会发生错误,如下示例:
由于目的地和源串是同一块空间,那么目的地的终止字符'\0'被覆盖的同时,源串的终止字符也被修改了,导致了死循环,进而引发了数组的越界访问操作。
3. strcmp
int strcmp ( const char * str1, const char * str2 );
将 C 字符串 str1 与 C 字符串 str2 进行比较。
此函数从每个字符串的第一个字符开始比较,如果它们彼此相等,则继续以下对,直到字符不同或达到终止字符 '\0'。
标准规定:
第一个字符串 > 第二个字符串,则返回大于0的数字
第一个字符串 == 第二个字符串,则返回0
第一个字符串 < 第二个字符串,则返回小于0的数字
如下示例:
长度受限制的字符串函数
1. strncpy
char * strncpy ( char * destination, const char * source, size_t num );
从源字符串拷贝num个字符到目标空间。
如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
如下示例:
2. strncat
char * strncat ( char * destination, const char * source, size_t num );
将源的前 num 个字符拷贝追加到目标。如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
如果 source 的长度大于 num,则不会在目标末尾隐式追加 终止字符 ‘\0'。因此,在这种情况下,destination 不应被视为以 '\0' 结尾的 C 字符串(这样读取它可能会溢出)。
如下示例:
3.strncmp
int strncmp ( const char * str1, const char * str2, size_t num );
比较num个字符,如下示例:
字符串查找
1. strstr
char * strstr ( const char *str1, const char * str2);
返回指向 str1 中 str2 第一次出现的指针,如果 str2 不是 str1 的一部分,则返回 null 指针。
匹配过程不包括终止字符 '\0',但到此为止。
如下示例:
2. strtok
char * strtok ( char * str, const char * sep );
将字符串拆分为标记
sep参数是个字符串,定义了用作分隔符的字符集合。
第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标 记。
对此函数的一系列调用将 str 拆分为标记,标记是由分隔符中的任何字符分隔的连续字符序列。
在第一次调用时,该函数需要一个 C 字符串作为 str 的参数,扫描第一个标记的起始位置。在后续调用中,该函数需要一个空指针NULL,并使用最后一个标记末尾的位置作为扫描的新起始位置。
为了确定标记的开头和结尾,该函数首先从起始位置扫描分隔符中未包含的第一个字符(该字符将成为标记的开头)。然后从此标记的开头开始扫描分隔符中包含的第一个字符,该字符成为该标记的结尾。如果找到终止字符,扫描也会停止。
标记的末尾自动替换为终止字符 '\0',并且标记的开头由函数返回。
在对 strtok 的调用中找到 str 的终止字符后,对此函数的所有后续调用(将 null 指针作为第一个参数)将返回一个 null 指针。
找到最后一个标记的点由要在下一次调用中使用的函数在内部保留(不需要特定的库实现来避免数据争用)。
注: strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。
来看具体示例:
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="- This, a sample string.";
char tmp[50] = {0};
strcpy(tmp, str);
char * pch= strtok (tmp," ,.-");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " ,.-");
}
return 0;
}
//输出:
This
a
sample
string
建议粘贴以上代码,再结合文字叙述,自行调试观察。
错误信息报告
strerror
char * strerror ( int errnum );
返回错误码所对应的错误信息。
库函数在执行的时候,如果发生错误,就会将一个错误码存放在一个叫errno的变量中,这个变量是C语言提供的一个全局变量,包含在 errno.h 这个头文件中。
如下示例:
字符分类和转换函数
头文件:ctype.h
内存操作函数
都是以字节为基本操作单位。
1. memcpy
void * memcpy ( void * destination, const void * source, size_t num );
源指针和目标指针指向的对象的基础类型与此函数无关。
函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
这个函数在遇到 '\0' 的时候并不会停下来。
如果source和destination有任何的重叠,复制的结果都是未定义的。
返回 destination。
如下示例:
2. memmove
void* memmove(void* destination, const void* source, size_t num);
移动内存块
和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
如果源空间和目标空间出现重叠,就得使用memmove函数处理。
返回destination.
如下示例:
3. memset
void * memset ( void * ptr, int value, size_t num );
填充内存块
把指向ptr的连续num个字节设为特定值value。
注意:value该值以 int 形式传递,但该函数使用此值的无符号 char 转换填充内存块,也就是说会发生截断。
返回ptr。
如下示例:
4. memcmp
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
比较从ptr1和ptr2指针开始的num个字节。
判断的返回值和strcmp一样。
二. 上述常用库函数的模拟实现
1.模拟实现strlen
//方式一:计数器
int my_strlen(const char * str)
{
int count = 0;
while(*str)
{
count++;
str++;
}
return count;
}
//方式二:递归
int my_strlen(const char * str)
{
if(*str == '\0')
return 0;
else
return 1+my_strlen(str+1);
}
//方式三:指针 - 指针
int my_strlen(char *s)
{
char *p = s;
while(*p != ‘\0’ )
p++;
return p-s;
}
2. 模拟实现strcpy
char *my_strcpy(char *dest, const char*src)
{
char *ret = dest;
assert(dest != NULL);
assert(src != NULL);
while((*dest++ = *src++))
{
;
}
return ret;
}
3. 模拟实现strcat
char *my_strcat(char *dest, const char*src)
{
char *ret = dest;
assert(dest != NULL);
assert(src != NULL);
while(*dest)
{
dest++;
}
while((*dest++ = *src++))
{
;
}
return ret;
}
4. 模拟实现strstr
char * strstr (const char * str1, const char * str2)
{
char *cp = (char *) str1;
char *s1, *s2;
if ( !*str2 )
return((char *)str1);
while (*cp)
{
s1 = cp;
s2 = (char *) str2;
while ( *s1 && *s2 && !(*s1-*s2) )
s1++, s2++;
if (!*s2) return(cp);
cp++;
}
return NULL;
}
5. 模拟实现strcmp
int my_strcmp (const char * src, const char * dst)
{
int ret = 0 ;
assert(src != NULL);
assert(dest != NULL);
while( !(ret = *src - *dst) && *dst)
++src, ++dst;
if ( ret < 0 )
ret = -1 ;
else if ( ret > 0 )
ret = 1 ;
return ret;
}
6. 模拟实现memcpy
void * memcpy ( void * dst, const void * src, size_t count)
{
void * ret = dst;
assert(dst);
assert(src);
while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
return ret;
}
7. 模拟实现memmove
void * memmove ( void * dst, const void * src, size_t count)
{
void * ret = dst;
if (dst <= src || (char *)dst >= ((char *)src + count))
{
while (count--)
{
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
}
else {
dst = (char *)dst + count - 1;
src = (char *)src + count - 1;
while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst - 1;
src = (char *)src - 1;
}
}
return ret;
}
本次分享到这就结束了,如果对你有所帮助,就是对小编最大的鼓励,如果可以的话,点赞,关注加收藏并分享给你好友,一起学习进步吧!
关注小编,持续更新!