通过编程,实现strlen、strcmp、strcpy、strcnpy、strcat、strstr、strchr等字符串处理函数,和atoi函数
(1)strlen函数:int mystrlen(char *s)
功能:计算字符串s的长度、返回s的长度,不包括结束符'\0'。
思路:遍历字符串直到结束符为止,定义一个int型变量记录字符串长度
int mystrlen(const char *s)
{
int count = 0;
while(*s++) //先取后+
{
count++;
}
return count;
}
(2)strcmp函数:int mystrcmp(const char *str1,const char * str2)
功能:比较字符串s1和s2:(1)当s1
思路:遍历字符串s1和s2,当某串结束或不相等时跳出循环,返回字符的差值。(当两串相等时差值也是为0)
int mystrcmp(const char *s1,const char *s2)
{
while( ((*s1 != '\0')||(*s2 != '\0')) && (*s1 == *s2))
{
s1++;
s2++;
}
return *s1 - *s2;
}
过程中发生的小错误:
没有判断字符串为空了的情况,导致相等的情况下s1++,s2++后回到循环判断条件中取地址,显示段错误
(3)strcpy函数:char *mystrcpy(char* dest, const char *src)
功能:把从src地址开始且含有NULL结束符的字符串复制到以dest开始的地址空间,返回指向dest的指针。
思路:定义一个char*的指针ret指向dest的首地址,while循环从*ret值不为'\0'为止,依次把src的字符赋给ret(包括'\0')
所有操作用局部变量ret来实现,操作结果是dest的首地址不变而地址指向的值改变了,返回的是dest的首地址而不是局部变量ret。
char *mystrcpy(char* dest, const char *src)
{
char *ret = dest;
while(*ret++ = *src++)
{;}
return dest;
}
(4)strncpy函数:extern char *mystrncpy(char *dest, char *src, int n)
功能:把src所指由NULL结束的字符串的前n个字节复制到dest所指的数组中、返回指向dest的指针。如果src的长度小于n个字节,则以NULL填充dest直到复制完n个字节。
思路:与mystrcpy的思路相近。定义一个char*的指针ret指向dest的首地址,循环while当n等于0时结束,若src已到尾而n还未置零时,*ret = NULL
所有操作用局部变量ret来实现,操作结果是dest的首地址不变而地址指向的值改变了,返回的是dest的首地址而不是局部变量ret。
extern char *mystrncpy(char *dest, const char *src, int n)
{
char *ret = dest;
while(n--)
{
if(*src == '\0')
{
*ret = '\0';
}
else
{
*ret = *src;
}
}
return dest;
}
过程中发生的小错误
dest中传进来的参数不能是char *s = "",因为字符串常量中有\0,第一步取地址的时候就会显示段错误;
(5)strcat函数:char *mystrcat(char *dest,char *src)
功能:把src所指字符串添加到dest结尾处(覆盖dest结尾处的'\0')并添加'\0'、返回指向dest的指针。
思路:定义一个char*的指针ret指向dest的首地址,先遍历src直到结尾,再while循环ret从头到遇到'\0'为止,依次赋值
所有操作用局部变量ret来实现,操作结果是dest的首地址不变而地址指向的值改变了,返回的是dest的首地址而不是局部变量ret。
char *mystrcat(char *dest, const char *src)
{
char *ret = dest;
while(*ret)
{
ret++;
}
while(*ret++ = *src++)
{;}
return dest;
}
过程中发生的小错误:
在写第一个循环遍历ret的时候,图省事写的判断条件是 *ret++,当遍历结束的时候*ret位于'\0'字符串结束符之后,后面再进行赋值操作时复制后的字符都显示不出来,因为输出的是到第一个'\0'为止
即 :hello'\0'world'\0'
(6)strstr函数:char *mystrstr(const char *s1, const char *s2)
功能:实现从字符串str1中查找是否有字符串str2,如果有,从str1中的str2位置起,返回str1中str2起始位置的指针,如果没有,返回null。
思路:定义三个char*的指针,start指向s1的首地址,p2指向s2的首地址,p1先赋初值为NULL;当s2为空的时候不必判断(没有空判断的话,到下面的if时会判断条件成功,返回start值);while循环start(即循环s1),在比较前给p1和p2重新赋值,然后比较*p1和*p2是否相等,相等的话就p1++,p2++,其他情况跳出循环;循环结束之后判断s2是否为空,若为空则代表s2搜索成功,返回串首地址start
char* mystrstr(const char* s1, const char* s2)
{
char *start = (char *)s1;
char *p1 = NULL;
char *p2 = (char *)s2;
if(*s2 == '\0')
{
return nullptr;
}
while(*start)
{
p1 = start;
p2 = (char *)s2;
while((*p1 != '\0') && (*p2 != '\0') && (*p1 == *p2))
{
p1++;
p2++;
}
if(*p2 == '\0')
{
return start;
}
}
return nullptr;
}
过程中发生的小问题:
假如串s1为"hello" ,s2为"ell"时,可以搜索到子串,但是输出的结果为"ello",因为给的只是首地址,他会遍历到'\0'为止
应该在s2结束了的地方赋值'\0',但我不知道怎么改
(7)strchr函数:extern char *mystrchr(const char *s1, const char *s2)
功能:查找字符串s中首次出现字符c的位置、返回首次出现c的位置的指针,如果s中不存在c则返回NULL。
思路:定义一个char*的指针ret指向dest的首地址,while循环当*ret不为'\0'且等于c的时候ret++,当循环结束*ret为'\0'时返回NULL
extern char *mystrchr(const char *s,char c)
{
char *ret = (char *)s;
while((*ret != '\0') && (*ret != c))
{
ret++;
}
if(*ret == '\0')
{
return NULL;
}
return ret;
}
(8)atoi函数:int atoi(const char *nptr)
功能:把字符串转换成整型数。扫描参数nptr字符串,跳过前面的空格字符,直到遇上数字或正负符号才开始做转换,而再遇到非数字或字符串结束符('\0')才结束转换,并将结果返回。
思路:定义int变量num存放转换的整型数,定义两个标志(flag_num作数字组已经结束的标记;flag_symbol作符号标记)
while循环直到*npt不为'\0' ;如果遇到'-'则flag_symbol=-1;如果遇到'+'则flag_symbol=1 ;如果遇到数字组,标记不为-1时作正数的转换;如果遇到数字组,标记为-1时作负数的转换
当数字组结束遇到其他字符时则打破循环,返回num值
int myatoi(const char* nptr)
{
int num = 0;
int flag_num = 0;
int flag_symbol = 0;
while(*nptr != '\0')
{
if((*nptr == '-') && !flag_symbol)
{
flag_symbol = -1;
}
else if((*nptr == '+') && !flag_symbol)
{
flag_symbol = 1;
}
else if((*nptr >= '0') && (*nptr <= '9') && (flag_symbol != -1))
{
flag = 1;
num = num * 10 + *nptr - '0';
}
else if((*nptr >= '0') && (*nptr <= '9') && (flag_symbol == -1))
{
flag = 1;
num = num * 10 + '0' - *nptr;
}
else if(flag)
{
break;
}
nptr++;
}
return num;
}