【Linux C】字符串编程练习

通过编程,实现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<s2时,返回为负数;(2)当s1==s2时,返回值= 0;(3)当s1>s2时,返回正数。

思路:遍历字符串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;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值