字符串函数的使用和剖析——长度不受限的字符串函数

模拟实现函数
在这里插入图片描述
在这里插入图片描述

长度不受限制的字符串函数

函数介绍:
一、strlen函数
size_t strlen(const char* str);
功能:求字符串的长度(不包括\0)

  • 字符串是以‘\0’结尾的。strlen返回的是‘\0’前出现的字符的个数,不包括‘\0’的长度。
  • 参数指向的字符要以‘\0’结尾
  • 注意函数的返回值是size_t,是无符号的**(易错)**
    strlen模拟实现
    1、计数器方法实现
int my_strlen(const char *p){
	assert(*p);
	int count=0;
	while (*p){//遇到'\0'结束
		count++;
		p++;
	}
	return count;
}
int main(){
	char arr[] = "abcdefg";
	int num = 0;
	num = my_strlen(arr);
	printf("%d", num);
	system("pause");
	return 0;
}

2、递归方法实现

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <Windows.h>
#include <assert.h>
//递归方法实现
int my_strlen(const char *p){
	assert(p);//排除空指针
	int num = 0;
	if (*p!='\0'){
		return 1+my_strlen(++p);//递归,直到找当字符串中的'\0'
	}
	else {
		return 0;//找到\0,但是strlen函数计算字符串长度不把'\0'算入内,
	}

}
int main(){
	char *arr = "abcdefg";
	int num = 0;
	num = my_strlen(arr);
	printf("%d", num);
	system("pause");
	return 0;
}

3、指针减指针方法实现

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <Windows.h>
#include <assert.h>
//指针减指针方法实现
int my_strlen(const char *p){
	assert(p);//排除空指针
	char *i = p;
	while (*i != '\0'){
		i++;//让指针挪到字符串最后一个位置,'\0'前一个位置。
	}
	return i - p;//指针减去指针所得的值是他们之间相隔的个数。

}
int main(){
	char *arr = "abcdefg";
	int num = 0;
	num = my_strlen(arr);
	printf("%d", num);
	system("pause");
	return 0;
}

注:因为strlen函数返回的是个无符号数,如果出现下列情况

return strlen("abc")-atrlen("abcdef");

本来结果应该是-3,但是由于返回的是个无符号数,所以符号位的1会被认为是数值,那么返回的数字就是个大于0的数。这是strlen这个函数的易错点。

二、模拟实现strcpy函数
char* strcpy(char* destination ,const char* source);
功能:把从source地址开始的且含有NULL的字符串复制到以destination地址开始的字符空间里面去。

  • 源字符串必须以’\0’结束
  • 会将源字符串中的’\0’拷贝到目标空间去。
  • 目标空间必须足够的大,以确保能够存放源字符串。
  • 目标地址必须可变。

函数实现:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <Windows.h>
#include <assert.h>
//指针减指针方法实现
int my_strlen(const char *p){
	assert(p);//排除空指针
	char *i = p;
	while (*i != '\0'){
		i++;//让指针挪到字符串最后一个位置,'\0'前一个位置。
	}
	return i - p;//指针减去指针所得的值是他们之间相隔的个数。

}
//strcpy函数实现
void my_strcpy(char *dest,const char *src){//因为是把arr2里的字符串复制到arr1中,所以arrr2中的字符串不需要修改,为了防止程序出现了错误,加上const(不允许修改)
	assert(dest!=NULL);//判断是否为空指针,如果为控股指针则打印出错误信息
	assert(src!=NULL);
	if (my_strlen(dest) - my_strlen(src) < 0){//当目的字符数组的长度小于源字符数组长度,则打印错误提示,退出my_strcpy函数
		printf("目的字符数组的长度小于源字符数组长度");
		return ;
	}
	else{
		while (*src != '\0'){//依次将arr2中的字符复制到arr1中,包括'\0'
			*dest = *src;
			dest++;
			src++;
		}
		*dest = *src;
		return;
	}
}
int main(){
	char arr1[] = "abcdef";
	char arr2[] = "qwe";
	my_strcpy(arr1, arr2);
	printf("%s", arr1);
	system("pause");
	return 0;
}

my_strcpy函数部分还可以更加精炼一点

//因为是把arr2里的字符串复制到arr1中,所以arrr2中的字符串不需要修改,为了防止程序出现了错误,加上const(不允许修改)
void my_strcpy(char *dest,const char *src){
//判断是否为空指针,如果为控股指针则打印出错误信息
	assert(dest!=NULL);
	assert(src!=NULL);
	//当目的字符数组的长度小于源字符数组长度,则打印错误提示,退出my_strcpy函数
	if (my_strlen(dest) - my_strlen(src) < 0){
		printf("目的字符数组的长度小于源字符数组长度");
		return ;
	}
	else{
	//依次将arr2中的字符复制到arr1中,包括'\0'
		while (*dest++ = *src++);
		*dest = *src;
		return;
	}
}

三、模拟实现strcat函数
strcat(char dest,const char src);
功能:将源字符数组追加到目的字符数组后面。

  • 目标字符数组的空间必须足够大,能容纳源字符串的内容。
  • 源字符串必须以’\0’结束。
  • 目标空间必须可修改。
    1、strcat函数模拟实现
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <Windows.h>
#include <assert.h>
#define NUM 30
//strcat函数模拟实现
void my_strcat(char *dest, const char *src){
	//assert(dest != NULL);//判断字符指针不能为空指针
	assert(src != NULL);
	if ( NUM< ( strlen(dest) + strlen(src) ) ){//如果目标空间容纳不下源字符串的追加,则退出函数
		printf("目标字符数组空间过小");
		return;
	}
	else{
		while (*dest != '\0'){//找到目的字符数组的末尾
			dest++;
		}
		while (*src != '\0'){//开始追加
			*dest++ = *src++;
		}
		*dest = *src;//把源字符串中的'\0'放进目标字符数组中
		return;
	}
}
int main(){
	char arr1[NUM] = "abcdef";
	char arr2[] = "qwe";
	my_strcat(arr1, arr2);
	printf("%s", arr1);
	system("pause");
	return 0;
}

2、strcat函数给自己追加会发生什么呢?
如果strcat函数给自己追加的话,那么原来的‘\0’的位置会被修改,就可能会导致函数死循环。
三、模拟实现strcmp 函数
int strcmp(const char* str1,const char* str2);
标准规定

  • 第一个字符串大于第二个字符串,则返回大于0的数字
  • 第一个字符串等于第二个字符串,则返回0
  • 第一个字符串小于第二个字符串则返回小于0的数字
    注:这里比较的是ascii码值的大小。
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <Windows.h>
#include <assert.h>
//strcmp函数实现
int my_strcmp(const char* p1,const char *p2){
	assert(p1);
	assert(p2);
	while ((*p1) == (*p2)&&(*p1!='\0')){//找到第一个不相等的字符
		p1++;
		p2++;
	}
	if ((*p1) == (*p2)){//如果最后一个字符相等且等于'\0' ,则代表两个字符串完全相等,返回0
		return 0;
	}
	else if ((*p1) > (*p2)){//第一个字符串大于第二个字符串,则返回1
		return 1;
	}
	else if ((*p1) < (*p2)){//第一个字符串小于第二个字符串,则返回-1
		return -1;
	}
}
int main(){
	char arr1[NUM] = "abcdef";
	char arr2[] = "abc";
	int ret = my_strcmp(arr1, arr2);
	printf("%d", ret);
	system("pause");
	return 0;
}

结尾:上述都是长度不受限的字符串函数,对字符串的操作都是遇到了’\0’停止,这样就有可能发生越界访问,产生不安全。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值