常见字符串函数实现

本文详细介绍了13种常用的字符串操作函数,包括strlen、strcpy、strncpy等,并提供了每种函数的具体实现代码,帮助读者深入理解这些函数的工作原理及使用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1,strlen

①计数法 

unsigned int my_strlen1(const char *str)

{

    unsigned int count=0;

    assert(str);

    while(*str){

        count++;
        str++;
    }
    return count;
}

 

②递归法

unsigned int my_strlen2(const char *str)
{
	if(*str=='\0')
		return 0;
	return my_strlen2(str+1)+1;
}

③首尾相减法

unsigned int my_strlen3(const char *str)
{
	assert(str);
	const char *end=str;
	while(*end++);
	return end-str-1;
}

2,strcpy

dest字符串要有足够的空间,src复制包括'\0'在内的字符串到dest中。

char *my_strcpy(char *dest,const char *src)
{
	char *tmp=dest;
	assert(dest&&src);
	
	while(*dest++=*src++);
	return tmp;
	
}

3,strncpy

src复制len个字符串到dest中,len如果比src长,则继续复制'\0'。len比src小时,复制len个,最后并添加'\0'。原strncpy最后没有添加'\0'。

char *my_strncpy(char *dest,const char *src,unsigned int len)
{
	assert(dest&&src);
	char *tmp=dest;
	while(len--){
		if((*dest++=*src)!='\0')
			src++;
	}
	*dest='\0';/*确保dest后有'\0',strncpy 没有这步,但是如果dest位置全部用完也没办法*/
	return tmp;
}

4,strcat

先遍历dest到'\0'位置,然后进行复制

char *my_strcat(char *dest,const char *src)
{
	char *tmp=dest;
	assert(dest&&src);
	while(*dest!='\0')
		dest++;
	while(*dest++=*src++);
	return tmp;
}

5,strncat

len就算比src的长度长 也不会像stcncpy继续添加'\0',而是src遇到'\0' 就结束

 

char *my_strncat(char *dest,const char *src,unsigned int len)
{
	assert(dest&&src);
	char *tmp=dest;
	while(*dest)
		dest++;
	while(len--&&(*dest++=*src++));

	*dest='\0';/*目标串始终以'\0'结束,strncat也是这么实现的*/ 
	return tmp;
} 

6,strcmp

int my_strcmp(const char *str1,const char *str2)
{
	assert(str1&&str2);
	/*第二个条件的作用,如果没有第二个条件当两个都为""只有一个\0字符时 就会奔溃*/ 
	while(*str1==*str2&&*str2){
		str1++;
		str2++;
	}
	return  *str1-*str2;
}

7,strncmp

int my_strncmp(const char *str1,const char *str2,unsigned int len)
{
	assert(str1&&str2);

	while(len--&&*str2){
		if(*str1!=*str2){
			return *str1-*str2;
		}
		str1++;
		str2++;
	}
	return 0;
}

8,strchr

在一个字符串中查找一个字符第一次出现的位置,如果没有则返回NULL

 

char *my_strchr(const char *str,char ch)
{
	assert(str);
	const char *tmp=str;
	while(*tmp){
		if(*tmp==ch)
			 return tmp;
		tmp++;
	}
	return NULL;
}

9,strrchr

查找一个字符在字符串最后出现的位置,没有则返回NULL

char *my_strrchr(const char *str,char ch)
{
	assert(str);
	const char *tmp=str;
	const char *ptr=NULL; 
	while(*tmp){
		if(*tmp==ch){
			ptr=tmp;
		}
		tmp++;
	}
	return  ptr;
}

10,strstr

在str1找第一次出现str2的起始位置,如果没有则返回NULL,str2为空字符串则返回str1

 

char *my_strstr(const char *str1,const char *str2)
{
	assert(str1&&str2);
	const char *cur=str1;
	const char *tmp=str2;
	if(*str2=='\0'){
		return str1;
	}
	while(*str1){
		while((*str1)&&(*str2)&&(*str1==*str2)){
			str1++;
			str2++;
		}
		if(*str2=='\0'){
			return cur;
		}
		cur++;
		str1=cur;
		str2=tmp; 
	}
	return NULL;
}

11,atoi

字符串转换为int型整数,字符串前面允许有若干空格,和+,-号。符号位后面必须是数字字符才算有效,如果遇到非法字符,则停止转换,返回前面转换好的数字。

需要考虑的问题:

  1. 指针是否为NULL
  2. 字符串是否为空串:空串为0
  3. 空白字符
  4. 正负号问题
  5. 溢出问题
  6. 异常字符处理

一些情况

" 1234" ->1234

" +1234" ->1234

" -1234" ->-1234

"-123 4" ->-123

"a1234" ->0

"+ 1234" ->0

"" ->0

int my_atoi(const char *str)
{
	assert(str);
	int ret=0;
	int flag=1;
	const char *tmp=str;
	
		while(isspace(*tmp)){
			tmp++;
		}
		if(*tmp=='-'){
			flag=-1;
			tmp++;
		}
		else if(*tmp=='+'){
			tmp++;
		}
		while(*tmp){
			if(isdigit(*tmp)){
				ret=ret*10+*tmp-'0';
				if(ret>INT_MAX||ret<INT_MIN){
					return flag*ret;
				}
			}
			else{
				break;/*异常字符*/
			}
			tmp++;
	}
	return flag*ret;
}

12,itoa

linux没有这个函数,windows上有,且有进制选择,下面只实现10进制的情况

char *my_itoa(int num,char *buf)
{
	assert(buf);
	int tmp=0;
	int i=0,j=0;
	int flag=0;
	if(num==0){
		buf[0]='0';
		buf[1]='\0';
		return buf;
	}
	if(num<0){
		num=-num;
		flag=1;
	}
	buf[i++]='\0';//开始把第一个字符设为'\0'
	while(num){
		tmp=num%10;
		buf[i++]=tmp+'0';
		num/=10;
	}
	
	if(flag==1){
		buf[i]='-';
	}
	else{
		i--;
	}//把倒序的字符串翻转
	while(j<i){
		tmp=buf[j];
		buf[j]=buf[i];
		buf[i]=tmp;
		j++;
		i--;
	}
	return buf;
}

13,memset

void* my_memset(void *src,int ch,int n)
{
	assert(src);
	void* ret=src;
	char *p=(char*)src;
	int i=0;
	while(n--)
	{
		*p++=ch;
	}
	return ret;
}

14,memcpy(不能正确处理有重复,且src在dest前的情况)

void* my_memcpy(void *dest,void *src,int n)
{
	assert(dest);
	assert(src);
	void* ret=dest;
	char* str1=(char*)dest;
	char* str2=(char*)src;
	while(n--)
	{
		*str1++=*str2++;
	}
	return ret;
}

15,memmove(利用处理上述情况)

void* my_memmove(void* dest,void* src,int n)
{
	assert(dest);
	assert(src);
	void* ret=dest;
	char* str1=(char*)dest;
	char* str2=(char*)src;
	if(src>dest)
	{
		while(n--)
		{
			*(str1+n)=*(str2+n);
		}
	}
	else
	{
		while(n--)
		{
			*str1++=*str2++;
		}
	}
	return ret;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值