C语言字符类库函数

 

目录

 

1.前言

2. 字符类

2.1字符分类函数

2.2字符转换函数 

3.字符串类 

3.1 strlen函数的模拟实现 

3.2 strcpy函数的使用和模拟实现

3.3 strcat函数的使用和模拟实现

3.4strcmp函数的使用和模拟实现

3.5strstr函数的使用和模拟实现

 3.6strtok函数的使用

3.7strerror函数的使用 

4.总结 


1.前言

  大家平时在刷题的时候是否遇到一些比较麻烦的处理字符,字符串函数的题目。比如,将字符进行分类,大小写转化,计算字符串个数,拷贝字符串等。其实C语言提供了一系列库函数来帮组程序员实现对字符,字符串的快速处理。今天我们就来着重了解它们,并试着进行模拟实现。


2. 字符类

2.1字符分类函数

C语⾔中有⼀些的函数是专门做字符分类的,这些函数的使用都需要包含同一个头文件<ctype.h>

表格中的函数使用都非常类似,我们就以函数isupper为例:

int isupper (int c);

isupper是用来判断参数c是否为大写字母的。若参数c为大写字母,则返回非0整数;不为大写字母,则返回0。

#include<ctype.h>
int main()
{
	char a;
	scanf("%c", &a);
	if (isupper(a))//函数返回值最为判断条件
		printf("大写字母\n");
	else
		printf("不为大写字母\n");

	return 0;
}

模拟实现思路 :

因为字符在内存中以ASCII值的形式储存,并且大小写字母的ASCII值是连续的,那么我们直接判断字符的ASCII值是否在该范围内,从而判断该字符是否为大(小)字母。

                     大写字母 A~Z ASCII:65~90                           小写字母:a~z ASCII:97~122

2.2字符转换函数 

我们在刷题时会遇到将字符进行大小写转换,而C语言中提供了两个字符转换函数——tolower toupper。

int tolower(int c);//参数为大写字母,则返回其对应的小写字母
int toupper(int c);//参数为小写字母,则返回其对应的大写字母

模拟实现思路 :

因为同一个字母的大小写的ASCII刚好相差32,所以我们只需要将字母的ASCII值加上(减去)32就能获得对应的小写(大写)字母。

下面运用字符分来函数和字符转换函数来实现将一个字符串进行大小写转化:

int main()
{
	char arr[15] = "Hello World";
	int i = 0;
	while (arr[i])
	{
		if (islower(arr[i]))
			arr[i]=toupper(arr[i]);
		else
		arr[i]=tolower(arr[i]);
		i++;
	}
	printf("%s", arr);
	return 0;

}


3.字符串类 

3.1 strlen函数的模拟实现 

注意:
①字符串以'/0'作为结束标志,这里的终止字符指的就是'/0'
strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' )
参数指向的字符串必须要以 '\0' 结束 ,否则函数返回的结果就是随机值。
strlen函数返回值的类型为size_t 即无符号整形。
⑤使用时记得包含头文件<string.h>

模拟实现思路: 

思路一:首先想到使用指针,又因为字符串的特性——以'/0'结尾,我们可以利用这一点。即让计算机从首字符开始往后数,遇到'/0'后停下,再使用局部变量记录个数,最后返回用来计数的局部变量即可。

size_t M_strlen(char* p)
{
	size_t count = 0;
	while (*p++)
	{
		count++;
	}
	return count;
}

int main()
{
	char arr[] = "abcdef";
	printf("%zd",M_strlen(arr));
	return 0;
}

思路二: 思路一采用的是迭代,其实也可以尝试使用递归来实现。

#include<assert.h>
size_t m_strlen(char* p)
{
	assert(p);//防止p为空指针
	if (*p == 0)//限制条件
		return 0;
	else
		return 1 + m_strlen(p + 1);
}

 

①这里函数递归的限制条件是解引用指针p得到的值不为0,而字符串的结束标志'/0'的ASCII值就是0。所以递归越深入,参数就会越接近限制条件。②因为我们的设想是每当遇到一个不为'/0'的字符时,函数返回值加1,否则就保持不变(加0)。所以不满足限制条件就直接返回0反之就是1加上下一层函数递归的返回值

3.2 strcpy函数的使用和模拟实现

 

#include<string.h>
int main()
{
	char arr1[] = "xxxxxxxxxxxxxxx";
	char arr2[] = "hello world";
	strcpy(arr1, arr2);
	printf("%s", arr1);

	return 0;
}

这里直接打印“hello world” ,说明拷贝源字符串时也包含'/0'

注意 :

①  源字符串必须以 '\0' 结束。
② 拷贝源字符串时, 会将源字符串中的 '\0' 拷贝到目标空间。
目标空间必须足够大 ,以确保能存放源字符串。
④目 标空间必须可修改

模拟实现思路:

我们只需要将源字符串中的字符逐一地赋值到目标字符串中对应的字符内即可。

#include<string.h>
#include<assert.h>
char* m_strcpy(char* destination, const char* source)
{
	assert(destination);
	assert(source);
	char* p = destination;
	while (*destination++ = *source++)
	{//先解引用在加加访问下一个字符
		;//空语句
	}
	return p;//返回目标字符串的起始地址
}
int main()
{
	char arr1[] = "xxxxxxxxxxxxxxx";
	char arr2[] = "hello world";
	m_strcpy(arr1, arr2);
	printf("%s", arr1);

	return 0;
}

 

3.3 strcat函数的使用和模拟实现

#include<string.h>
int main()
{
	char arr1[10] = "acde";
	char arr2[] = "fghi";
	strcat(arr1, arr2);
	printf("%s\n", arr1);
	strcat(arr1, arr1);//尝试字符串自己连接自己
	printf("%s\n", arr1);

	return 0;
}

注意 :

源字符串和目标字符串必须以 '\0' 结束 。后者用来确定连接点 。
③ ⽬标字符串空间 必须足够的大 ,能容纳下源字符串的内容。
④⽬标字符串空间 必须可修改
字符串无法实现给自己与自己连接。

 

模拟实现思路:

想要实现字符串连接,只需要从目标字符串的'/0'处开始将源字符串中的字符逐一赋值到目标字符串中即可。

#include<string.h>
char* m_strcat(char* destination, const char* source)
{
	char* p = destination;
	while (*++destination)
	{
		;
	}//此时的指针指向目标字符串的/0处
	while (*destination++ = *source++)
	{
		;
	}
	return p;//返回目标字符串起始位置
}
int main()
{
	char arr1[10] = "acde";
	char arr2[] = "fghi";
	printf("%s", m_strcat(arr1, arr2));
	return 0;
}

3.4strcmp函数的使用和模拟实现

 

 

  逐一比较字符串中对应字符的ASCII 值,在第一次出现两字符不相等的情况时,若str1中字符的ASCII值大于str2中的,则返回大于0的整数;反之则返回小于0的整数。

int main()
{
	char arr1[] = "abc";
	char arr2[] = "abd";
	printf("%d",strcmp(arr1, arr2));
	return 0;
}

 

模拟实现思路 :

比较两个字符串,实际上是比较每个字符串对应位置字符的ASCII值的大小。只需要将对应位置字符的ASCII值相减,若结果不为0,则直接返回相减后的结果;若为0,则往后继续比较,直到遇到终止字符'/0'

int m_strcmp(const char* arr1, const char* arr2)
{
	while (*arr1 && *arr2)//遇到终止字符前
	{
		if (*arr1 - *arr2)
		{//相减后的结果不为0时,返回该结果
			return *arr1 - *arr2;
		}
		arr1++;
		arr2++;
	}
	return 0;
}
int main()
{
	char arr1[] = "abc";
	char arr2[] = "abd";
	printf("%d",m_strcmp(arr1, arr2));
	return 0;
}

3.5strstr函数的使用和模拟实现

.

int main()
{
	char arr1[] = "abcdebcde";
	char arr2[] = "cde";
	
	printf("%s", strstr(arr1, arr2));
	return 0;
}

 

模拟实现思路: 

 注:实现字符串查找有一种非常高效的KMP算法,由于本人才疏学浅,还没有理清缘由,所以这里只能给大家带来遍历法,实在抱歉! 

在字符串str1中找到第一次出现的字符串str2,首先就需要再str1中找到与str2中首字符相等的字符,再往后比较第二,三个字符,若之后的字符与str2中的均相等,则返回str1中与str2中首字符相等的指针;若之后的字符与str2中的不相等,则在str1中继续往后寻找与str2首字符相等的字符,直到满足条件,或者到达str1的末尾。

char* m_strstr( const char* str1,const char* str2)
{
	char* p2 = (char*)str2;//const char*需要强制转化为char*
	char* p1 = (char*)str1;
	if (!*str2)//*str2为/0时
		return ((char*)str1);
	while (*(char*)str1++)//未到达字符串str1末尾
	{
		p1 = (char*)str1;//指针p1回str1下一字符的位置
		p2 = (char*)str2;//指针p2回到起始位置
		while (*p2)//未到达字符串str2末尾
		{
			if (*p2 != *p1)
				break;
			p2++;
			p1++;
		}
		if (*p2 == 0)
			return (char*)str1;
	}
	return NULL;
}
int main()
{
	char arr1[] = "abcdecdecde";
	char arr2[] = "cde";
	
	printf("%s", m_strstr(arr1, arr2));
	return 0;
}

 

 3.6strtok函数的使用

1 char * strtok ( char * str, const char * sep);

 注意:

①参数sep指向⼀个字符串, 定义了用作分隔符的字符集合
第⼀个参数指定⼀个字符串,它包含了0个或者多个由sep字符串中⼀个或者多个分隔符分割的标记。
③ strtok函数 找到str中的下⼀个标记,并将其用 \0 结尾 返回一个指向该标记开头的指针
④strtok函数会改变被操作的字符串,所以在使 用strtok函数切分的字符串⼀般都是临时拷贝的内容
并且可修改。  
⑤strtok函数的第⼀个参数不为 NULL , 函数将找到str中第⼀个标记,并保存它在字符串中的位置。
⑥strtok函数的第⼀个参数为 NULL , 函数将在同⼀个字符串中被保存的标记的位置开始,查找下⼀个标记。
⑦ 如果字符串中 不存在更多的标记,则返回 NULL 指针
int main()
{
	char arr[] = "2023.12.26";
	char* sep = ".";
	printf("%s\n", strtok(arr, sep));//第一个参数不为NULL,找到第一个标记
	printf("%s\n", strtok(NULL, sep));//第一个参数为NULL,找到同一字符串中下一标记
	printf("%s\n", strtok(NULL, sep)); 
	printf("%s\n", strtok(NULL, sep));//不存在更多标记,返回空指针
	return 0;
}

 

3.7strerror函数的使用 

char * strerror ( int errnum );
  strerror函数可以返回参数部分错误码对应的错误信息的字符串地址。
  在不同的系统和C语⾔标准库的实现中都规定了⼀些错误码,这些错误码⼀般是放在头文件<errno.h >中说明的,C语⾔程序启动的时候就会使用⼀个全⾯的变量errno来记录程序的当前错误码。在程序启动的时候errno是0,表示没有错误,当我们在使用标准库中的函数的时候发生了某种错误,就会将对应的错误码,存放在errno中。同时每一个错误码都有其对应的错误信息。strerror函数可以由此将错误对应的错误信息字符串的地址返回。

 

我们来打印0~10这些错误码的对应信息

#include<errno.h>
int main()
{
	int i = 0;
	for (i = 0; i <= 10; i++)
	{
		printf("%2d:%s\n", i,strerror(i));
	}
	return 0;
}

 使用举例:

#include <string.h>
#include <errno.h>
int main()
{
	FILE* pFile;
	pFile = fopen("unexist.text", "r");//以阅读的方式打开不存在的文件unexist.text
	if (pFile == NULL)
		printf("% s\n", strerror(errno));
	return 0;
}

 

4.总结 

我们介绍完了部分处理字符,字符串的库函数。在对其部分进行模拟实现的时候很容易发现,实现这些功能离不开指针。同时,也希望能在各位对指针的理解和使用上产生一点帮助。

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值