首页 > 其他分享 >【C语言】字符函数和字符串函数(1)

【C语言】字符函数和字符串函数(1)

时间:2024-09-28 22:24:27浏览次数:10  
标签:函数 ++ str2 str1 C语言 char 字符串

在这里插入图片描述

文章目录

一、字符分类函数

   C语⾔中有⼀系列的函数是专⻔做字符分类的,也就是⼀个字符是属于什么类型的字符的,这些函数的使⽤都需要包含⼀个头⽂件是 ctype.h
如下图:
在这里插入图片描述
   这些函数的使用方式十分类似,现在拿一个函数举例:

int islower ( int c );

   islower 是能够判断参数部分的 c 是否是小写字母的,通过返回值来说明是否是小写字母,如果是小写字母就返回非0的整数,如果不是小写字母,则返回0
   练习:写⼀个代码,将字符串中的小写字母转大写,其他字符不变,最后将其打印出来
   分析:首先我们可以创建一个字符数组存放字符串,随后对数组遍历,每一次都使用函数islower函数判断一下该字符是否是小写字母,如果是小写字母,那就给它-32,让它变成对应的大写字母,最后我们以%s的形式将数组打印出来即可(记得包含头文件ctype.h)
代码如下:

#include <stdio.h>
#include <ctype.h>

int main()
{
	char arr[] = "Hello World!";
	int sz = sizeof(arr) / sizeof(arr[0]);
	for (int i = 0; i < sz-1; i++)
	{
		if (islower(arr[i]))
		{
			arr[i] -= 32;
		}
	}
	printf("%s\n", arr);
	return 0;
}

运行结果:
在这里插入图片描述

二、字符转换函数

   C语言提供了两个字符转换函数,要使用它们同样要包含头文件ctype.h:

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

   于是我们之前的那个将小写字母转换为大写字母的练习就可以这样写:

#include <stdio.h>
#include <ctype.h>

int main()
{
	char arr[] = "Hello World!";
	int sz = sizeof(arr) / sizeof(arr[0]);
	for (int i = 0; i < sz-1; i++)
	{
		if (islower(arr[i]))
		{
			toupper(arr[i]);
		}
	}
	printf("%s\n", arr);
	return 0;
}

三、strlen的使用和模拟实现

   首先我们来看看strlen的原型:

 size_t strlen ( const char * str );

strlen的特点:

  • 字符串以 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前⾯出现的字符个数(不包含 ‘\0’ )
  • 参数指向的字符串必须要以 ‘\0’ 结束。
  • 注意函数的返回值为 size_t,是⽆符号的( 易错 )
  • strlen的使⽤需要包含头⽂件string.h

   当我们知道strlen的原理后我们就试着来模拟实现一下我们自己的strlen:

  1. 函数命名:my_strlen
  2. 函数参数:直接照抄原函数strlen的参数,如下:
size_t my_strlen(const char* p)
  1. 函数实现:
    (1)由于我们传递的是指针,所以为了保险,我们可以在函数开头使用assert对p进行断言,注意包含头文件assert.h
    (2)然后我们可以创建一个start指针变量,用于存放初始的p的地址
    (3)随后使用while循环,如果对p解引用不是\0,那么就进入循环对p进行++操作,如果是\0,那么循环自动结束
    (4)最后返回此时p和start的差值即可
  2. 函数代码:
#include <assert.h>

size_t my_strlen(const char* p)
{
	assert(p);
	const char* start = p;
	while (*p)
	{
		p++;
	}
	return p - start;
}
  1. 函数测试:如图:
    在这里插入图片描述

四、strcpy的使用和模拟实现

   函数strcpy的作用是拷贝字符串,比如我们要把一个数组中的字符串拷贝到另一个数组中,我们就会使用strcpy函数,使用它需要包含头文件string.h,接下来我们来看看函数strcpy的原型:

char* strcpy(char * destination, const char * source );

   原型解析:strcpy的第一个参数是我们拷贝字符串的目的地的首地址,也就是接收拷贝的数组的首元素地址,第二个参数是我们拷贝字符串的源字符串的首地址,它的返回值就是接收拷贝的目标空间的初始地址
   了解了它的原型,我们现在来看看它的特点:

  • 源字符串必须以 ‘\0’ 结束
  • 会将源字符串中的 ‘\0’ 拷⻉到⽬标空间
  • ⽬标空间必须⾜够⼤,以确保能存放源字符串
  • ⽬标空间必须可修改

   现在我们来使用一下它,把数组arr2的字符串拷贝到arr1当中,如图:
在这里插入图片描述
   可以看到strcpy帮我们把数组arr2的字符串拷贝给了arr1
   学会使用,以及了解了它的使用方法之后,我们来试着模拟实现一下strcpy:

  1. 函数命名:my_strcpy
  2. 函数参数:可以直接照抄strcpy原型的参数,但是为了方便,我们把名字改简单一点,如下:
char* my_strcpy(char* str1, const char* str2)
  1. 函数实现:
    (1)由于接收的是两个指针参数,所以我们最好首先使用assert进行断言
    (2)由于要返回目标空间的起始地址,所以我们还是创建一个start变量来存放刚开始的str1,最后用于返回
    (3)strcpy函数的原理就是把源字符串的字符一个一个拷贝给目标字符串,所以我们可以使用while循环,对str2解引用,然后赋值给*str1,把这个赋值表达式作为循环判断条件,然后每执行一次就对str1和str2++一次,如果中途遇到赋值到\0,那么赋值表达式的结果为\0,自动停止循环如下:
	while (*str1 = *str2)
	{
		str1++;
		str2++;
	}

(4)我们可以优化一下上面的代码,既然str1和str2都要++的,我们可以直接写到循环条件里去,如下:

while (*str1++ = *str2++)
{
	;
}

这样比较简洁
(5)最后实现拷贝后,我们就可以返回start了

  1. 函数代码:
#include <assert.h>

char* my_strcpy(char* str1, const char* str2)
{
	assert(str1 && str2);
	char* start = str1;
	while (*str1++ = *str2++)
	{
		;
	}
	return start;
}
  1. 函数测试:如图:
    在这里插入图片描述

五、strcat的使用和模拟实现

   函数strcat的作用是追加字符串,把一个字符串追加到指定字符串的末尾,使用它要包含头文件string.h,接下来我们来看看strcat的原型

char * strcat ( char * destination, const char * source );

   strcat函数原型:它的参数和strcpy类似,第一个参数是被追加的目的地的首地址,第二个参数是要追加的源数据的首地址,返回的也是被追加的目的地的首地址
   了解了它的原型后,我们来看看它的特点:

  • 源字符串必须以 ‘\0’ 结束
  • ⽬标字符串中也得有 \0 ,否则没办法知道追加从哪⾥开始
  • ⽬标空间必须有⾜够的⼤,能容纳下源字符串的内容
  • ⽬标空间必须可修改

   了解strcat的特点后,我们来试着使用它,把字符串数组arr2的字符串追加到字符串数组arr1后:
在这里插入图片描述
   随后我们来试试模拟实现一下strcat:

  1. 函数命名:my_strcat
  2. 函数参数:可以直接照抄strcat原型的参数,但是为了方便,我们把名字改简单一点,如下:
char* my_strcat(char* str1, const char* str2)
  1. 函数实现:
    (1)还是老步骤,接收指针首先使用assert对它们断言一下
    (2)strcat函数就是把源字符串放在目标字符串后面,我们就要思考一下是放在目标字符串的哪个字符的后面,是不是\0后面呢?很明显不是,因为如果是\0后面,在打印时会提前碰到目标字符串的\0,结束打印,而不会打印后面追加的内容
    (3)所以可以得出,在追加时,strcat会从目标字符串的\0处开始追加,会覆盖目标字符串的\0,所以第一步我们就要先把str1移动到\0那个位置,还是可以使用我们的while循环,如下:
while (*str1)
{
	str1++;
}

(4)注意这里不能把循环条件写成str1++,因为如果str是\0了,循环是照常结束,但是str还要++一次,str就指向\0后面了,根据我们前面的分析就是错误的,所以这里只能把str自增的语句写在循环体内,当然,如果是拷贝字符串则不用担心这一点,可以放心把自增写在循环判断条件中
(5)然后我们继续分析,经过上面的循环,我们的str1指向的就是\0了,接着我们就把str2字符串完整的拷贝过来就可以了,这个拷贝的过程可以参考strcpy,可以把自增条件写在循环判断条件中,如下:

while (*str1++ = *str2++)
{
	;
}
  1. 函数代码:
#include <assert.h>

char* my_strcat(char* str1, const char* str2)
{
	assert(str1 && str2);
	char* start = str1;
	while (*str1)
	{
		str1++;
	}
	while (*str1++ = *str2++)
	{
		;
	}
	return start;
}
  1. 函数测试:如下图:
    在这里插入图片描述

   最后我们思考一下,一个字符串能不能使用strcat自己给自己追加?如图:
在这里插入图片描述
   很明显失败了,这是为什么呢?原因在下一篇字符函数和字符串函数(2)中我们会讲到,要实现这个功能需要另一个函数strncat,到时候也会详细介绍以及实现这个函数,期待一下吧!

六、strcmp的使用和模拟实现

   strcmp的作用就是帮我们比较两个字符串的大小,那么比较的依据是什么呢?是字符的acsll码值,同样的,使用该函数要包含头文件string.h,我们来看看它的原型:

int strcmp ( const char * str1, const char * str2 );

   原型解析:strcmp的两个参数分别是两个字符串的首字符地址,如果前一个字符串大于后一个字符串,返回一个大于0的数,如果相等就返回0,如果小于就返回一个小于0的数
   接着我们来看看strcmp的特点:

  • 第⼀个字符串⼤于第⼆个字符串,则返回⼤于0的数字
  • 第⼀个字符串等于第⼆个字符串,则返回0
  • 第⼀个字符串⼩于第⼆个字符串,则返回⼩于0的数字
  • 那么如何判断两个字符串? 比较两个字符串中对应位置上字符ASCII码值的大小

   了解了这些之后,我们来尝试使用一下strcmp函数来比较两个字符串,技巧就是用一个变量接收strcmp的返回值,然后根据返回值来确定两个字符串的大小关系,如下:
在这里插入图片描述
   现在我们来模拟实现一下strcmp:

  1. 函数命名:my_strcmp
  2. 函数参数:可以直接照抄strcmp原型的参数,如下:
int my_strcmp ( const char* str1, const char* str2 );
  1. 函数实现:
    (1)首先还是对两个指针变量断言一下
    (2)我们可以用一个while循环,判断一下 *str1 和 *str2是否相等,如果相等就进入循环,然后对str1和str2进行++操作
    (3)要注意的一点是,有可能它们两个字符串完全相等,我们可以判断一下 *str1是否是\0,由于它们解引用后相等才会进入循环,所以此时 *str2也是\0,此时就说明两个字符串完全相等,直接返回0
    (4)如果出了循环,说明它们当前指向的字符不相同,所以此时我们直接返回它们的差值即可,如果前一个字符更大,差值就自然大于0,符合函数的情况,后一个字符大也同理,这样我们就实现了我们的strcmp
  2. 代码:
#include <assert.h>

int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 && str2);
	while (*str1 == *str2)
	{
		if (*str1 == '\0')
			return 0;
		str1++;
		str2++;
	}
	return *str1 - *str2;
}
  1. 函数测试:如图:
    在这里插入图片描述
       这次的字符函数和字符串函数(1)就介绍到这里,更多的相关函数请期待下文!
       感谢阅读!

标签:函数,++,str2,str1,C语言,char,字符串
From: https://blog.csdn.net/hdxbufcbjuhg/article/details/142594131

相关文章

  • 【C语言】手把手带你拿捏指针(完)(指针笔试、面试题解析)
    文章目录一、sizeof和strlen的对⽐1.sizeof2.strlen3.sizeof与strlen对比二、数组和指针笔试解析1.一维数组2.字符、字符串数组和字符指针代码1代码2代码3代码4代码5代码63.二维数组4.总结三、指针运算笔试题解析代码1代码2代码3代码4代码5代码6一、sizeof和strl......
  • 华为OD机试2024年E卷-转骰子[200分]( Java | Python3 | C++ | C语言 | JsNode | Go )实
    题目描述骰子是一个立方体,每个面一个数字,初始为左1,右2,前3(观察者方向),后4,上5,下6,用123456表示这个状态,放置在平面上,可以向左翻转(用L表示向左翻转1次),可以向右翻转(用R表示向右翻转1次),可以向前翻转(用F表示向前翻转1次),可以向后翻转(用B表示向后翻转1次),可以逆时针旋转(......
  • 华为OD机试2024年E卷-矩阵匹配[200分]( Java | Python3 | C++ | C语言 | JsNode | Go )
    题目描述从一个N*M(N≤M)的矩阵中选出N个数,任意两个数字不能在同一行或同一列,求选出来的N个数中第K大的数字的最小值是多少。输入描述输入矩阵要求:1≤K≤N≤M≤150输入格式:NMKN*M矩阵输出描述N*M的矩阵中可以选出M!/N!种组合数组,每个组合......
  • 友元运算符重载函数
    目录1.定义友元运算符重载函数的语法形式2.双目运算符重载3.单目运算符重载1.定义友元运算符重载函数的语法形式        (1)在类的内部,定义友元运算符重载函数的格式如下:friend函数类型operator运算符(形参表){函数体}        (2)在类中,声明友......
  • 【Kotlin 集合概述】可变参数vararg、中缀函数infix以及解构声明(二十)
    导读大纲1.1使用集合:vararg、infix调用和解构声明1.1.1扩展Java集合API1.1.2vararg:接受任意数量参数的函数1.1.3处理pairs:Infix调用和解构声明1.1使用集合:vararg、infix调用和解构声明本节将介绍Kotlin标准库中用于处理集合的一些函数同时......
  • Python函数的魔法:定义与调用的艺术
    引言:你是否曾被代码困住?想象一下,你正在编写一个复杂的程序,突然间,代码的逻辑变得混乱不堪,像是一团乱麻。你是否曾经想过,为什么有些代码看起来如此简洁,而有些却让人头疼不已?答案往往在于函数的使用。函数不仅是代码的“魔法师”,更是我们编程旅程中的得力助手。在这篇文章中,我们......
  • java字符串连接和运算符优先级
    源代码:publicclassEnumTest{publicstaticvoidmain(String[]args){intx=100;inty=200;System.out.println("x+y="+y+x+y);System.out.println(x+y+"=x+y");}}程序输出:x+y=200100200300=x......
  • C++ day02(函数、类和对象、封装、构造函数、析构函数)
    目录【1】函数1》内联函数inline 2》函数重载overload  3》函数的参数默认(缺省)值 4》哑元函数【2】类和对象1》类的定义 2》创建对象 【3】封装 【4】构造函数constructor1》基础使用2》构造初始化列表 3》构造函数的调用方式 4》拷贝构造函数1>概......
  • YOLOv10改进策略【损失函数篇】| Shape-IoU:考虑边界框形状和尺度的更精确度量
    一、本文介绍本文记录的是改进YOLOv10的损失函数,将其替换成Shape-IoU。现有边界框回归方法通常考虑真实GT(GroundTruth)框与预测框之间的几何关系,通过边界框的相对位置和形状计算损失,但忽略了边界框本身的形状和尺度等固有属性对边界框回归的影响。为了弥补现有研究的不足,Sh......
  • 字符函数和字符串函数
    字符函数和字符串函数字符分类函数大家知道字符是分为很多种类型的就比如说’a’‘1’'A’等等,所以我们需要一种函数来完成字符函数的分类这就是字符分类函数函数需要包含头文件<ctype.h>函数的运行规则是:如果符合下列参数就返回真inscntrl(控制任何字节)isspace(空白......