IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 字符函数和字符串函数(C语言) -> 正文阅读

[C++知识库]字符函数和字符串函数(C语言)

前言

在函数那篇中我们介绍过了关于库函数的相关部分,库函数我们知道的有:IO函数、字符函数、字符串函数、内存函数、时间日期函数、数学函数等等。这次主要详细介绍字符和字符串函数。

函数介绍

strlen()函数

作用:strlen()函数是用来求字符串的长度的函数。
形式:size_t strlen( const char *string )
解释:将一个字符地址传给函数,strlen()函数进行搜寻,直到找到“\0”停止,计算字符个数(不包含“\0”)。
我们看例子:

#include<stdio.h>
#include<string.h>
int main()
{
	size_t sz = strlen("abcdef");
	printf("%u\n", sz);
	return 0;
}

size_t表示的是strlen()函数的返回类型,也就是说计算一个字符串的字符个数时会返回字符的个数,那么我们用一个变量接收,size_t表示的是无符号整型,也就是unsigned int,因此,用unsigned int定义sz也是可以的。所以在打印是我们也用%u来打印无符号整型。

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = "abcdef";
	size_t sz = strlen(arr);
	printf("%u\n", sz);
	return 0;
}

当然,我们也可以用字符数组来储存一个字符串,那么我们只需要将数组名传给函数就可以实现字符元素个数的计算。因为这里的数组名就表示首字符的地址,当找到“\0”就会停止。
我们来看一个错误的用法:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = { 'a','b','c' };
	size_t sz = strlen(arr);
	printf("%u\n", sz);
	return 0;
}

我们可以看到,arr[]也是一个字符数组,但是和上面例子不一样的是没有了以“\0”结尾的结束标志,这就导致strlen()函数,一直在后方内存中寻找,直到找到“\0”为止。所以此时打印结果不可知,是一个随机值。
易错:

  • 字符串已经 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数(不包含 ‘\0’ )。
  • 参数指向的字符串必须要以 ‘\0’ 结束。
  • 注意函数的返回值为size_t,是无符号的。

strcpy()函数

作用:strcpy()函数是用于字符串拷贝。
形式:char* strcpy(char* destination,const char*source)
解释:拷贝source字符串到destination字符串中,包含“\0”字符。
我们看这个例子:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "xxxxxxxxxxxx";
	char arr2[] = "hello";
	strcpy(arr1, arr2);
	printf("%s", arr1);
	return 0;
}

这段代码中我们将arr2的内容拷贝到arr1中,但是我们发现打印结果是:
在这里插入图片描述
我们发现hello后面的“xxx”不见了,这就表明strcpy()函数实现过程中是寻找“\0”将“\0”前面所有的字符包括“\0”一起拷贝到arr1中,因此打印时打印到“\0”就发生了停止,所以后面的“xxx”也就消失不见了(其实并不是真正意义上的消失,只是不被打印出来)。
我们来看两个错误的例子:
错误1

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "xxx";
	char arr2[] = "hello";
	strcpy(arr1, arr2);
	printf("%s", arr1);
	return 0;
}

在这个代码中我们发现将arr2的内容拷贝到arr1中是不行的,因为arr1中不够将arr2中的字符都拷贝过来,因此会放生数组越界的访问。这是不被允许的,所以会报错。
错误2

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "xxxxxxxxxxx";
	char arr2[] = {'a','b','c'};
	strcpy(arr1, arr2);
	printf("%s", arr1);
	return 0;
}

这段代码没有错误1中的毛病,但是我们看到arr2数组中并没有“\0”,这就导致strcpy()函数会无限制的向下寻找“\0”,并将前面的字符拷贝到arr1中,这也是不被编译器所允许的,因此同样会报错。
易错:

  • 源字符串必须以 ‘\0’ 结束。
  • 会将源字符串中的 ‘\0’ 拷贝到目标空间。
  • 目标空间必须足够大,以确保能存放源字符串。
  • 目标空间必须可变。

strcat()函数

作用:strcat()函数是用于字符串追加和字符串连接。
形式:char* strcat(char* strDestanation,const char* strSource)
解释:strcat函数将strSource追加到strDestination,并用空字符终止结果字符串。strSource的初始字符覆盖strDestination的终止空字符。复制或追加字符串时不执行溢出检查。
我们来看一个例子:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[20] = "abc";
	strcat(arr1, "def");
	printf("%s\n", arr1);
	return 0;
}

这段代码中我们可以清楚的看到打印结果为abcdef,这就是strcat()函数的作用。
我们来看错误例子:
错误1:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "abc";
	strcat(arr1, "def");
	printf("%s\n", arr1);
	return 0;
}

这段代码和上述的代码只相差了数字“20”,但是这段代码时跑不过去的,因为我们知道,在数组初始化时,如果没有给数组元素个数,那么系统会分配给数组刚好大小的空间,也就是说arr1[]被分配了4个字节(还有“\0”),但是在追加时,将“def”追加给arr1[]会导致数组的越界访问,因此这段代码无法通过编译器。
错误2

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[20] = "abc";
	char arr2[] = { 'd','e','f' };
	strcat(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}

这段代码中,我们创建arr1,其中有足够大小的空间,但是当进行追加时,我们发现arr2没有了结束的标志“\0”,这就导致不知道何时停止追加。因此导致不能通过编译。
易错

  • 原字符串必须以“\0”结束。
  • 目标空间必须足够大。
  • 目标空间必须可修改。

strcmp()函数

作用:strcmp()函数用于字符串比较,比较的是字符串的内容不是长度。
形式:int strcmp(const char* str1, const char* str2)
解释:strcmp函数按字典顺序比较string1和string2,并返回一个值,指示它们之间的关系。
我们来看例子:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abq";
	int ret = strcmp(arr1, arr2);
	printf("%d\n", ret);
	return 0;
}

在这段代码中,通过strcmp()函数的比较,我们将返回值用ret接收,如果arr1中字符(Ascll码值)<arr2字符,将返回一个小于0的值(通常为-1),如果arr1中字符(Ascll码值)>arr2字符,将返回一个大于0的值(通常为1),如果arr1中字符(Ascll码值)=arr2字符,将返回0,直到遇到“\0”停止上述过程,在这个例子中,前两个字符“ab”相等,在第三个字符中“c”<“q”,所以返回-1,打印结果为-1。

strncpy()函数、strncat()函数、strncmp()函数

细心的同学可能发现,这三个函数跟上诉我们学习的三个函数很相似,是的,原因就在于上述中 strcpy()函数、strcat()函数、strcmp()函数其实是不够安全的,什么意思呢?我们可以发现,这三个函数是不受字符串长度的限制,在使用时,不管三七二十一,直接就是用找到“\0”才会停止,这样往往会导致一些不必要的问题,因此我们在这三个函数的基础上做出了改进,是的改进后的strncpy()函数、strncat()函数、strncmp()函数受到长度的限制。
形式:
char *strncpy( char *strDest, const char *strSource, size_t count );
char *strncat( char *strDest, const char *strSource, size_t count );
int strncmp( const char *string1, const char *string2, size_t count );
我们看到,这三个函数相对于一开始的函数增加了一个参数,这个参数就是用来记录操作字符的个数的。举个例子:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[20] = "abcefghi";
	char arr2[] = "xxxx";
	strncpy(arr1, arr2, 2);
	printf("%s\n", arr1);
	return 0;
}

在这里插入图片描述
我们可以看到打印结果是“xxcdefghi”,而函数strncpy(arr1, arr2, 2)中所用的数字“2”,就是操作arr2数组中两个字符,也就是“xx”,同理,strncat()函数、strncmp()函数也是如此。

strstr()函数

作用:strstr()函数作用于字符串查找。
形式:char *strstr( const char *string, const char *strCharSet );
解释:strstr函数返回一个指针,指向字符串中第一个出现的strCharSet。搜索不包括终止空字符。
我们来看例子:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "i am a good student,hehe student";
	char arr2[] = "student";
	//查找arr1中arr2第一次出现的位置
	char* ret = strstr(arr1, arr2);
	if (ret == NULL)
	{
		printf("找不到\n");
	}
	else
	{
		printf("%s\n",ret);
	}
	return 0;
}

在这里插入图片描述
函数strstr()在找到对应匹配的字符时,会返回该字符的首字符地址,例子中我们用ret接收并打印,因此会从第一个“student”起打印直到“\0”。如果没有找到对应匹配的字符,那么返回NULL指针。

strtok()函数(了解即可)

作用:strtok()函数用于字符串的切割。
形式:char *strtok( char *str, const char *sep);
解释:strtok函数在str中查找下一个令牌。sep中的字符集指定在当前调用的str中找到的令牌的可能分隔符。
我们看例子:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] =  "zjt@bdsaitedu.tedch" ;
	char arr2[100] = { 0 };
	char sep[] = "@.";
	strcpy(arr2, arr1);
	char* ret = NULL;
	for (ret = strtok(arr2, sep); ret != NULL; ret=strtok(NULL,sep))
	{
		printf("%s\n", ret);
	}
	return 0;
}

这段代码有些许复杂,我们创建3个数组分别为arr1[],arr2[],sep[]数组,我们将arr1的内容拷贝到arr2中,进入for循环,第一次我们用sep[]数组中的符号分割出“zjt”,此时函数返回分割出字符的首字符地址,也就是“z”的地址,并赋值给ret,判断ret是否为NULL指针,显然不为空指针,打印出“zjt”,第二次循环,ret=strtok(NULL,sep)(此函数的特点:进行一次分割后,该函数会将分割位置作为标记,就像第一次分割时,会将“@”转化为“\0”,并记下分割的位置,再次进行分割时,从记住的位置再次进行分割),当第一个参数为NULL指针时函数,将在同一个字符串中被保存的位置开始,查找下一个标记。因此分割出“bdsaitedu”,以此类推,最后打印结果:
在这里插入图片描述
特点:

  • sep参数是个字符串,定义了用作分隔符的字符集合
  • 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
  • strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
  • strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
  • strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
  • 如果字符串中不存在更多的标记,则返回 NULL 指针。
    关于常见的字符和字符串函数介绍就到这里,如果有错误或者不正确的地方欢迎各位指正,谢谢大家!
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-19 07:48:45  更:2021-09-19 07:50:52 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/28 13:47:50-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计