【C语言】字符串及内存函数解析(部分)
引言:不同字符串函数代表了对字符串进行不同的处理,以得出与字符串相关的信息,下面介绍有关字符串函数与内存函数的介绍
strlen
此函数用于求字符串的长度,具体调用格式为传入字符串的首地址,之后会检查字符串的每个字符,知道遇到字符**’\0’停止计数,’\0’**不会被统计进去,具体代码示例如下:
size_t strlen (const char * str)
{
const char *eos = str;
while( *eos++ ) ;
return( eos - str - 1 );
}
由代码第一行可知 strlen 函数接收一个char* 类型的指针,返回的是一个size_t类型的整数(即无符号整型,其值>=0,在长度比较时一定要注意),在函数体内部创造了一个名为 eos 的char*类型的指针,用来存储地址以指向str所指向的空间,while循环中自加减运算符优先级高于解引用运算符,每次先对eos指向空间读取后再自加,当eos读取到的空间为0时跳出循环,eos指向的是’\0’(其真实值为0)后的下一个空间,故eos-str代表字符串的元素个数(包括字符’\0’),之后减1减去字符’\0’,完成字符串长度求解。所以一定要保证有结束字符。
strcpy
此函数用于拷贝字符串,将源头字符串拷贝至目标指向的空间,因此必须保证有足够的空间容纳字符串,示例代码如下:
char * strcpy(char *dest, const char*src)
{
char *ret = dest;
assert(dest != NULL);
assert(src != NULL);
while((*dest++ = *src++));
return ret;
}
第一行代码表示strcpy函数需要两个参数,即源字符串(src)的首地址与目标空间(dest)的首地址,首先创建一个变量ret来保存目标空间的首地址以便于返回,再通过断言判断指针有效性,之后的while循环中,其循环过程为:首先将src指向的空间的值赋予dest指向的空间,之后src自加,dest指向空间的值经过判断后,dest自加,再快到结束的时候在判断条件为零(dest指向空间存放’\0’)时,循环结束,此时,dest指针与src指针都指向后面一个空间,但没有赋值。此时拷贝已经完成,所以返回开始保存的目标空间的指针;函数源字符串必须包含结束字符’\0’否则难以确定拷贝何时停止。
strcat
此函数用于字符串的追加,在接续目标字符串末尾后添加源字符串,同样是以源字符串的结束字符作为结束标志。
char * __cdecl strcat (
char * dst,
const char * src
)
{
char * cp = dst;
while( *cp )
cp++;
while( *cp++ = *src++ ) ;
return( dst );
}
代码第一行表示这个字符串需要两个参数:目标字符串的首地址(dst),源字符串的首地址(src)。通过创建cp指针指向目标字符串空间防止dst指针存放的空间地址被改变,便于返回目标字符串的首地址值。第一个while循环用于寻找目标字符串的结束字符’\0’,先读取cp指向空间是否为0,若不是,cp自加,如果是,结束循环,cp指向的是目标字符串结束字符存放的空间。第二个循环开始将src指向空间的值赋给dst, 指导dst指向空间的值为零后结束,返回目标字符串的首地址后,函数任务完成。在使用该函数时,一定要保证src字符串有结束标志。
strstr
此函数用于判断某字符串是否为另一字符串的子字符串。示例代码如下:
char * __cdecl 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);
}
该函数需要两个参数,str1字符串与str2字符串的首地址,用于判断str2是否为str1的子字符串;第一个if语句表示如果str2是一个空字符串的话,直接返回str1的地址,毕竟空字符串包是任意字符串的子集。在第一个while循环是每一次比对过程的的循环,在每次循环后,s1被重新赋值,s2指向str2的首地址以返回源头,内嵌的while循环时具体的比对过程:在保证s1没有指向结束字符(母字符串没有结束),s2未指向结束字符(子字符串没有比对结束),s1与s2指向空间存放字符相同三组条件一起满足的情况下,s1与s2共同自加,逐个比对,while循环结束时(意味着以上三个条件有一个不满足),若s2指向空间为0,说明母字符串中一部分与子字符串相同,此时cp指向的时母字符串中与子字符串相同部分的首地址,将其返回;若没有找到,说明比对失败,cp自加,以母字符串下一个字符为比对起点进行比对,往复循环·········如果一直没有比对到(cp指向结束字符),意味着str2不是str1的子字符串,返回空指针。
strcmp
此函数用于字符串逐个字符的比对,返回字符串之间第一个有差异字符的差值(返回一个int整型)。示例代码如下:
int strcmp (
const char * src,
const char * dst
)
{
int ret = 0 ;
while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
++src, ++dst;
if ( ret < 0 )
ret = -1 ;
else if ( ret > 0 )
ret = 1 ;
return( ret );
}
此函数需要两个参数,分别时不同字符串的首地址。while循环中,其循环的条件是 ret的值为0 或者 解引用dst的值为0,满足条件后 src++,dst++进行下一组字符比对。若在两个字符串逐个字符比对的过程中发现有两个字符存在差异,ret的值即为非0,循环跳出,根据ret的值返回要求数字(如果两个长度不等的字符串比较大小,在短字符串全部与长字符串前一部分相同,会拿短字符串结束字符’\0’进行比较);如果一直比对到两个字符串最后的结束字符’\0’,*dst = 0,跳出循环,返回此时的ret值0。
memcpy
以mem开头的函数不同于以str开头的函数,其属于内存函数,作用范围不再像以str开头的字符串一样只可用于字符串的相关操作,可以用于对一切数据类型进行处理,例如memcpy可以对int型,float型,甚至结构体类型进行拷贝。通过示例代码对此函数进行讲解:
void * memcpy (
void * dst,
const void * src,
size_t count
)
{
void * ret = dst;
while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
return(ret);
}
首先,该函数有三个参数,目标空间的首地址,分别是①目标空间的首地址dst②要拷贝的数据空间的的首地址src③要拷贝的具体的字节数(无符号整型),首先创建ret变量存放dst指向空间的首地址,以便于函数结束后返回while循环的条件是count–,先判断完条件后自减,在判断为0之前,循环体执行了count次,循环体部分:第一句用于赋值操作,后面两句用于指针指向下一个字节空间,循环往复。void类型比较特殊,它是一个指针但没有指向具体的数据类型,让它加减整数必须将他转化为特定数据类型的指针,例如转化为char * 指针加一后,可以使他指向下一个字节的空间。至此,内存拷贝函数介绍完成。
memmove
memmove函数主要用于字符串在内存重叠的情况下的拷贝,它的功能完全包含memcpy函数,也有它的特殊部分。其示例代码如下:
void * __cdecl memmove (
void * dst,
const void * src,
size_t count
)
{
void * ret = dst;
if (dst <= src ) {
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);
}
此函数所需要的参数类型与memcpy函数的一致,两者不同的是对字符串的拷贝方法:当源字符串的地址大于目标空间的首地址时,采用由低地址到高地址的方向拷贝(代表的是if语句块的处理),否则(源字符串的地址小于目标空间的首地址)采用由高地址到低地址的方向拷贝,在拷贝之前将地址要拷贝空间的最高地址处,然后逐个字节倒序拷贝。
|