使用C语言处理字符串

1.获取字符串长度

int my_strlen(const char *src) {
    assert(src != NULL);
    /*方法1*/
    int len = 0;
    while(*src++ != '\0') {//函数退出条件是src='\0'但之后还进行了自增运算
        len++;
    }
    return len;
    /*方法2*/
    // const char *psrc = src;
    // while(*psrc++ != '\0') ;
    // return psrc - src - 1;
}

2.字符串比较

//字符串s与字符串t 相等 返回0
//字符串s与字符串t 不相等 返回1或-1
int my_strcmp(const char *s,const char *t) {
    assert(s != NULL && t != NULL);
    while(*s == *t) {
    	if(*s == '\0')
    		return 0;
    	s++;
    	t++;
    }
    // return ((*(unsigned char *)s > *(unsigned char *)t) > 0)? 1: -1;
    return ((*s - *t) > 0)?1:-1;
}

3.字符串比较(前n个字符)

//限制比较个数,只比较前n个字符
//字符串s与字符串t 相等 返回0
//字符串s与字符串t 不相等 返回1或-1
int my_strncmp(const char *s,const char *t,int n) {
	assert(s != NULL && t != NULL);
	while(n-- && *s == *t) { //条件用n判断但之后n减少了1
		if(n == 0 && *s == *t)
			return 0;
		s++;
		t++;
		
	}
	return ((*s - *t) > 0)? 1: -1;
}

4.字符串复制

//将src复制到dst
char *my_strcpy(char *dst,const char *src) {
    if(src == dst) return dst;
    assert(src != NULL && dst != NULL);
    char *pdst = dst;
    while(*pdst++ = *src++);
    //*pdst = '\0'; //该代码可以忽略
    return dst;
}

5.字符串复制(指定复制字符数n)

//将src的n个字符复制到dst
char *my_strncpy(char *dst,const char *src,size_t n) {
	assert(src != NULL && dst != NULL);
	char *pdst = dst;
	while(n-- > 0 && *src != '\0')
		*pdst++ = *src++;
	*pdst = '\0'; //切记勿忘
	return dst;
}

6.字符串拼接

//将src拼接到dst后面
char *my_strcat(char *dst,const char *src) {
	assert(src != NULL && dst != NULL);
	char *pdst = dst;
	while(*pdst) pdst++;
	while((*pdst++ = *src++) != '\0');
	//*pdst = '\0'; //该行可以忽略
	return dst;
}

7.字符串拼接(指定拼接字符数n)

//将src的n个字符拼接到dst后面
char *my_strncat(char *dst,const char *src,size_t n) {
	assert(src != NULL && dst != NULL);
	char *pdst = dst;
	while(*pdst) pdst++ ; 
	while(n-- && (*pdst++ = *src++)) ;
	*pdst = '\0';
	return dst;
}

8.字符串拷贝到新位置

/*字符串拷贝到新位置,需要配合free使用*/
char *my_strdup(const char *src) {
	if(src == NULL) return NULL;
	/*先计算字符串长度*/
	size_t len = my_strlen(src);
	char *new_addr = malloc(len + 1);
	char *res = new_addr;
	while((*new_addr++ = *src++) != '\0');
	return res;
	// 测试
	// char *str = my_strdup("hello world!");
	// printf("%s\n",str);
	// free(str);
}

9.字符数组反转(倒序)

char *my_strrev(char *src) {
	assert(src != NULL);
	char *s = src;
	char *t = src + my_strlen(src) - 1;
	while(s < t) {
		*s ^= *t;
		*t ^= *s;
		*s ^= *t;
		s++;t--;
	}
	return src;
	// 测试
	// char s[] = "hello";
	// printf("%s\n",my_strrev(s)); //不能使用字符串,因为字符串是常量,无法修改
}

10.字符串转数字

/**
 * 字符串转整数即atoi
 * 如果第一个非空格字符存在,从数字或者正负号开始做类型转换,
 * 检测到非数字或者结束符时停止转换返回相应整数;否则溢出时就返回0
 * 判断字符串是不是数字,类似于strtod
 */
int my_atoi(const char *src) {
	const char *p = src;
	while(*p && (*p == ' ' || *p == '\t' || *p == '\n') ) p++;
	long long res = 0;
	bool flag = false;
	bool valid = false;
	if(*p == '+')
		p++;
	else if(*p == '-') {
		p++;
		flag = true;
	}
	/*检测到非数字字符时停止转换,返回整形数否则返回0*/
	for(;*p && (*p >= '0' && *p <= '9');p++) {
		int sign = (flag == true)?-1:1;
		res = res * 10 + sign * (*p - '0');
		if((flag && res < 0x80000000) || (!flag && res > 0x7fffffff)) {
			res = 0;
			break;
		}
	}
	if(*p == '\0') {
		valid = true;
	}
	return (int)res;
}

11.字符串中查找字符

//查找成功则返回该字符第一次出现的位置
//查找失败则返回NULL
char *my_strchr(const char *src,int ch) {
	assert(src != NULL);
	const char *psrc = src;
	while(*psrc != '\0' && *psrc != ch) {
		psrc++;
	}
	return (*psrc == '\0')? NULL : (char *)psrc;
}

12.字符串中查找字符(后面开始)

//查找一个字符c在另一个字符串str中末次出现的位置
//(也就是从str的右侧开始查找字符c首次出现的位置),并返回这个位置的地址。
//如果未能找到指定字符,那么函数将返回NULL。
char *my_strrchr(const char *src,int ch) {
	if(src == NULL) return NULL;
	const char *rsrc = src;
	while(*rsrc!= '\0') rsrc++;
	for(--rsrc; *rsrc != ch;--rsrc) {
		if(rsrc == src)
			 return NULL;
	}
	return (char *)rsrc;
}

13.字符串中查找字符串

//用于判断字符串str2是否是str1的子串。
//如果是,则该函数返回 str1字符串从 str2第一次出现的位置开始到 str1结尾的字符串;
//否则,返回NULL。
/*BF算法的指针版本*/
char *my_strstr(const char *cs,const char *ct) {
	assert(cs != NULL && ct != NULL);
	const char *s = cs;
	const char *t = ct;
	for(; *cs != '\0';cs++) {
		for(s = cs,t = ct;*t != '\0' && *s == *t;s++,t++);
		if(*t == '\0')
			return (char *)cs;
	}
	return NULL;
}
//用于判断字符串str2是否是str1的子串。
//如果是,则该函数返回 str1字符串从 str2第一次出现的位置开始到 str1结尾的字符串;
//否则,返回NULL。
/*BF算法的数组版本*/
char *my_strstr1(const char *cs,const char *ct) {
	assert(cs != NULL && ct != NULL);
	int len1 = my_strlen(cs);
	int len2 = my_strlen(ct);
	for(int i = 0; i <= len1 - len2;i++) {
		int j = 0;
		while(j < len2 && cs[i + j] == ct[j]) j++;
		if(j == len2)
			return (char *)(cs + i);
	}
	return NULL;
}

14.get_next

KMP算法中get_next函数分析
关于KMP算法中next函数的详细解析

void get_next(const char *pat,int *next,int n) {
	int j = -1;
	next[0] = -1;
	for(int i = 1; i < n;i++) {
		while(j != -1 && pat[j + 1] != pat[i])  j = next[j]; //回退到匹配尾字符的位置
		if(pat[j + 1] == pat[i]) j++;
		next[i] = j; //更新当前位置的next值
	}
}

15.kmp_strstr

实现strStr()(KMP解法)

//在字符串src中找出 pat字符串出现的第一个位置 (从0开始)
int kmp_strstr(const char *src,const char *pat) {
	int slen = my_strlen(src);
	int plen = my_strlen(pat);
	int *next = malloc(sizeof(int) * plen);
	get_next(pat,next,plen);

	int j = -1;
	for(int i = 0; i < slen;i++) {
		while(j > -1 && pat[j + 1] != src[i])  j = next[j];
		if(pat[j + 1] == src[i]) j++;
		if(j == plen - 1) { //表明模式串最后一个字符被匹配
			free(next);
			return i - j;
		}
	}
	free(next);
	return -1;
}

参考链接:
https://www.cnblogs.com/xionghj/p/4443891.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值