C语言之字符串和内存函数


前言

一些常用的字符函数和内存函数


一、字符函数

1.字符串长度

(1)strlen:求字符串长度

size_t strlen(const char *str)
strlen求字符串的长度,就是找到‘\0’就结束。
三种方式模拟实现:
(1)计数器的方法 
(2)递归的方法
(3)指针-指针的方法

计数器的方法 :

//1.计数器的方法
int my_strlen1(const char* str) {
	int count = 0;//记录字符的个数
	assert(str);//断言,字符不为空
	while (*str) {
		count++;
		str++;
	}
	return count;
}

递归的方法 :

//2.递归的方法
int my_strlen2(const char* str) {
	assert(str);
	if (*str == '\0') {
		return 0;
	}
	return 1 + my_strlen2(++str);//递归
}

指针-指针的方法

//3.指针-指针的方法
int my_strlen3(const char* str) {
	assert(str);
	char* start = str;
	while (*str) {
		str++;
	}
	return str - start;//指针减指针的结果是字符的个数
}

2.长度不受限制的字符函数

(1)strcpy:拷贝字符串

strcpy : '\0'也会拷到目标空间、目标空间必须足够大。

strcpy模拟实现 :

// strcpy模拟实现
char* my_strcpy(const char* str1, const char* str2) {
	assert(str1 && str2);
	char* ret = str1;
	while (*str1++==*str2++) {
		;
	}
	return ret;
}

(2)strcat: 字符串追加

strcat: 字符串追加,将str2字符串追加在str1后面,str1空间需要足够大。
//strcat 字符串追加 模拟实现
char* my_strcat(char* str1, const char* str2) {
	assert(str1 && str2);
	char* ret = str1;
	while (*str1) {
		str1++;
	}
	while (*str1 == *str2) {
		;
	}
	return ret;
}
int main() {

	char arr1[20] = "awe";
	char arr2[] = "abcde";
	//strcat 字符串追加
	printf("strcat(arr1,arr2) = %s\n", strcat(arr1, arr2));
	printf("my_strcat(arr1,arr2) = %s\n", my_strcat(arr1, arr2));
	return 0;
}

(3)strcmp: 字符串比较

strcmp:比较字符串的大小。
>0:str1>str2;
=0:str1=str2;
<0:str1<str2.
//strcmp模拟实现
int my_strcmp(const char* str1, const char* str2) {
	assert(str1 && str2);
	while (*str1 == *str2) {
		if (*str1 == '\0') { //如果字符串都相等返回0,退出
			return 0;
		}
		str1++;
		str2++;
	}
	return *str1 - *str2;//返回
}

2.长度受限制的字符函数

比起不受限制的字符函数多了一个条件。需要给出操作的大小num。

(1)strncpy、strncat、strncmp

strncpy:char * strncpy ( char * destination, const char * source, size_t num ); 比起strcpy多了一个限制num。
strncat:char * strncat ( char * destination, const char * source, size_t num );
strncmp:int strncmp ( const char * str1, const char * str2, size_t num );
//长度受限制的字符函数
int main() {
	//长度受限制的字符函数
	//strncpy
	char arr1[20] = "abcdef";
	char arr2[] = "qwu";
	strncpy(arr1, arr2, 3);
	printf("%s\n", arr1);
	//strncat
	printf("%s\n", strncat(arr1, arr2, 2));
	//strncmp
	int ret = strncmp(arr1, arr2, 2);
	if (ret > 0) {
		printf(">\n");
		printf("%d\n", ret);
	}
	else if (ret == 0) {
		printf("=\n");
		printf("%d\n", ret);
	}
	else {
		printf("<\n");
		printf("%d\n", ret);
	}
	return 0;
}

3.字符串查找

(1)strstr

strstr :寻找arr1中有没有arr2,返回第一次出现的地址,如果没有找到返回NULL。

strstr模拟实现 :

//strstr模拟实现
char* my_strstr(const char* str1, const char* str2) {
	assert(str1 && str2);
	char* s1 = str1;
	char* s2 = str2;
	char* cur = str1;
	while (*cur) {
		s1 = cur;
		s2 = str2;
		while (*s1 == *s2) {
			s1++;
			s2++;
		}
		if (*s2 == '\0') {
			return cur;
		}
		cur++;
	}
	return NULL;
}

(2)strtok

strtok :char* strtok(char* str,const char* stp)
stp是一个字符串,里面定义了分隔符
将str按分隔符截断并返回。

注意:strtok是对str本身进行操作,如果不想改变原有字符串,可以用strcpy先拷贝一份。

int main() {
	//strtok
    //char* strtok(char* str,const char* stp)
	//stp是一个字符串,里面定义了分隔符
	//使用
	char str[] = "why@qq.com";
	char stp[] = "@.";
	char buf[20];
	strcpy(buf, str);//拷贝一份
	//输出方式一
	/*printf("%s\n", strtok(buf, stp));
	printf("%s\n", strtok(NULL, stp));
	printf("%s\n", strtok(NULL, stp));*/
	//输出方式二
	char* ch = strtok(buf, stp);
	for (ch; ch != NULL; ch = strtok(NULL, stp)) {
		printf("%s\n", ch);
	}
	//输出方式三
	/*char* tmp;
	tmp = strtok(buf, stp);
	while (tmp != NULL) {
		printf("%s\n", tmp);
		tmp = strtok(NULL, stp);
	}*/
	return 0;
}

4.错误信息报告

strerror

(1)头文件:errno.h
(2)错误码:errno 是一个全局变量
(3)strerror将错误码转换为错误信息
(4)perror()与strerror比较,perror()会将错误信息直接打印
int main() {
	//错误信息报告 
	//将错误码转换为错误信息
	//void perror(const char* string)  
	//perror()会直接打印错误信息
	printf("%s\n", strerror(1));
	printf("%s\n", strerror(2));
	printf("%s\n", strerror(3));
	//int* p = (int*)malloc(40);
	int* p = (int*)malloc(INT_MAX);
	if (p == NULL) {
		printf("%s\n", strerror(errno));
		perror("malloc");
	}
	return 0;
}

5.字符操作

(1)头文件ctype.h
函数条件
iscntrl任何控制字符
isspace空白字符 ’ ‘,’\f’换页,’\n’,’\r’回车,制表符’\t’或者垂直制表符’\v’
isdigit十进制数0-9
isxdigit十六进制数
islower小写字母
isupper大写字母
isalphaa-z/A-Z
isalnuma-z/A-Z/0-9
ispunct变点符号,任何不属于数字或字母的图形字符(可打印)
isgraph任何图形字符
isprint任何可打印字符,包括图形字符和空白字符
tolower()转换为小写字母
toupper()转换为大写字母
int main() {
	//字符操作 ctype.h
	// iscntrl 任何控制字符
	//isspace 空白字符 ' ','\f'换页,'\n','\r'回车,制表符'\t'或者垂直制表符'\v'
	//isdigit 十进制数0-9
	printf("%d\n", isdigit('5'));
	//isxdigit 十六进制数
	printf("%d\n", isdigit('f'));
	char ch1 = 'A';
	char ch2 = 'a';
	//islower 小写字母
	printf("%d\n", islower(ch1));
	//isupper 大写字母
	printf("%d\n", isupper(ch1));
	//isalpha a-z/A-Z
	printf("%d\n", isalpha(ch1));
	//isalnum a-z/A-Z/0-9
	printf("%d\n", isalnum(ch1));
	//ispunct 变点符号,任何不属于数字或字母的图形字符(可打印)
	//isgraph 任何图形字符
	//isprint 任何可打印字符,包括图形字符和空白字符
	//字符转换 tolower() toupper()
	printf("%c\n", tolower(ch1));
	printf("%c\n", toupper(ch2));
	return 0;
}

二、内存函数

1.memcpy

memcpy :将非字符的数组进行拷贝,一个字节一个字节进行拷贝
(自己拷贝到自己本身存在缺陷)

memcpy模拟实现 :

//memcpy模拟实现
//存在缺陷 vs编译器忽略了
void* my_memcpy(void* des, const void* src, size_t count) {
	assert(des && src);
	void* ret = des;
	while (count--) {
		*((char*)des) = *((char*)src);
		des = (char*)des + 1;
		src = (char*)src + 1;
	}
	return ret;
}

2.memove

memove:可以实现重叠内存拷贝,解决memcpy存在的缺陷。
例:
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
//memmove(arr1, arr1+2, 20);
//memmove(arr1+2, arr1, 20);	

memove模拟实现 :

//memmove模拟实现
void* my_memmove(void* des, const void* src, size_t count) {
	assert(des && src);
	char* ret = des;
	//前-后
	if (*((char*)des) < *((char*)src)) {
		while (count--) {
			*((char*)des) = *((char*)src);
			des = (char*)des + 1;
			src = (char*)src + 1;
		}
	}
	else {
		//后-前
		while (count--) {
			*((char*)des + count) = *((char*)src + count);
		}
	}
	return ret;
}

3.memcmp

memcmp:int memcmp ( const void * ptr1, const void * ptr2, size_t num );	
比较从ptr1和ptr2指针开始的num个字节。
该函数是按字节比较的。
(1)返回值 < 0,则表示 str1 小于 str2。
(2)返回值 > 0,则表示 str2 小于 str1。
(3)返回值 = 0,则表示 str1 等于 str2。

注意:该函数是按字节比较的。

4.memset

memset:void * memset ( void * ptr, int value, size_t num );
(1)内存设置,以字节为单位初始化内存。
(2)常用于内存空间初始化。
(3)可以方便的清空一个结构类型的变量或数组。
int main() {
	//memcmp
	int arr1[] = { 1,2,3,4,5,6 };
	int arr2[] = { 1,2,3,4 };
	int ret = memcmp(arr1, arr2, 16);
	printf("%d\n", ret);

	//memset 内存设置 以字节为单位初始化内存
	int arr[] = { 1,2,3,4,5 };
	memset(arr, 6, 16);
	for (int i = 0; i < (sizeof(arr) / sizeof(int)); i++) {
		printf("%p ", arr[i]);
	}

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值