字符串函数

字符串函数

1. strlen

size_t strlen (const char* str);
(1) 它是用来求字符串的长度
(2)使用strlen必须是字符串,并且他必须进行参数校验
(3)用代码来实现它,如下:

size_t strlen(const char* str) {
	//两种校验方式
	//此处校验只能校验空指针,不能校验野指针
	/*if (str == NULL) {
	return 0;
	}*/
	//assert是"断言",是一个宏.
	assert(str != NULL);
	size_t size = 0;
	while (str[size] != '\0') {
		size++;
	}
}

注意:此处参数校验可以使用两种方式一种是if,另一种是assert,这两种比较if比较温和,assert比较激烈.使用assert时必须包含头文件"#include <assert.h>";
上面代码中的size_t一般都是8个字节的无符号整数

2. strcpy

char* strcpy(char* destination,const char* sourse);
(1) 它是用来拷贝字符串的
(2) 用代码来实现它,如下:

char* myStrcpy(char* dest, const char* src) {
	assert(dest != NULL);
	assert(src != NULL);
	int i = 0;
	while (src[i] != '\0') {
		dest[i] = src[i];
		i++;
	}
	dest[i] = '\0';
	return dest;
}
3. strcat

char* strcat (char* destination,const char* sourse);
(1) 它是用来字符串拼接的
(2) 用代码来实现它,如下:

char* myStrcat(char* dest , const char* src ) {
	assert(dest != NULL);
	assert(src != NULL);
	//先找dest的结束位置
	int destTail = 0;
	while (dest[destTail] != '\0') {
		destTail++;
	}

```c
	//当循环结束的时候,destTail就指向\0的位置
	//mystrcpy(dest + destTail, src);
	int i = 0;
	while (src[i] != '\0') {
		dest[destTail + i] = src[i];
		i++;
	}
	//最后把dest最后的位置设为\0
	dest[destTail + i] = '\0';
	return dest;
}
4. strcmp

int strcmp ( const char * str1, const char * str2 );
(1) 它是用来比较字符串是否相等
(2)比较规则就是字典序(谁在前谁小)
(3) 用代码来实现它,如下:

int myStrcmp(const char* str1, const char* str2) {
	assert(str1 != NULL);
	assert(str2 != NULL);
	const char* p1 = str1;
	const char* p2 = str2;
	while (*p1 != '\0' && *p2 != '\0') {
		if (*p1 < *p2) {
			return -1;
		}
		else if (*p1 > *p2) {
			return 1;
		}
		else {//相等就是比较下一个字符
			p1++;
			p2++;
		}
	}
	//两个字符串不一样长
	if (*p1 < *p2) {
		return -1;
	}
	else if (*p1 > *p2) {
		return 1;
	}
	else {
		return 0;
	}
}

注意:大部分编程语言都是根据==来比较的,但C和Java例外

5. strncpy

char* strncpy (char* destination,const char* source,size_t num);
(1) 他也是拷贝字符串,但是它多了个num,是为了避免出现dest空间不够的情况,它限制长度,确实能够防止内存越界,但很可能只拷贝了一般(这很可能成为一个bug)
(2) 用代码实现它,如下:

char* myStrncpy(char* dest, const char* src, size_t num) {
	assert(dest != NULL);
	assert(src != NULL);
	assert(num != 0);
	int i = 0;
	while (src[i] != '\0' && i < num) {
		dest[i] = src[i];
		i++;
	}
	//有两种情况导致循环结束
	//1)src遇到\0,后续把dest剩余部分都设成\0
	//2)i=nmu,函数直接结束即可(这种情况会被下面的while给包含)
	/*if (i == num) {
		return dest;
	}*/
	while (i < num) {
		dest[i] = '\0';
		i++;
	}
	return dest;
}

注意: 1. 当num比src小的时候,会在后面补充上\0
2. 当num比src小的时候,只拷贝了num个字符,这样不会拷贝\0
3. num的数值,必须要保证dest能够容纳的下(要考虑\0的情况)

6. strncat

char* strncat (char* destination,const char* sourse,size_t num);
(1) 拼接前num个字符串
(2) 用代码来实现它,如下:

char* myStrncat(char* dest, char* src, size_t num) {
	assert(dest != NULL);
	assert(src != NULL);
	assert(num != 0);
	//先找dest末尾
	size_t destTail = 0;
	while (dest[destTail] != '\0') {
		destTail++;
	}
	size_t i = 0;
	while (src[i] != '\0' && i < num) {
		dest[destTail + i] = src[i];
		i++;
	}
	//循环结束有两种情况
	//1)src[i]=>\0,需要给dest末尾(dest[destTail+i])设为\0
	//2)i==num,也需要给dest末尾加\0
	dest[destTail + i] = '\0';
	return dest;
}
7. strncmp

int strncmp (const char* destination, const char* sourse, size_t num);
(1) 只比较前num个字符(比较规则任为字典序)
(2) 用代码来实现它,如下:

int myStrncmp(const char* str1, const char* str2, size_t num) {
	assert(str1 != NULL);
	assert(str2 != NULL);
	assert(num != 0);
	size_t i = 0;
	while (str1[i] != '\0' && str2[i] != '\0' && i < num) {
		if (str1[i] < str2[i]) {
			return -1;
		}
		else if (str1[i] > str2[i]) {
			return 1;
		}
		else {
			i++;
		}
	}
	//循环结束有三种情况
	//1)str1[i]=='\0'
	//2)str2[i]=='\0'
	// 	   这两种情况视为一种,谁先结束,谁就更小
	//3)i==num
	if (i == num) {
		return 0;
	}
	return str1[i] - str2[i];
}
8. strstr

const char * strstr ( const char * str1, const char * str2 );
(1) 它是用来判定一个字符串是否包含另一个
(2) 用代码来实现,如下:

char* mystrstr(const char* str1, const char* str2) {
	assert(str1 != null);
	assert(str2 != null);
	assert(*str1 != '\0');
	assert(*str2 != '\0');
	const char* black = str1;
	//外层循环是从black从str1的哪个位置开始找子串
	while (*black != '\0') {
		char* red = black;
		char* sub = str2;
		//里层循环就是从black开始判定当前这个子串是否和str2相等
		while (*red!='\0'&&*sub!='\0'
			&&*red == *sub) {
			red++;
			sub++;
		}
		//循环结束有三种可能
		//1.*red==\0
		//2.*sub==\0
		//3.*red!=*sub
		/*if (*red == '\0' || *red == *sub) {
			black++;
			continue;
		}*/
		if (*sub == '\0') {
			return black;
		}
		black++;
	}
	return null;
 }
9. strtok

char* strtok(char* str, const char* delimiters);
(1) 它是用来切分字符串的
(2) strtok的缺点:1. 需要多次调用才能完成功能,使用起来比较复杂
2. 多次调用过程中的参数不同
3. 调用过程中会调用原来的字符串
4. strtok内部使用静态变量,记录上次调用的位置,这会导致线程不安全.

10. memcpy

void* memcpy(void* destination,const void* source,size_t num);
(1) 他是把一块内存中的数据拷贝到另一个内存中
(2) 用代码来实现它,如下:

void* myMemcpy(void* dest, const void* src, size_t num) {
	assert(dest != NULL);
	assert(src != NULL);
	assert(num != 0);
	//按照字节为单位进行拷贝
	char* cdest = (char*)dest;
	const char* csrc = (const char*)src;
	for (size_t i = 0; i < num; i++) {
		cdest[i] = csrc[i];
	}
	return dest;
}

注意:void* 是一种特殊的指针,只知道地址,不知道大小(各种类型的变量都可以赋值给void*),mem系列的函数也是在"#include <string.h>的头文件下的.

11. memmove

void* memmove(void* destination,const void* source,size_t num);
(1) 在字符串出现重叠的时候,字符串拷贝用这个函数
(2) 用代码来实现它,如下:

void* myMemmove(void* dest, const void* src, size_t num) {
	char* cdest = (char*)dest;
	const char* csrc = (const char*)src;
	if (csrc <= cdest && cdest <= csrc + num) {
		//内存重叠,反着拷贝
		for (size_t i = num; i > 0; i--) {
			cdest[i - 1] = csrc[i - 1];
		}
		return dest;
	}
	else {
		//不重叠就正着拷贝
		for (size_t i = 0; i < num; i++) {
			cdest[i] = csrc[i];
		}
		return dest;
	}
}
12. memcmp

int memcmp (voidptr1,const void ptr2,size_t num);
(1)它是用来比较两个内存中内容大小关系(他没有什么意义)
(2) 用代码来实现它,如下:

int myMemcmp(const void* ptr1, const void* ptr2, size_t num) {
	assert(ptr1 != NULL);
	assert(ptr2 != NULL);
	assert(num != 0);
	const char* cptr1 = (const char*)ptr1;
	const char* cptr2 = (const char*)ptr2;
	for (size_t i = 0; i < num; i++) {
		if (cptr1[i] < cptr2[i]) {
			return -1;
		}
		else if (cptr1[i] > cptr2[i]) {
			return 1;
		}
		else {
			continue;
		}
	}
}
13. memset

void* memset(void* ptr , int value,size_t num);
(1)它是用来将某块内存中的内容设定为指定值的
(2) 用代码来实现它,如下:

void* myMemset(void* ptr, int value, size_t num) {
	assert(ptr != NULL);
	assert(num != 0);
	char* cptr = (char*)ptr;
	for (size_t i = 0; i < num; i++) {
		cptr[i] = (char)value;
	}
	return ptr;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值