手写strlen()、strcpy()、strcmp()、strcat()、strstr()、memcpy()
一、int strlen(const char *str);
此函数是传入一个字符串,计算该字符串的长度,’\0’不算入其中。 (sizeof()才会把’\0’算入其中,但是sizeof()的功能是计算传入字符串所占的字节是多少)
int strlen(const char *str){
assert(str != NULL); //检查传入的字符串有没有申请空间
int len = 0; //定义字符串长度的计数变量
while((*str++) != '\0') //一直计算到'\0'的前一个字符为止
len++;
return len; //返回字符串的长度(不包含'\0'的一个长度)
}
二、char* strcpy(char* str1, char* str2)
此函数是将str2复制到str1所指向的空间上。此函数不安全,容易产生内存越界(溢出),如果str2申请的空间比str1申请的空间大,就会产生此情况。
char* strcpy(char* str1, char* str2){
assert((str1 != NULL)&&(str2 != NULL)); //检查传入的字符串有没有申请空间
char * addr = str1; //首先记录str1字符串的首地址,为了后面返回用
while((*str1++ = *str2++) != '\0'); //一直将str2的字符复制到str1的内存中去,直到复制完str2的'\0'空字符为止
return addr; //返回str1的首地址
}
三、int strcmp(const char* str1, const char* str2)
此函数比较两个字符串是否相等,如果相等返回0,如果str1大于str2,返回正数,如果str1小于str2,返回负数。
int strcmp(const char* str1, const char* str2){
assert((str1 != NULL)&&(str2 != NULL)); //检查传入的字符串有没有申请空间
int ret = 0; //定义返回值变量
while(!(ret = *(unsigned char *)str1 - *(unsigned char *)str2)&&(*str1)){
str1++; //计算str1和str2的差值,如果差值为0,继续往后计算
str2++; //如果不为0,则退出循环。当str1指向'\0'时,退出循环。
}
if(ret > 0) //大于0,返回1
return 1;
else if(ret < 0) //小于0,返回-1
return -1;
else
return 0; //否则,返回0
}
四、char* strcat(char* str1, const char* str2)
此函数从str1字符串的’\0’位置开始将str2复制到str1后面。
char* strcat(char* str1, const char* str2){
assert((str1 != NULL)&&(str2 != NULL)); //检查传入的字符串有没有申请空间
char * addr = str1; //首先记录str1字符串的首地址,为了后面返回用
while((*str1++) != '\0'); //将str1指针指向最后一个空字符'\0'
while((*str1++ = *str2++) != '\0'); //从空字符开始将str2复制进str1的内存空间
*str1 = '\0'; //复制完后在最后的位置加上'\0'
return addr; //返回复制完后的首地址
}
五、char* strstr(const char* str1, const char* str2)
此函数用于判断str2是否是str1的子串,如果找到了就返回str1中中对应位置的起始地址,如果没找到就返回NULL。
char* strstr(const char* str1, const char* str2){
assert((str1 != NULL)&&(str2 != NULL)); //检查传入的字符串有没有申请空间
int str1len = strlen(str1); //计算str1的长度
int str2len = strlen(str2); //计算str2的长度
if(str1len < str2len)
return -1; //这种情况就直接返回
int i,j;
for(i = 0; i<(str1len-str2len); i++){
for(j = 0; j<str2len; j++){
if(str1[i+j] != str2[j]) //循环判断str2是否是str1其中的子串
break;
}
if(str2len == j) //如果str2len的长度和j相等,证明str2是str1子串
return str1+i; //返回str1其中子串的起始地址
}
return NULL; //失败返回NULL
}
六、void* memcpy(void* str1, const void* str2,int count)
该函数将str2的count个字节数据复制到str1存储区内。
void* memcpy(void* str1, const void* str2,int count){
assert((str1 != NULL)&&(str2 != NULL)); //检查传入的字符串有没有申请空间
char* STR1 = (char*)str1;
const char* STR2 = (char*)str2;
int i;
if(STR1 > STR2&&STR1 < (STR2 + count)){
for(i = count-1;i>=0;i--)
STR1[i] = STR2[i];
}
else{
for(i = 0;i < count;i++)
STR1[i] = STR2[i];
}
return str1;
}