字符函数和字符串函数

字符分类函数

C语语言中有⼀系列的函数是专门做字符分类的,也就是⼀个字符是属于什么类型的字符的。 这些函数的使用都需要包含⼀个头⽂件是"ctype.h"

这些函数的使用方法非常类似,我们就讲解⼀个函数的事情,其他的非常类似

复制代码
int islower ( int c );

islower 是能够判断参数部分的 c 是否是小写字母的。 通过返回值来说明是否是小写字母,如果是小写字母就返回非0的整数,如果不是小写字母,则返回 0

练习

写⼀个代码,将字符串中的小写字母转大写,其他字符不变

复制代码
#include <stdio.h>
#include <ctype.h>
int main()
{
	int i = 0;
	char str[] = "Test String.\n";
	char c;
	while (str[i])
	{
		c = str[i];
		if (islower(c))
			c -= 32;
		putchar(c);
		i++;
	}
	return 0;
}

while循环里面就是判断数组的字符串里面有没有"\0",有就停止循环,if分支里面有一个islower函数,该函数是判断字符是不是小写,因为小写字母比大写字母的ascii值大32,所以就减去32就是大写字母,最终打印字符c

字符转化函数

C语言提供了2个字符转换函数:

复制代码
int tolower ( int c ); //将参数传进去的⼤写字⺟转⼩写
int toupper ( int c ); //将参数传进去的⼩写字⺟转⼤写

上面的代码,我们将小写转大写,是-32完成的效果,有了转换函数,就可以直接使用该函数

复制代码
#include <stdio.h>
#include <ctype.h>
int main()
{
	int i = 0;
	char str[] = "Test String.\n";
	char c;
	while (str[i])
	{
		c = str[i];
		if (islower(c))
			c = toupper(c);
		putchar(c);
		i++;
	}
	return 0;
}

strlen函数

复制代码
size_t strlen ( const char * str )

字符串以含 '\0' ), '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前⾯出现的字符个数(不包'\0')

参数指向的字符串必须要以'\0'结束

注意函数的返回值为size_t,是无符号的

strlen的使用需要包含头文件

学会strlen函数的模拟实现

复制代码
#include <stdio.h>
#include <string.h>
int main()
{
	const char* str1 = "abcdef";
	const char* str2 = "bbb";
	if (strlen(str1) - strlen(str2) > 0)
	{
		printf("str1>str2");
	}
	else
	{
		printf("str1<str2");
	}
	return 0;
}

strcpy函数

写 ⼀个代码,将一个字符串复制给另一个字符串

看一下这个方法可不可以

复制代码
char arr1[] = "abcdefg";
char arr2[20] = { 0 };
arr1 = arr2;

我们把arr2直接赋值给arr1?

答案是不可以的,数组名表示首元素地址,而我们不能修改地址,这样会报错,但我们可以使用对应的函数strcpy

复制代码
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
	char arr1[] = "abcdefg";
	char arr2[20] = { 0 };
	strcpy(arr2, arr1);
	printf("%s\n", arr2);
	return 0;
}

函数strcpy将arr1复制给arr2

strcat函数

将源字符串的副本追加到目标字符串。目标字符串中的终止空字符会被源字符串的第一个字符覆盖,并在目标字符串中两个字符串连接形成的新字符串末尾包含一个空字符

源字符串必须以\0结束

目标字符串中也得有\0,否则没办法知道追加从哪里开始

目标空间必须有足够的大,能容纳下源字符串的内容

字符串自己给自己追加怎么样?

复制代码
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
	char arr1[20] = "abcde";
	char arr2[20] = "hello";
	strcat(arr1, arr2);
	printf("%s\n", arr1);

	return 0;
}

那现在我们实现一下自己追加自己

复制代码
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
	char arr1[20] = "abcde";
	//char arr2[20] = "hello";
	strcat(arr1, arr1);
	printf("%s\n", arr1);

	return 0;
}

没有任何输出结果,说明strcat不能用于自己追加自己,但后面我们会将

strcmp函数

比较字符串的大小,是比较每一个字符的ascii值的大小当比较出大小后就输出结果

第⼀个字符串大于第⼆个字符串,则返回大于0的数字

第⼀个字符串等于第二个字符串,则返回0

第⼀个字符串小于第二个字符串,则返回小于0的数字

复制代码
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
	char arr1[] = "abcde";
	char arr2[] = "hello";
	int ret=strcmp(arr1, arr2);
	printf("%d\n", ret);
	return 0;
}

此时比较出大小,说明字符串arr1小于arr2(strcmp函数的返回值是">0"的数和"0"和"<0"的数字,但VS中返回的是"1"和"0"和"-1")

strncpy函数

复制代码
char * strncpy ( char * destination, const char * source, size_t num );

将源字符串的前 num 个字符复制到目标位置。如果在复制完 num 个字符之前遇到源 C 字符串的结尾(以空字符表示),则用零填充目标,直到总共写入 num 个字符为止

拷贝num个字符从源字符串到目标空间

如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个

复制代码
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
	char arr1[] = "abcdefg";
	char arr2[20] = "xxxxxxxxxxx";
	strncpy(arr2, arr1, 3);
	printf("%s\n", arr2);
	return 0;
}

我从arr1中复制了三个值,现在赋值给arr2的前三个,我们通过调试看一下

strncat函数

复制代码
char * strncat ( char * destination, const char * source, size_t num );

将源字符串的前 num 个字符追加到目标字符串,并加上一个终止空字符

如果源字符串中C字符串的长度小于num,则只复制到终止空字符为止的内容

复制代码
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
	char str1[20];
	char str2[20];
	strcpy(str1, "To be ");
	strcpy(str2, "or not to be");
	strncat(str1, str2, 6);
	printf("%s\n", str1);
	return 0;
}

通过字符串复制函数strcpy给两个字符数组初始化,再用"安全的字符串拼接函数strncat",将str2 的前6个字符拼接到str1尾,最终输出拼接后的完整字符串

strncmp函数

复制代码
int strncmp ( const char * str1, const char * str2, size_t num );

比较str1和str2的前num个字符,如果相等就继续往后比较,最多比较num个字母,如果提前发现不⼀ 样,就提前结束,大的字符所在的字符串大于另外⼀个,如果num个字符都相等,就是相等返回0

复制代码
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
	char arr1[] = "helde";
	char arr2[] = "hello";
	int ret = strncmp(arr1, arr2,3);
	printf("%d\n", ret);
	return 0;
}

可以看到比strcmp多了一个参数,这个参数代表范围,表示比较前三个字符的大小

strstr函数

函数返回字符串str2在字符串str1中第⼀次出现的位置

字符串的比较匹配不包含 \0 字符,以 \0 作为结束标志

复制代码
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
	char str[] = "This is a simple string";
	char* pch;
	pch = strstr(str, "simple");
	strncpy(pch, "sample", 6);
	printf("%s\n", str);
	return 0;
}

在字符串 str 中查找子串 "simple",找到后将其替换为 "sample",最终输出修改后的完整字符串

这里用pch指针指向"simple"字符串常量的首个字符地址,然后再以此替换

strtok函数

复制代码
char * strtok ( char * str, const char * sep);

sep参数指向⼀个字符串,定义了用作分隔符的字符集合

第⼀个参数指定⼀个字符串,它包含了0个或者多个由sep字符串中⼀个或者多个分隔符分割的标 记

strtok函数找到str中的下⼀个标记,并将其用 \0 结尾,返回⼀个指向这个标记的指针(注: strtok函数会改变被操作的字符串,所以被strtok函数切分的字符串⼀般都是临时拷⻉的内容并且 可修改)

strtok函数的第⼀个参数不为NULL

函数将找到str中第⼀个标记,strtok函数将保存它在字符串

strtok函数的第⼀个参数为NULL,函数将在同⼀个字符串中被保存的位置开始,查找下⼀个标记

如果字符串中不存在更多的标记,则返回 NULL 指针

复制代码
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
	char arr[] = "192.168.6.111";
	char* sep = ".";
	char* str = NULL;
	for (str = strtok(arr, sep); str != NULL; str = strtok(NULL, sep))
	{
		printf("%s\n", str);
	}
	return 0;
}

strerror函数

复制代码
char* strerror ( int errnum );

strerror 函数可以把参数部分错误码对应的错误信息的字符串地址返回来。 在不同的系统和C语⾔标准库的实现中都规定了⼀些错误码,⼀般是放在 errno.h 这个头头件中说明 的,C语言程序启动的时候就会使⽤⼀个全局的变量errno来记录程序的当前错误码,只不过程序启动 的时候errno是0,表示没有错误,当我们在使用标准库中的函数的时候发生了某种错误,就会将对应 的错误码,存放在errno中,而⼀个错误码的数字是整数很难理解是什么意思,所以每⼀个错误码都是有对应的错误信息的,strerror函数就可以将错误对应的错误信息字符串的地址返回

复制代码
#define  _CRT_SECURE_NO_WARNINGS
#include <errno.h>
#include <string.h>
#include <stdio.h>
int main()
{
	int i = 0;
	for (i = 0; i <= 10; i++) {
		printf("%s\n", strerror(i));
	}
	return 0;
}

windows10家庭版+VS2022

相关推荐
山上三树2 分钟前
详细介绍 C 语言 typedef 及与 #define 的核心对比
c语言·数据结构·算法
释怀°Believe8 分钟前
Daily算法刷题【面试经典150题-7️⃣位运算/数学/】
算法·面试·职场和发展
2401_8762213418 分钟前
因数个数、因数和、因数积
c++·算法
云里雾里!28 分钟前
LeetCode 744. 寻找比目标字母大的最小字母 | 从低效到最优的二分解法优化
算法·leetcode
一条大祥脚42 分钟前
26.1.3 快速幂+容斥 树上dp+快速幂 带前缀和的快速幂 正序转倒序 子序列自动机 线段树维护滑窗
数据结构·算法
二狗哈1 小时前
czsc入门5: Tick RawBar(原始k线) NewBar (新K线)
算法·czsc
꧁Q༒ོγ꧂1 小时前
算法详解(四)--排序与离散化
数据结构·算法·排序算法
Tisfy1 小时前
LeetCode 0865.具有所有最深节点的最小子树:深度优先搜索(一次DFS + Python5行)
算法·leetcode·深度优先·dfs·题解
Q741_1471 小时前
C++ 队列 宽度优先搜索 BFS 力扣 429. N 叉树的层序遍历 C++ 每日一题
c++·算法·leetcode·bfs·宽度优先
Yzzz-F1 小时前
P4145 上帝造题的七分钟 2 / 花神游历各国[线段树 区间开方(剪枝) + 区间求和]
算法·机器学习·剪枝