前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >库函数之字符函数与字符串函数(上)

库函数之字符函数与字符串函数(上)

作者头像
初阶牛
发布2023-03-13 09:56:37
2790
发布2023-03-13 09:56:37
举报
文章被收录于专栏:C语言基础
前言

🎈个人主页:🎈 :✨✨✨初阶牛✨✨✨ 🐻推荐专栏: 🍔🍟🌯 c语言进阶 🔑个人信条: 🌵知行合一 🍉本篇简介:>:介绍c语言中有关字符函数与字符串函数部分库函数.包括模拟实现,参数介绍等. 金句分享: ✨没有一朵花从一开始就是一朵花.✨

学习库函数的模拟实现之前,要先了解两个这两个

const关键字和assert()库函数

1.对于**const关键字,**这位博主讲的十分详细. const介绍 2.assert函数简单介绍. 函数名:断言函数 头文件:

代码语言:javascript
复制
#include <assert.h>

作用: 判断参数表达式的真假,如果为假就会终止程序,打印错误信息. 对于程序员这是一个非常友好的函数,可以减少出错的可能性,由于会返回错误到具体的哪一行,也就省去了调试的成本. assert()中的参数表达式为真时,什么也不会发生,在release版本中,assert会被优化掉.

目录

推荐查询库函数的网站: 查询库函数的网站

一、strlen函数

函数原型:

函数作用:

用于计算字符串的长度.(输入字符串首地址,返回字符串长度).

头文件

代码语言:javascript
复制
#include <string.h>

函数参数:

参数

意义

const char * str

要计算长度的字符串的首地址

返回值: 该字符串’\0’之前的字符个数,即不包括’\0’.

函数应用

代码语言:javascript
复制
#include <stdio.h>
#include <string.h>
int main()
{
	char arr[100]={0};
	printf("请输入字符串:\n");
	scanf("%s", arr);//这里可以不用&arr,因为arr是数组名,是数组的首地址
	size_t ret = strlen(arr);
	printf("字符串长度%zd", ret);
	return 0;
}

模拟实现:

代码语言:javascript
复制
//模拟实现strlen
#include <stdio.h>
#include <assert.h>
size_t my_strlen1(const char* str)//方法一:计数法
{
	assert(str);
	int count = 0;
	while (*str++)
	{
		count++;
	}
	return count;
}
size_t my_strlen2(const char* str)//方法二:递归方式实现
{
	assert(str);
	if (*str != '\0')
	{
		return 1 + my_strlen2(str + 1);
	}
	return 0;
}
size_t my_strlen3(const char* str)//方法三:指针-指针
{
	assert(str);
	char* ret = str;
	while (*ret)
	{
		ret++;
	}
	return ret - str;
}
int main()
{
	char arr[] = { "abcdefg" };
	printf("%d\n", my_strlen1(arr));
	printf("%d\n", my_strlen2(arr));
	printf("%d\n", my_strlen3(arr));
	return 0;
}

注意事项:

要保证被计算的字符串中包含’\0’,如果字符串没有包含’\0’,就会接续往后寻找,直到遇到’\0’,即产生随机值.

代码语言:javascript
复制
#include <stdio.h>
#include <string.h>
int main()
{
	char arr[] = { 'a','b','c' };
	int ret = strlen(arr);
	printf("%d", arr);
	return 0;
}

运行结果:

随机值

小细节: 你知道size_t是什么吗?

你知道这段代码的运行结果是什么吗?

代码语言:javascript
复制
#include <stdio.h>
#include <string.h>
int main()
{
	if (strlen("abc") - strlen("abcdef"))
	{
		printf("大于");
	}
	else
	{
		printf("小于等于");
	}
	return 0;
}

运行结果:

大于

原因就是size_t 3-6虽然结果是-3,但是对于无符号整形来说,就是一个很大的正数了.

其实size_t的本质是无符号整形,毕竟一个字符串的长度是非负数,所以库函数的设计还是比较合理的.

代码语言:javascript
复制
typedef unsigned int size_t;

二、strcpy函数

函数模型

函数作用:

用于将源地址的字符串拷贝到目的地址.

函数名:字符串拷贝函数

头文件:

代码语言:javascript
复制
#include <string.h>

函数参数:

参数

意义

参数1:char * destination

目的地址: 指向要在其中复制内容的目标数组的指针。

参数2:const char * source

源地址:要复制的 C 字符串。

返回值:拷贝完成后目的地址.

🌰栗子

代码语言:javascript
复制
#include<stdio.h>
#include <string.h>
int main()
{
	char arr1[20] =  "xxxxxxxxxxxxxxx" ;
	char arr2[] = "hello csdn" ;
	printf("%s", strcpy(arr1, arr2));
	return 0;
}

运行结果:

hello csdn

为了更加方便的观察拷贝的结果,我们可以通过调试,在监视窗口观察arr1的存放结果.

很明显,strcpy函数是从源地址的首地址处开始,直到遇到’\0’,最后将’\0’也拷贝过去. 为了验证是否真的只是到’\0’而不是所有数据. 将代码改成:

代码语言:javascript
复制
#include<stdio.h>
#include <string.h>
int main()
{
	char arr1[20] =  "xxxxxxxxxxxxxxx" ;
	char arr2[] = "hello\0 csdn" ;
	printf("%s", strcpy(arr1, arr2));
	return 0;
}

验证结果是正确的.

模拟实现:

代码语言:javascript
复制
#include <stdio.h>
//destination目的地		source源地址
char* my_strcpy1(char* dest, char* src)//第一种
{
	char* ret = dest;//记录首地址
	while (*src != '\0')
	{
		*dest = *src;
		dest++;
		src++;
	}
	*dest++ = *src++;
	return ret;
}
char* my_strcpy2(char* dest, char* src)//优化1,代码变得更加简洁
{
	char* ret = dest;
	while (*dest++=*src++)
	{
		;
	}
	return ret;
}

#include <assert.h>
char* my_strcpy3(char* dest, const char* src)
{
	assert(dest && src);//防止传入空指针
	char* ret = dest;
	while (*dest++ = *src++)//刚好最后将'\0'覆盖过去
	{
		;
	}
	return ret;
}
int main()
{
	char arr1[] = { "HELLO CSDN!" };
	char arr2[20] = { "xxxxxxxxxxxxxxxxxx" };
	char* p = NULL;//空指针
	printf("%s\n", my_strcpy1(arr2, arr1));
	//printf("%s\n", my_strcpy2(arr2, arr1));
	//printf("%s\n", my_strcpy3(arr2, arr1));
	return 0;
}

注意事项:

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

三、strcat函数

函数模型:

函数作用:

将源字符串(source)的副本(复制一份)追加到目标字符串(destination)。目标中的终止空字符(‘\0’)被源字符串的第一个字符覆盖,并且在目标中由两者串联形成的新字符串的末尾包含一个空字符(‘\0’)。

函数参数

参数

意义

参数1:char * destination

目的地址: 指向要在后面追加字符串的目标数组的指针。

参数2:const char * source

源地址:要追加的 C 字符串。

函数应用:

代码语言:javascript
复制
#include <stdio.h>
#include <string.h>
int main()
{
	char arr1[20] = "HELLO ";
	char arr2[] = "CSDN!";
	strcat(arr1,arr2);
	printf("%s", arr1);
	return 0;

运行结果:

HELLO CSDN!

模拟实现:

代码语言:javascript
复制
#include <stdio.h>
#include <assert.h>
my_strcat(char* dest, const char* src)
{
	assert(dest && src);//防止传入空指针
	char* ret = dest;
	while (*dest)
	{
		dest++;
	}
	while (*dest++ = *src++)
	{
		;
	}
	return ret;
}
int main()
{
	char arr1[20] = "HELLO ";
	char arr2[] = "CSDN!";
	my_strcat(arr1,arr2);
	printf("%s", arr1);
	return 0;
}

注意事项:

  • 源字符串必须以 ‘\0’ 结束。
  • 目标空间必须有足够的大,能容纳下源字符串的内容。
  • 目标空间必须可修改。 重点
  • 不可自己追加自己,否则不知道什么时候停下来,因为’\0’被改掉了.

四、strcmp函数

函数模型:

头文件:

代码语言:javascript
复制
#include <stdio.h>

函数作用:

将 C 字符串 str1 与 C 字符串 str2 进行比较。 此函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续向后比较,直到字符不同或达到终止空字符。 返回值: 返回一个整数值,该值指示字符串之间的关系

返回值

意义

<0

第一个不匹配的字符的str1的值小于str2中的值

0

两个字符串的内容相等

>0

第一个不匹配的字符的str1的值大于于str2中的值

函数参数:

参数

意义

参数1:const char * str1

指向字符串1的指针

参数2 const char * str2

指向字符串2的指针

函数应用: 实现一个设置密码,只有三次机会.

代码语言:javascript
复制
#define MAX 3
#include <stdio.h>
#include <string.h>
int main()
{
	char password[] = "1433223";
	char input[20];
	for (int i = MAX; i > 0; i--)
	{
		printf("请输入密码:\n你还有%d次机会:\n", i);
		scanf("%s", input);
		if (password== input)
		{
			printf("恭喜你,密码正确!!!");
			break;
		}
		else
		{
			printf("很遗憾,密码错误\n");
		}
	}
	return 0;
}

运行结果:

请输入密码: 你还有3次机会: 123 很遗憾,密码错误 请输入密码: 你还有2次机会: 1433223 很遗憾,密码错误 请输入密码: 你还有1次机会: 1234 很遗憾,密码错误

当密码输入正确时,也显示密码错误,因为字符串不能直接用"=="进行比较,而要借助库函数,strcmp函数进行比较.

代码语言:javascript
复制
#define MAX 3
#include <stdio.h>
#include <string.h>
int main()
{
	char password[] = "1433223";
	char input[20];
	for (int i = MAX; i>0; i--)
	{
		printf("请输入密码:\n你还有%d次机会:\n",i);
		scanf("%s", input);
		if (strcmp(password,input)==0)
		{
			printf("恭喜你,密码正确!!!");
			break;
		}
		else
		{
			printf("很遗憾,密码错误\n");
		}
	}
	return 0;
}

运行结果:

请输入密码: 你还有3次机会: 123 很遗憾,密码错误 请输入密码: 你还有2次机会: 123456 很遗憾,密码错误 请输入密码: 你还有1次机会: 1433223 恭喜你,密码正确!!!

模拟实现:

代码语言:javascript
复制
int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 && str2);
	while (*str1 == *str2)
	{
		if (*str2 == '\0')//循环条件是,字符串的元素相等,如果一方是'\0',说明两者都是'\0'.
		{
			return 0;//返回0,说明两者相等
		}
		str1++;
		str2++;
	}
	//跳出循环,说明有字符元素不相等
	if (*str1 > *str2)//比较哪方的字符更大
	{
		return 1;
	}
	else
	{
		return -1;
	}
}

注意事项: 此函数执行字符的二进制比较,实际比较的是字符的ASCII码值,并不是按长度比较. 而是比较第一次出现不同字符的大小. 在vs编译器下,

第一个字符串大于第二个字符串,返回1; 相等返回0 第一个字符串小于第二个字符串,返回-1; 而与库函数本身有点小的差别,库函数要求返回>0 0和<0的数即可.

后续会更新strncpy,strncat,strncmp,strstr,strtok,strerror=等库函数讲解. 今天就先到这里啦!!! 886

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-03-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 目录
  • 一、strlen函数
    • 函数作用:
      • 函数参数:
        • 模拟实现:
          • 注意事项:
          • 二、strcpy函数
            • 函数作用:
              • 函数参数:
                • 模拟实现:
                  • 注意事项:
                  • 三、strcat函数
                    • 函数作用:
                      • 函数参数
                        • 模拟实现:
                          • 注意事项:
                          • 四、strcmp函数
                            • 函数作用:
                              • 函数参数:
                                • 模拟实现:
                                领券
                                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档