字符函数与字符串函数

前言:

C语言的标准库中有许多字符函数与字符串函数,其存在能够大大减轻许多编程压力,因此,充分了解并能够熟练运用字符函数与字符串函数是很有必要的,在本文中,我们将对于其进行深入了解

正文开始:

一.字符分类函数:

C语言中有一类函数专门用于字符分类,使用时需要包含一个头文件<ctype.h>

函数参数符合条件就返回真(非0)
具体函数如下:

1.iscntrl—任何控制字符
2.isspace—空白字符
3.isdigit—十进制数字
4.isxdigit—十六进制数字
5.islower—小写字母a-z
6.isupper—大写字母A-Z
7.isalpha—字母a-z或者A-Z
8.isalnum—字母或者数字
9.ispunct—标点符号,非任意字母(图形)或者数字
10.isgraph—任何图形字符
11.isprint—任何可打印字符,包括图形与空白字符

示例:
1.

#include<ctype.h>
int main()
{
	int r = isdigit('a');//r=0;
	printf("%d\n", r);
	if (r)
	{
		printf("是十进制字符\n");
	}
	else
	{
		printf("不是十进制字符\n");
	}
	return 0;
}

输出结果为:

不是十进制字符
int main()
{
	int r = islower('a');//r=2;
	printf("%d\n", r);
	if (r)
	{
		printf("是小写字符\n");
	}
	else
	{
		printf("不是小写字符\n");
	}
	return 0;
}

输出结果为:

是小写字符
int main()
{
	//小写字符转大写
	char arr[] = "I am a Chinese";
	int i = 0;
	for (i = 0; arr[i] != '\0'; i++)
	{
		int r=islower(arr[i]);
		if (r)
		{
			arr[i] -= 32;//'a'-'A'=32
		}
		printf("%c", arr[i]);
	}
	
	return 0;
}

输出结果为:

I AM A CHINESE

二.字符转化函数

注:仅适用于字母
大写转小写:tolower
小写转大写:toupper
1次只能够转1个
示例:

int main()
{
	//小写字符转大写
	char arr[] = "I am a Chinese";
	int i = 0;
	for (i = 0; arr[i] != '\0'; i++)
	{
		int r = islower(arr[i]);
		if (r)
		{
			arr[i] = toupper(arr[i]);
		}
		printf("%c", arr[i]);
	}

	return 0;
}

输出结果为:

I AM A CHINESE

字符转换函数的模拟实现:
以toupper函数为例:

char my_toupper(char x)
{
	if (x >= 'a' && x <= 'z')
	{
		x -= 32;
	}
	return x;
}



int main()
{
	//小写字符转大写
	char arr[] = "i am a chinese";
	int i = 0;
	for (i = 0; arr[i] != '\0'; i++)
	{
		int r = islower(arr[i]);
		if (r)
		{
			arr[i] = my_toupper(arr[i]);
		}
		printf("%c", arr[i]);
	}

	return 0;
}

该函数也能够行使字符转换功能

三.strlen函数

前面已讲,详情请看指针–习题练习

注:返回类型:size_t–无符号整型–必定大于等于0

示例:

int main()
{
	if ((strlen("abc") - strlen("abcdef"))>0)
	{
		printf(">\n");
	}
	else
	{
		printf("<=\n");
	}
	return 0;
}

输出结果为

>

证明返回数字大于0,即为无符号整型

strlen函数的另一种模拟实现(第一种在指针–习题练习):

size_t my_strlen(const char* str)
{
	if (*str != '\0')
	{
		return 1 + my_strlen(str + 1);
	}
	else
	{
		return 0;
	}
}

四:字符串函数

1.strcpy

功能:字符串拷贝,拷贝到字符串中的\0为止
参数:两字符串的首元素地址

注:1.以\0结束
2.\0也会被拷贝
3.目标空间必须足够大
4.目标空间必须可被修改(即arr2初始化时不能是常量字符串)

示例:
i

nt main()
{
	char arr1[] = "Hello world!";
	char arr2[] = { 0 };


	//arr2 = arr1;//错误!arr2代表地址,不可修改
	//数组名为地址,地址是一个编号,但地址是常量,无法修改

	
	char*ret= strcpy(arr2, arr1); 

	printf("%s\n", arr2);
	printf("%s\n", ret);


	return 0;
}

输出结果为:

Hello world!
Hello world!

strcpy函数的模拟实现:

两个条件:
1.能够将y代表数组的内容拷贝到x中
2.能够返回y数组的首元素地址

#include<assert.h>

char* my_strcpy(char* x, const char* y)
{
   //x---指针,指向目的空间  //y--指针,指向源头数据
	char* ret = x;
	assert(y && x);//两者均不能为空指针
	while (*x++ = *y++)
	{
		;
	}
	

	return ret;
}
	
int main()
{
	char arr1[] = "Hello world!";
	char arr2[20] = "xxxxxxxxx";



	 my_strcpy(arr2, arr1);

	printf("%s\n", arr2);

	

	return 0;
}

2.strcat–字符串追加
char* strcat(charx,const chary)
x----指针,指向目的空间
y–指针,指向源头数据
返回目标空间起始地址
注:
1.源字符串(x)必须以\0结束
2.目标字符串中也应有\0(从\0开始追加)
3.目标字符串应足够大,能够容纳源字符串内容
4.目标字符串可修改

示例:

int main()
{
	char arr1[20] = "hello \0xxxxxxxx";
	char arr2[] = "world!";
	char*r=strcat(arr1, arr2);
	printf("%s\n", arr1);
	printf("%s\n", r);
	return 0;
}

输出结果为:

hello world!

strcat函数的模拟实现:

两个条件:
1.能够将y代表数组的内容追加到x中
2.能够返回x数组的首元素地址

#include<assert.h>
char* my_strcat(char* x, char* y)
{
	assert(y && x);
	//1.寻找\0
	char* r = x;
	while (*x != '\0')
	{
		x++;
	}
	while (*x++ = *y++)
	{
		;
	}
	return r;
}


int main()
{
	char arr1[20] = "hello \0xxxxxxxx";
	char arr2[] = "world!";
	char* r = my_strcat(arr1, arr2);
	printf("%s\n", arr1);
	printf("%s\n", r);
	return 0;
}

3.strcmp—字符串比较
主要内容前面已讲
功能:从两个字符串首字母开始比较ASCII码值,若相同则比较下一字母

参数:char* a,char* b

返回值:a>b 返回t>0 a<b 返回t<0

示例:

int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abq";
	int r = strcmp(arr1, arr2);
	printf("%d\n", r);
	if (r < 0)
	{
		printf("arr1<arr2\n");
	}
	return 0;
}

输出结果为:

arr1<arr2

strcmp函数的模拟实现:

int my_strcmp(const char* a, const char* b)
{
	assert(a && b);
	while (*a == *b)
	{
		if (*a == '\0')
		{
			return 0;//相等
		}
		a++;
		b++;
	}
	if (*a > *b)
	{
		return 1;
	}
	else
	{
		return -1;
	}
}


int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abq";
	int r = my_strcmp(arr1, arr2);
	printf("%d\n", r);
	if (r < 0)
	{
		printf("arr1<arr2\n");
	}
	return 0;
}

输出结果一致!

另外:
介绍三个类似函数:

strncpy—strcpy
strncat—strcat
strncmp—strcmp
长度受限—长度不受限
前者相较于后者多出一个参数:size_t num,意义为限制拷贝的字符个数

主要优点:后者相较于前者更加灵活安全

示例:

int main()
{
	char arr1[] = "abcdefg";//遇到\0提前结束
	char arr2[] = "xxxxxxxxxxxx";
	//strncpy(arr2, arr1, 5);//最多拷贝5个字符
	//printf("%s", arr2);
	//strncat(arr2, arr1, 5);//最多追加5个字符
	//printf("%s", arr2);
	int r=strncmp(arr2, arr1, 5);//最多比较5个字符
	printf("%s\n", arr2);
	printf("%d", r);//1---a>b
	return 0;
}

其余内容重复,不再讲解

4.strstr函数
功能:在一个字符串中寻找另一个字符串第一次出现位置
结果:找到:返回出现位置指针,找不到:返回NULL

示例:

int main()
{
	char arr1[] = "heheabcdefgh";
	char arr2[] = "def";
	char* p = strstr(arr1, arr2);
	
	if (p != NULL)
	{
		printf("找到了,%s\n", p);//打印找到位置后的字符串

	}
	else
	{
		printf("未找到\n");
	}

	return 0;
}

strstr函数的模拟实现

两种:
1.

char* my_strstr(const char* a, const char* b)
{
  char* p1 = a;
	while (*p1 != *b)
	{
	    p1++;
	}
	size_t len = 0;
	char* p2 = b;
	while (*b != '\0')
	{
		b++;
		len++;
	}
	if (strncmp(p1, p2, len) == 0)
	{
		if (*p1 != '\0')
		{
			return p1;
		}
		else
		{
			return NULL;
		}
	}
	else
	{
		return my_strstr(p1 + 1, b);
	}
}

自己写的

char* my_strstr(const char* a, const char* b)
{
	char* p = a;
	char* s1 = NULL;
	char* s2 = NULL;

	//特殊场景:
	if (*p == '\0')
	{
		return a;
	}


	while (*p)
	{
		s1 = p;
		s2 = b;
		while (*s1&&*s2&&*s1 == *s2)
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
		{
			return p;
		}
		p++;
	}
	return NULL;
}

老师教的:暴力查找

其他方式:KMP

5.strtok函数
char * strtok(char * x,char * y)

功能:1.分割字符串;//根据y中的符号//调用一次分割一次
2.修改原始字符串,分割符号被修改为\0
3.返回首元素地址

示例:

int main()
{
	char arr[] = "zpw@yeah.net";
	char sep[] = "@.";
	char buf[20] = { 0 };
	strcpy(buf, arr);
	char* p = NULL;

//1.
	for (p = strtok(buf, sep); p != NULL; p = strtok(NULL, sep))
	{
		printf("%s\n", p);
	}
//2.
	//char* p = strtok(buf, sep);
	//printf("%s\n", p);//zpw

	//p = strtok(NULL, sep);//yeah
	//printf("%s\n", p);

	//p = strtok(NULL, sep);//net
	//printf("%s\n", p);

	//p = strtok(NULL, sep);//NULL
	//printf("%s\n", p);


	return 0;
}

6.strerror函数:
char*strerror(int errnum);
需要包含头文件<string.h>
C语言库函数在使用发生错误时会将一个错误码记录到errno的变量中
功能:
1.可以通过参数部分的errnum表示错误码,得到对应的错误信息,并返回错误信息字符串首字符地址
2.strerror函数只针对标准库中函数方式错误后设置错误码的转换

参数:errnum

示例:

int main()
{

	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d:%s\n", i, strerror(i));
	}//strerror函数将错误码转化为错误信息
	return 0;
}

转换形式:
0 : No error :无错误
1 : Operation not permitted:错误被拒绝
2 : No such file or directory :无该文件或文件夹
3 : No such process :没有进程
4 : Interrupted function call :函数调用被中断
5 : Input / output error :输入/输出错误
6 : No such device or address :无该设备或地址
7 : Arg list too long ……
8 : Exec format error
9 : Bad file descriptor
后面不再赘述

我们来看一个例子:

C语言可打开文件
该过程称为fopen
若以读的方式打开,则文件必须存在,若不存在,打开失败
open函数会将错误码放在errno中
同时函数返回NULL

如下:

int main()
{
	


	FILE*pf=fopen("data.txt", "r");
	if (pf == NULL)
	{
		
		printf("错误码为:\n%s\n", strerror(errno));
      printf("该文件不存在,打开失败\n");
		return 1;
	}
	//读文件:
	//………………

	//关闭文件:
	fclose(pf);
	pf = NULL;
	return 0;
}

7.perror函数:
void perror(char*str);

功能:记录错误码+打印错误信息 一体化
perror(xxx) -->xxx:错误信息
缺点:不够灵活
优点:足够方便

具体功能前面已经分开介绍,故不再赘述

后记:

通过以上示例,我们对于字符与字符串函数有了一个较为系统的认识,通过不断进行练习,熟悉度也会提高,下一节我们将认识另一种新的C语言函数:内存函数。那么,本节内容到此结束,我们下节再见!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值