C语言字符串专题二:重写字符串相关函数+朴素字符串匹配算法

本篇文章仍是较为基础的C语言字符串操作及相关知识,欢迎大家阅读!!

附加:指针可以进行相减(相减时对于指针的指向:算头不算尾!),相减得到的是存储单元的个数(对于char类型也可以说成减下来是字节个数);指针也可以加一。(但指针间的加法运算无意义)

一、重写求字符串长度的函数(利用指针相减)

#include<stdio.h>
#include<assert.h>
int my_strlen(const char* str){
	assert(str!=NULL);
	const char* cp=str; //由于定义的形参为const char*(只可读不可改),故进行赋值 cp也需要定义为const char*类型。 
	while(*cp!='\0'){
		cp++;
	}
	return (int)(cp-str); //通过指针运算返回字符串长度(字节数、存储单元个数) 
}
int main(){
	char stra[30]={"xiaoxin"};
	int len=my_strlen(stra);
	printf("len: %d",len); //运行结果:len: 7 
}

注意:如果将while循环写成while(*cp++!='\0'); //不会编译出错!!        当执行到*cp=='\0'时,不再循环,但仍会执行(cp++)这一步,所以会多加一次! 应该:return (int)(cp-str-1);

二、重写字符串比较函数(结果为0:两个字符串相等;结果为>0的值:字符串1>字符串2;结果为<0的值:字符串1<字符串2)

1. 易于理解的一种写法

int my_strcmp(const char* dest,const char* src){
	assert(dest!=NULL&&src!=NULL);
	while(*dest!='\0'||*src!='\0'){
		if(*dest==*src){
			dest++;
			src++;
		}
		else{
			break;
		}
	}
	return (*dest-*src);//返回字符相减结果(ASCII码值相减,'\0'的ASCII码值为0) 
}

2. 高效的写法

//特别高效的写法
int my_strcmp(const char* dest,const char* src){
	assert(dest!=NULL&&src!=NULL);
	int k=0;
	while((k=*dest-*src)==0 &&*dest++ && *src++); //1.相减赋值给k 2.判断k是否等于0(等于0则为1) 3.*dest!='\0'&&*src!='\0' 进入循环 4.dest++; src++;  
	return k; //返回字符相减结果(ASCII码值相减)  
}

三、重写返回字符串中存储某一特定字符的地址的函数

1. 从前往后找

//从前往后查找 
char* my_strchr(const char*str,char ch){ 
	assert(str!=NULL);
	char* cp=(char*)str; //定义新的字符指针指向str(必须强转为非 常性指针,可读可写,否则会报错!!)  
	while(*cp!='\0' && *cp!=ch){
		cp++;
	}
	if(*cp=='\0') cp=NULL;
	return cp;
}

2. 从后往前找

//从后往前找
int my_strlen(const char* str){
	assert(str!=NULL);
	const char* cp=str; //遇到类型不一致的情况究竟是强转还是定义为常性字符指针取决于自己 
	while(*cp!='\0'){
		cp++;
	} 
	return cp-str; //因为是字符型,所以减出来就为字符串长度 
}
char* my_strchr1(const char* str,char ch){
	assert(str!=NULL);
	char* cp=(char*)str+my_strlen(str)-1; //必须强转!! 减1使得cp指向最后一个元素(否则cp指向'\0') 
	while(ch!=(str-1) && *cp!=ch){   //str-1即为str首元素前一位的地址
		cp--;
	}
	if(cp==str-1) cp=NULL; //此时不要去比较*cp与ch是否相等。当退出条件为cp==str-1时,对应的数值已不再该数组范围内。 
	return cp;
} 

四、朴素字符串匹配算法(数据结构中学习的KMP算法自然更简明)

#include<stdio.h>
#include<assert.h>
int my_strlen(const char* str){
	assert(str!=NULL);
	const char* cp=str; //别忘记类型转换!!(只能将常性指针赋给常性指针变量) 
	while(*cp!='\0'){
		cp++;
	}
	return cp-str;
}
//朴素字符串匹配算法
char* my_strstr(const char* str,const char*substr){
	if(str==NULL||substr==NULL) return NULL;
	int sn=my_strlen(str); //主串长度
	int sm=my_strlen(substr); //子串长度
	int k=0;
	for(int i=0;i<sn-sm+1;i++){ //i<sn-sm+1; 是由于当i指向位置之后的字符个数不足字串个数即可直接退出,匹配失败 
		int j=0;
		k=i;
		while(j<sm&&str[k]==substr[j]){ //退出循环有两种情况:1.j=sm(完全匹配) 2.str[k]!=substr[j] 进行下一轮循环,i++; 
			j++;
			k++;
		}
		if(j==sm){
			return (char*)str; //返回&str[i];(地址!) 由于函数定义为char*,所以需要强转、或者将函数定义为const char* 
		} 
	}
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值