- 本篇会加入个人的所谓‘鱼式疯言’
- ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言,而是理解过并总结出来通俗易懂的大白话,我会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的,可能说的不是那么严谨.但小编初心是能让更多人能接受我们这个概念
  
前言
在本篇文章中小编主要讲解以下内容
 💕1.字符分类函数和字符转化函数
 2. strlen 函数
 3. strcpy 函数和 strncpy 函数
 4. strcat 函数和 strncat 函数
 5.strcmp 和 strncmp 函数
 6. strstr 函数
 7. strtok 函数💕
 是不是感觉像高中背英语单词一样,怎么那么多哇,没关系,接下来让小编一一介绍,让大家能够在理解的基础上进行记忆。
 💖💖💖下面,开始吧!!!
一.字符分类函数和字符转化函数
1.字符分类函数
C语⾔中有⼀系列的函数是专⻔做字符分类的,也就是⼀个字符是属于什么类型的字符的?
 这下我们就需要用到字符分类函数:
 
 这些函数的使⽤都需要包含⼀个头⽂件是 ctype.h
 下面小编就举例一部分相关函数给友友们示范一下
 //各种字符函数_test
#include<stdio.h>
#include<ctype.h>
int main()
{
	char ar = getchar();
	printf("%d\n",isalnum(ar));
	if (isalnum(ar))
	//判断成立,返回非零,否则为0.
	{
		printf("小写字母,大写字母,或数字\n");
	}
	if (islower(ar))
	{
		printf("小写字母\n");
	}
	else if (isupper(ar))
	{
		printf("大写字母\n");
	}
	else if (isdigit(ar))
	{
		printf("数字\n");
	}
	else if (isspace(ar))
	{
		printf("各种换行,空格,制表符\n");
	}
	else if (ispunct(ar))
	{
		printf("标点\n");
	}
	else
	{
		printf("啥都不是\n");
	}
	return 0;
}

 通过上面示范我们看到了字符分类函数的使用很简单
 只需要把字符或字符变量放在函数的参数部分
 如果该字符满足判断条件就返回非0,否则就返回0.
2.字符转化函数
//大小写转化_test
#include<stdio.h>
#include<ctype.h>
int main()
{
	
	char a[20] = "HeLLo MYstrl";
	char* p=a;
	while (*p)
	{
		if (isupper(*p))
		{
			*p=tolower(*p);
		}
		putchar(*p);
		p++;
	}
	return 0;
}

 字符串转化函数的要义:
 以大写字母转小写字母为例,我们可以看到,当字母为小写时,我们无须转化,当字母为大写时就会自动转化
二.strlen函数
1. strlen 函数基本形式
返回类型:size_t <=> unsigned(无符号整型)
 参数:const 修饰的字符类型指针
2.使用范例
#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[20] = "abcde";
	printf("%zd", strlen(arr1));
	//返回类型是size_t,要用%zd打印
	return 0;
}

3.错误示范
#include <stdio.h>
#include <string.h>
int main()
{
	const char* str1 = "abcdef";
	const char* str2 = "bbb";
	if (strlen(str2) - strlen(str1) > 0)
	{
		printf("str2>str1\n");
	}
	else
	{
		printf("srt1>str2\n");
	}
	return 0;
}

 看到这里的小伙伴是不是很费解啊,是不是想连发连发3个 why
 😲😲😲why why why???
 有没有小伙伴想到呢?
 怎么都不说,都那么低调么?
 不说的话,那只能小编来说啦!💖💖💖
 先说说函数实现原理和细节吧
所以聪明的你
 也就知道小编的要说的是哪一点了
 没错,我们要注意他的返回类型是size_t是无符号整型
 两个无符号整型相减必然还是无符号整型,所以就一定不可以出现负数哦!
 那怎么比较呢,请往下 look
#include <stdio.h>
#include <string.h>
int main()
{
	const char* str1 = "abcdef";
	const char* str2 = "bbb";
	if ((int)strlen(str2) - (int)strlen(str1) > 0)
	{
		printf("str2>str1\n");
	}
	else
	{
		printf("srt1>str2\n");
	}
	return 0;
}

 我们只需要强制转化成 有符号整型 int 就可以比较啦😁
这里是不是还想到还有一种类型自动转化的含义呢?
 什么意思呢?就是说现在是两个无符号整型是这样子,如果一边是 无符号 一边是 有符号 那是怎么样的呢?
#include<stdio.h>
#include<string.h>
int main()
{
	
	if (strlen("abc")>-1)
	{
		printf("该字符串个数>-1\n");
	}
	else
	{
		printf("该字符串个数<=-1");
	}
	return 0;
}

鱼式疯言
4.模拟strlen函数实现
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<assert.h>
//模拟strlen函数的三钟方法
int my_strlen1(const char* st)
//方法一:指针加减常数法
//用const 锁定 st的数据
//我们只传参,不改变
{
	int count = 0;
	assert(st);
	//判断st是否是NULL,再执行.
	while (*st)
	{
		count++;
		st++;
	}
	return count;
}
int my_strlen2(const char* st)
//方法二:指针减指针法
{
	const char* begin = st;
	assert(st && begin);
	while (*st)
	{
		st++;
	}
	return (int)(st - begin);
}
//方法三:用函数递归实现不创建临时变量计算字符串长度.
int my_strlen3( char* str)
{
	if (*str=='\0')
	{
		return 0;
	}
	else
	{
		return 1 + my_strlen3(++str);
		//此处用++str或 str+1,不可用str++,为什么呢?
		//因为我们要明白的是当str进入时就要递归地址就要向右走
		//str++还是用的是str.
	}
}
int main()
{
	char arr1[] = "abcdef";
	//int sz=my_strlen1(arr1);
	//int sz=my_strlen2(arr1);
	int sz=my_strlen3(arr1);
	printf("%d", sz);
	return 0;
}

这里小编提供了三种方法来实现我们的 strlen 函数,有兴趣的小伙伴可以尝试跟着小编的方法来模拟一下哦💕💕💕
三.strcpy函数和strncpy函数
1.styrcpy函数基本形式
char* strcpy(char * destination, const char * source )
 返回类型:char* 指针类型
 参数:char* 指针的目标字符,char* 指针的源字符。
2.strcpy使用范例
#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[30] = "abcde";
	char arr2[] = "my_boy";
	printf("%s", strcpy(arr1, arr2));
	return 0;
}

 小小的说明一下,想必友子们都看到了,strcpy 的作用就是把 arr1 的字符串完完整整的拷贝到arr2 中,而在这里能直接打印的原因是因为 strcpy 返回到 arr1 的首元素的地址。
3.strcpy的模拟实现
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<assert.h>
char* my_strcpy1(char* ar1, const char* ar2)
//普通版本_传字符同时向右走
{
	assert(ar1 && ar2);
	char* retn = ar1;
	while (*ar2)
	{
		*ar1 = *ar2;
		ar1++;
		ar2++;
	}
	//跳出时还要把\0赋上去.
	*ar1 = *ar2;
	return retn;
}
char* my_strcpy2(char* ar1, const char* ar2)
//高端版本_test
{
	char* retn=ar1;
	while ( *ar1++ = *ar2++)
	//ar2先赋值后++,arr1在得到值++.
	//当我们ar2到达\0时,我们就可先赋值再判断.
	{
		;
	}
	return retn;
}
int main()
{
	char arr1[30] = "abcde";
	char arr2[] = "my_boy";
	printf("%s", my_strcpy2(arr1, arr2));
	return 0;
}

鱼式疯言
当我们需要打印字符串时,我们只需要知道字符串的首个字符的地址,就可以用 %s 输出整个字符串啦!!!😊😊😊
4.strncpy使用范例
#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "**************";
	char arr2[] = "hello bit";
	printf("%s\n", strncpy(arr1, arr2, 3));
	printf("%s\n", strncpy(arr1, arr2, 5));
	printf("%s\n", strncpy(arr1, arr2, 10));
	printf("%s\n", strncpy(arr1, arr2, 12));
	//这里充分证明了用strncpy是代入\0的.
	return 0;
}

5.模拟strncpy实现
#define _CRT_SECURE_NO_WARNINGS
//strncpy_test
#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "**************";
	char arr2[] = "hello bit";
	printf("%s\n", strncpy(arr1, arr2, 3));
	printf("%s\n", strncpy(arr1, arr2, 5));
	printf("%s\n", strncpy(arr1, arr2, 10));
	printf("%s\n", strncpy(arr1, arr2, 12));
	//这里充分证明了用strncpy是不代入\0的.
	return 0;
}

这里的strncpy和strcpy的唯一区别就是能够在arr1内部指定拷贝多少字符
 达到便利的效果。
 能保证拷贝字符的安全性,不至于因为arr2字符长度过大导致非法访问。
 什么???
 居然有宝子问,什么是非法访问,请不懂宝子们移步我们下面的鱼式疯言了解了解。
鱼式疯言
非法访问:
 当一个数组长度已经确定好了,如果超出这个数组长度去访问,我们就会形成非法访问
 😵😵😵简而言之就是占别人的地盘了!!!
四.strcat函数和strncat函数
1.strcat函数基本形式
char strcat(char dest, const charsrc)
 返回类型: char 指针类型
 参数:char* 类型目标字符和 const 修饰的 char* 类型的源字符。
2.strcat使用范例
#include<stdio.h>
#include<string.h>
int main()
{
	char arr1 [10] = "abcde";
	char arr2 [10] = "fegh";
	//先覆盖arr1的\0,再用arr2追加。
	printf("%s", strcat(arr1, arr2));
	return 0;
}

 诸位仁兄都看到了吧!!!
 这个strcat函数主要是把arr2的字符追加arr1后面,从而达到补字符串的效果。
3.strcat模拟实现
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<assert.h>
//模拟实现strcat函数的拉长
char* my_strcat(char* atr1,const char*atr2)
//atr1为目标字符串。此处不需要加const锁定。
{
	assert(atr1 && atr2);
	char* p = atr1;
	while (*atr1)
	{
		atr1++;
	}
	//先让目标字符串到达\0.
	while (*atr1++=*atr2++)
	{
		;
		//最好这里用空语句.代表这里不需要加语句
	}
 //再赋值即可
	return p;
}
int main()
{
	char arr1[40] = "hello ";
	char arr2[] = "bit";
	printf("%s", my_strcat(arr1, arr2));
	return 0;
}

4.strncat范例
#include<stdio.h>
#include<string.h>
int main()
{
	char arr1 [10] = "abcde**";
	char arr2 [10] = "fegh";
	//先覆盖arr1的\0,再用arr2中选定的部分字符追加。
	//并带上\0.
	printf("%s", strncat(arr1, arr2,2));
	return 0;
}

 • 源字符串必须以 ‘\0’ 结束。
 • ⽬标字符串中也得有 \0 ,否则没办法知道追加从哪⾥开始。
 • ⽬标空间必须有⾜够的⼤,能容纳下源字符串的内容。
 • ⽬标空间必须可修改。
5.模拟strncat实现
#define _CRT_SECURE_NO_WARNINGS
 #include<stdio.h>
 #include<assert.h>
 //模拟实现strncat字符追加
 char* my_strncat(char* p1, const char* p2, int count)
 {
 assert(p1 && p2);
 char* stu = p1;
 while (p1)
 {
 p1++;
 }
 //注意这里跳到\0后的\0就打印不出来啦.
 while (count–)
 {
 p1 = p2;
 p1++;
 p2++;
 }
 return stu;
 }
 int main()
 {
 char arr1[15] = “abcdef”;
 char arr2[10] = "“;
 printf(”%s", my_strncat(arr1, arr2, 7));
 return 0;
 }
 
鱼式疯言
追加后面是一定要带 **\0** 的
不然我们是无法打印出正确的追加后的字符的
五. strcmp 和 strncmp 函数
1. strcmp 的基本形式
int my_strcmp (const char * str1, const char * str2)
 返回类型: int
 参数:两个都是 const 修饰的 char* 的指针
2. strcmp 范例
#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[40] = "abcdefghi";
	char arr2[40] = "abcdeu";
	if (strcmp(arr1, arr2) == 1)
	{
		printf("arr1>arr2");
	}
	else if(strcmp(arr1, arr2) == 0)
	{
		printf("arr1=arr2");
	}
	else
	{
		printf("arr1<arr2");
	}
	return 0;
}

- 第⼀个字符串⼤于第⼆个字符串,则返回 ⼤于0 的数字
- 第⼀个字符串等于第⼆个字符串,则返回 0
- 第⼀个字符串⼩于第⼆个字符串,则返回 ⼩于0 的数字
那么如何判断两个字符串?
⽐较两个字符串中对应位置上字符 ASCII码值 的⼤⼩。
 注意这里一定是对应位置哦,以上面的代码为例, arr1 的 a 和 arr2 的 a 进行对比,然后一直对应比下去,直到 arr1 的f的 ASCII 值比 arr2 的 ASCII 小,得出 arr1 比 arr2 小,返回 -1
3. strcmp 的模拟实现
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<assert.h>
// 模拟实现一个strcmp_test
int my_strcmp(const char*p1,const char*p2)
{
	assert(p1 && p2);
	while (*p1 == *p2)
	//先循环判断
	{
		p1++;
		p2++;
		if (*p1 > *p2)
		{
			return 1;
		}
		//一定要在循环内,一旦判断成立就会跳出函数.
		if (*p1 == '\0')
		{
			return 0;
		}
		if (*p1 < *p2)
		{
			return -1;
		}
	}
	
}
int main()
{
	char arr1[30] = "abrbcd";
	char arr2[30] = "abbcd";
	int sz=my_strcmp(arr1, arr2);
	if (sz>0)
	{
		printf("大于\n");
	}
	else if (sz < 0)
	{
		printf("小于\n");
	}
	else
	{
		printf("等于\n");
	}
	return 0;
}

 有兴趣的宝子们可以康康哦😊😊😊
4. strncmp 示范
 #include<stdio.h>
#include<string.h>
int main()
{
	char arr1[20] = "abceg";
	char arr2[20] = "abcfg";
	if (strncmp(arr1, arr2,3) == 1)
	{
		printf("arr1>arr2\n");
	}
	else if (strncmp(arr1, arr2,3) == 0)
	{
		printf("arr1=arr2\n");
	}
	else
	{
		printf("arr1<arr2\n");
	}
	if (strncmp(arr1, arr2, 5) == 1)
	{
		printf("arr1>arr2\n");
	}
	else if (strncmp(arr1, arr2, 5) == 0)
	{
		printf("arr1=arr2\n");
	}
	else
	{
		printf("arr1<arr2\n");
	}
	return 0;
}

 strcmp是全体比较,那么strncmp就选择性比较,比较的原理还是一样的哦.😊😊😊
 在这里小编就不带着大家实现咯,和上面实现的原理差不多哦。
六. strstr 函数
1.strstr 函数的基本形式
char * strstr ( const char * str1, const char * str2);
 返回类型: char*
 函数返回字符串 str2 在字符串 str1 中第⼀次出现的位置
 参数:两个都是 const 修饰的 char* 的指针
2. strstr 的范例
//strstr_test
#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[40] = "abcdef";
	char arr2[40] = "cd";
	printf("%s", strstr(arr1, arr2));
}

3.模拟 strstr 的实现
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<assert.h>
//模拟实现 my_strstr 的实现
char* my_strstr(const char* str1, const char* str2)
{
	char* p1 = (char*)str1;
	char* p2 = (char*)str2;
	//这里是需要两个参数和两个临时变量的
	//一个记住起始位置,一个进行移动判断是否相等
	assert(str1);
	if (str2 == '\0')
	{
		return (char*)str1;
	}
	while (*str1)
		//这里是目标字符遇到\0
		//就意味着我们我们目标字符就遍历完了
		//再也找不到了
	{
		p1 = (char*)str1;
		p2 = (char*)str2;
		while (*p1 == *p2)
		{
			p1++;
			p2++;
			if (*p2 == '\0')
				//只要源字符一遇到\0我们就意味着判断结束
				//找到了
			{
				return(char*) str1;
			}
		}
		str1++;
		//如果源字符再遇到\0之前,还未一直==,
		//目标字符也要跟着移动
	}
	return NULL;
	//str1跳出循环后,就会已NULL空指针的方式返回
}
int main()
{
	char arr1[40] = "abcccdef";
	char arr2[50] = "c";
	char* ch = my_strstr(arr1, arr2);
	if (ch == NULL)
	{
		printf("找不到了\n");
	}
	else
	{
		printf("%s", ch);
	}
}

如果有小伙伴没有看懂的话?💕💕💕
 这里小编就在这里小小说明一下
 我们 strstr 函数呢,主要是找子字符串 arr2 ,然后从找到子字符串开始一直往后输出 arr1.
七. strtok 函数
1. strtok 基本形式
char * strtok ( char * str, const char * sep);
 返回类型: char* 指针类型
 参数: char* 指针和 const 修饰的 char*
 • sep参数指向⼀个字符串,定义了⽤作分隔符的字符集合
 • 第⼀个参数指定⼀个字符串,它包含了 0个 或者多个由 sep字符串中⼀个 或者多个分隔符分割的标
 记。
 • strtok函数找到str中的下⼀个标记,并将其⽤ \0 结尾,返回⼀个指向这个标记的指针。(注:
 strtok函数会改变被操作的字符串,所以在使⽤strtok函数切分的字符串⼀般都是临时拷⻉的内容
 并且可修改。
2.strtok 示例
#include<stdio.h>
#include<string.h>
//strtok_test
int main()
{
	char arr[] = "abcef@12345...zho11111";
	char* p = "@.";
	char*ps1=strtok(arr, p);
	printf("%s\n", ps1);
	char*ps2=strtok(NULL, p);
	printf("%s\n", ps2);
	char* ps3 = strtok(NULL, p);
	printf("%s\n", ps3);
	return 0;
}

 因为这个函数自身比较复杂,实现起来很难让大家接受,所以感兴趣的小伙伴可以自己尝试尝试哦💖💖💖
鱼式疯言
简而言之,言而总之,就要这个strtok函数就是把分隔的各种标点分隔开,唯一使用的细节是先使用原指针arr,还有标点指针,然后在第一个参数一直传空指针就 OK 啦.以上小编介绍的这些字符串实现函数都有一个共同的头文件 string.h
总结
在本章内容我们主要讲解了
💕💕💕- 字符分类函数和字符转化函数
- 各种字符串函数的功能并带着大家去实现
 有:
- strlen 函数来测量字符串长度的。
- strcpy 函数和 strncpy 函数来拷贝字符的。
- strcat 函数和 strncat 函数来追加字符的。
 5.strcmp 和 strncmp 函数比较字符大小的。
- strstr 函数寻找部分字符的。
- strtok 函数分段字符的。
 可谓是收获颇多…💖💖💖
💖💖💖本次博文就到这里了,感觉各位小伙伴的赏脸品读小编写的拙作哦,如果觉得小编写的还不错的咱可支持三关下,不妥当的咱评论区指正,希望我的文章能给各位家人们带来哪怕一点点的收获就是小编创作的最大动力💖💖💖
 










