字符串和字符串函数(1)

前言:

        字符串在C语言中比较特别,没有单另的字符串类型,想要初始化字符串必须用字符变量的数组初始化,但是在C语言标准库函数中提供了大量能对字符串进行修改的函数,比如说可以实现字符串的的拷贝,字符串的追加,字符串的替换等等。       

        接下来就一起来学习这些功能,并且能够模拟实现以下这些函数的功能。

strlen函数

        介绍并且使用:

        

        简单了来说就是可以得到字符串的长度的函数,注意事项:

        1、字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包 含 '\0' )。

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

        3、注意函数的返回值为size_t,是无符号的( 易错 )。

#include<stdio.h>
#include<stdlib.h>
int main()
{
	char arr[] = { "abcdefg" };
	printf("%u\n", strlen(arr));//因为strlen返回值是一个无符号整型,我们可以用%u打印
	return 0;
}

很容易计算出结果是7,也就是这个字符串中有7个字符。

模拟实现strlen函数

        我们可以自己编写自己的strlen函数,只需要返回一个整型,然后即可,接下来用三种方式模拟实现strlen函数。

方法一:while循环      

代码如下:

int my_strlen(char *arr)
{
	int num = 0;
	while (1)
	{
		if (*arr == '\0')
		{
			break;
		}
		arr++;
		num++;
	}
	return num;
}
int main()
{
	char arr[] = { "abcdefg" };
	printf("%d\n",my_strlen(arr));
	return 0;
}

方法二:递归

int my_strlen(char* arr)
{
	if (*arr == '\0')
	{
		return 0;
	}
	else
	{
		return 1 + my_strlen(arr + 1);
	}
}
int main()
{
	char arr[] = { "abcdefg" };
	printf("%d\n",my_strlen(arr));
	return 0;
}

方式三:指针

//指针-指针的方式
int my_strlen(char *s)
{
       char *p = s;
       while(*p != ‘\0’ )
              p++;
       return p-s;
}
int main()
{
	char arr[] = { "abcdefg" };
	printf("%d\n",my_strlen(arr));
	return 0;
}

strcpy函数

介绍并使用:

        

可以进行字符串的拷贝。从源头拷贝到目的地。

注意事项:

1、源字符串必须以 '\0' 结束。

2、会将源字符串中的 '\0' 拷贝到目标空间。

3、目标空间必须足够大,以确保能存放源字符串。

4、目标空间必须可变。

int main()
{
	char arr1[] = {"abcde"};
	char arr2[20] = {0};
	strcpy(arr2,arr1);
	printf("%s\n", arr2);
	return 0;
}

模拟实现strcpy函数

      这里需要强调几点:

        1、由于是将一个数组的字符串传到另一个字符串中,所以这两个字符串里面应该都有位置,也就是传过去的地址不能是空值(NULL)

  所以用assret断言一下,如果是空值,电脑会进行报错。

        2、因为传进去的时候,也要将'\0'传进去所以当判断是'\0'的时候应该要跳出循环,在跳出之前最后将'\0'传进去。

        根据注意事项,即可对strcpy函数进行模拟,返回类型为char*。代码如下:

       

#include<assert.h>
char* my_strcpy(char* arr2, const char* arr1)
{
	assert(arr1 !=NULL);
	assert(arr2 != NULL);
	char* arr = arr2;
	while (1)
	{
		if (*arr1 == '\0')
		{
			*arr2 = *arr1;
			break;
		}
		*arr2 = *arr1;
		arr1++;
		arr2++;
	}

	return arr;
}
int main()
{
	char arr1[] = {"abcde"};
	char arr2[20] = {0};
	my_strcpy(arr2, arr1);
	printf("%s\n",arr2 );
	return 0;
}

 当然这里可以对代码进行升级,升级如下:

#include<assert.h>
char* my_strcpy(char* arr2, const char* arr1)
{
	assert(arr1 !=NULL);
	assert(arr2 != NULL);
	char* arr = arr2;
	while (*arr2++ = *arr1++)
	{
		;
	}
	*arr2 = *arr1;
	return arr;
}
int main()
{
	char arr1[] = {"abcde"};
	char arr2[20] = {0};
	my_strcpy(arr2, arr1);
	printf("%s\n",arr2 );
	return 0;
}

strcat函数

        介绍并使用:

        

该函数可以对字符串进行追加(连接)

例如:
        

int main()
{
	char arr1[20] = {"abcd"};
	char arr2[] = {"efgh"};
	strcat(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}

效果如下:

        

注意事项:

1、源字符串必须以 '\0' 结束。

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

3、目标空间必须可修改。

模拟实现strcat函数

这里首先根据正常逻辑分析并my_strcat

char* my_strcat(char*arr1,const char* arr2)
{
	assert(arr1 != NULL);
	assert(arr2 != NULL);
	char* arr = arr1;
	while (1)
	{
		if (*arr1 == '\0')
		{
			while (1)
			{
				*arr1 = *arr2;
				arr1++;
				arr2++;
				if (*arr2 == 0)
				{
					*arr1 = *arr2;
					break;
				}
			}
			break;
		}
		arr1++;
	}
	return arr;
}
int main()
{
	char arr1[20] = { "abcd" };
	char arr2[] = {"efgh"};
	//my_strcat(arr1, arr2);
	printf("%s\n", my_strcat(arr1, arr2));
	return 0;
}

可以进行一次改进:(减少if语句)

char* my_strcat(char*arr1,const char* arr2)
{
	assert(arr1 != NULL);
	assert(arr2 != NULL);
	char* arr = arr1;
	while (*arr1)
	{
		arr1++;
	}
	while (1)
	{
		*arr1 = *arr2;
		if (*arr2 == 0)
		{
			*arr1 = *arr2;
			break;
		}
		arr1++;
		arr2++;
	}
	return arr;
}
int main()
{
	char arr1[20] = { "abcd" };
	char arr2[] = {"efgh"};
	//my_strcat(arr1, arr2);
	printf("%s\n", my_strcat(arr1, arr2));
	return 0;
}

可以进行第三次改进

char* my_strcat(char* arr1, const char* arr2)
{
	assert(arr1 != NULL);
	assert(arr2 != NULL);
	char* arr = arr1;
	while (*arr1)
	{
		arr1++;
	}
	while (*arr1++ = *arr2++)//先赋值后++
	{
		;
	}
	return arr;
}
int main()
{
	char arr1[20] = { "abcd" };
	char arr2[] = { "efgh" };
	//my_strcat(arr1, arr2);
	printf("%s\n", my_strcat(arr1, arr2));
	return 0;
}

strcmp函数

介绍并使用:

这个函数可以实现比较两个字符串:

比较的是两个字符串的ASCALL码值,从第一个字符开始比较,返回值是这样的:

 当 str1大于str2的时候,返回>0的数

当str1小于str2的时候,返回<0的数

当str1等于str2的时候,返回 = 0的数    

     使用代码如下:

int main()
{
	char arr1[] = {"abcdf"};
	char arr2[] = {"abct"};
	if (strcmp(arr1, arr2) == 0)
	{
		printf("=");
	}
	else if(strcmp(arr1, arr2)>0)
	{
		printf(">");
	}
	else
	{
		printf("<");
	}

	return 0;
}

模拟实现strcmp函数

        初步模拟:

int my_strcmp(const char* arr1, const char* arr2)
{
    assert(arr1 != NULL);
    assert(arr2 != NULL);
	while (1)
	{
		if (*arr1 > *arr2)
		{
			return 1;
		}
		else if(*arr2 > *arr1)
		{
			return -1;
		}
		else if (*arr2 == '\0' && *arr1 == '\0')
		{
			return 0;
		}
		arr1++;
		arr2++;
	}
	
}
int main()
{
	char arr1[] = {"abcdef"};
	char arr2[] = {"abcdfk"};
	int c = 0;
	c = my_strcmp(arr1,arr2);
	if (c > 0)
	{
		printf(">");
	}
	else if (c < 0)
	{
		printf("<");
	}
	else
		printf("=");
	return 0;
}

二次修改:

        可以自己分析一下,while函数。

int my_strcmp(const char* src, const char* dst)
{
	int ret = 0;
	assert(src != NULL);
	assert(dst != NULL);
	while (!(ret = *(unsigned char*)src - *(unsigned char*)dst) && *dst)
	{
		src++;
		dst++;
	}
	if (ret < 0)
		ret = -1;
	else if (ret > 0)
		ret = 1;
	return ret;
}
int main()
{
	char arr1[] = {"abcdef"};
	char arr2[] = {"abcdefo"};
	int c = 0;
	c = my_strcmp(arr1,arr2);
	if (c > 0)
	{
		printf(">");
	}
	else if (c < 0)
	{
		printf("<");
	}
	else
		printf("=");
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/651234.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

直播预告:TinyVue 组件库实战解析,提升组件库构建技能!

在复杂的编码世界里&#xff0c;大家总希望能够寻找更高效、更简洁的解决方案来优化工作流程&#xff0c;提升开发效率。在5月28日晚7点 OpenTiny B站直播间&#xff0c;OpenTiny 非常荣幸地为大家带来一场关于 TinyVue 组件库实战分享的直播。届时&#xff0c;TinyVue 组件库成…

【java程序设计期末复习】chapter4 类和对象

类和对象 编程语言的几个发展阶段 &#xff08;1&#xff09;面向机器语言 计算机处理信息的早期语言是所谓的机器语言&#xff0c;使用机器语言进行程序设计需要面向机器来编写代码&#xff0c;即需要针对不同的机器编写诸如0101 1100这样的指令序列。 &#xff08;2&#x…

优优嗨聚集团:快速摆脱个人债务束缚的秘诀

在快节奏的现代生活中&#xff0c;个人债务问题时常困扰着许多人。面对日益增长的债务压力&#xff0c;如何快速有效地处理成为众多人的迫切需求。本文将为你提供一套实用的债务清零攻略&#xff0c;帮助你摆脱债务的束缚&#xff0c;重获财务自由。 一、认清债务现状&#xff…

[NISACTF 2022]easyssrf、[NISACTF 2022]level-up

[NISACTF 2022]easyssrf 使用dirsearch扫描后没发现什么路径 尝试访问127.0.0.1&#xff0c;成功了 访问127.0.0.1/flag.php提示有文件/fl4g 使用file://协议读取文件/fl4g&#xff0c;提示除此页面外还有一个ha1x1ux1u.php页面。 file:///fl4g 直接访问&#xff0c;发现GET…

WDW-20B微机控制人造板试验机

一&#xff0e;设备外观照片&#xff1a; 项目简介&#xff1a; 微机控制电子式万能试验机是专门针对高等院校、各种金属、非金属科研厂家及国家级质检单位而设计的高端微机控制电子式万能试验机、计算机系统通过全数字控制器&#xff0c;经调速系统控制伺服电机转动&#xff…

JavaWeb_HTTP协议

HTTP&#xff1a; 概念&#xff1a; HTTP&#xff08;Hyper Text Transfer Protocal&#xff09;&#xff0c;超文本传输协议&#xff0c;规定了浏览器和服务器之间数据传输的规则。 特点&#xff1a; 1.基于TCP协议&#xff1a;面向连接&#xff0c;安全 2.基于请求-响应模型…

【Linux】升级GCC(版本9.3),补充:binutils

GCC&#xff1a;GNU Compiler Collection 。编译器&#xff0c;几乎Linux中所有程序&#xff08;包括内核&#xff09;都是gcc编译的&#xff0c;包括libc。 gcc不仅仅是编译器&#xff0c;gcc也有很多库&#xff0c;依赖libc。gcc和libc互相依赖。 GCC官网&#xff1a;GCC, …

如何注册Claude3?解决Claude3无海外手机号接收验证码的问题以及如何订阅Claude Pro

原文链接&#xff1a;如何注册 Claude3&#xff1f;解决 Claude3 无海外手机号接收验证码的问题以及如何订阅 Claude Pro 前言 Claude3已经出来有一段时间了&#xff0c;大家有没有体验过呢&#xff1f;不过从目前来看&#xff0c;Anthropic公司总共推出了3个模型&#xff1…

Java项目:基于SSM框架实现的学生就业管理系统分前后台(ssm+B/S架构+源码+数据库+毕业论文+开题报告)

一、项目简介 本项目是一套基于SSM框架实现的学生就业管理系统 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、操作简单、功能…

【Chapter5】死锁与饥饿,计算机操作系统教程,第四版,左万利,王英

文章目录 1.1 什么是死锁1.2 死锁的类型1.2.1 竞争资源引起的死锁1.2.2 进程间通信引起的死锁1.2.3 其他原因引起的死锁 1.3 死锁产生必要条件1.4 死锁的处理策略1.5 死锁的预防1.5.1 破坏资源独占条件1.5.2 破坏不可剥夺条件1.5.3 破坏保持申请条件1.5.4 破坏循环等待条件 1.6…

ip反解域名-python脚本

import sys import socket from requests.packages.urllib3.contrib import pyopenssl def domain_dns(ip, port, timeout0.09): try: # 创建一个 socket sock socket.create_connection((ip, port), timeouttimeout) # 设置超时 sock.settimeout(timeout) # 加载 SSL 证书 x5…

第十七届全国大学生信息安全竞赛创新实践能力赛初赛部分复现

Misc 神秘文件 1.根据提示信息&#xff0c;均需要从ppt中提取信息 2.在ppt的属性中发现一串密文和key&#xff0c;解密之后得到第一部分&#xff0c;根据提示Bifid chipher&#xff0c;为双歧密码解密&#xff0c;使用Bifid Cipher Decode解码 3.在第五张幻灯片&#xff0c;…

neo4j docker安装使用,py2neo python包使用

参考&#xff1a;https://neo4j.com/docs/operations-manual/current/docker/introduction/ 运行&#xff1a; docker run --publish7474:7474 --publish7687:7687 neo4j查看&#xff1a; http://192***ip:7474 username/password 都是 neo4j/neo4j 简单案例 创建例子&am…

基于Docker部署GitLab环境搭建

文件在D:\E\学习文档子目录压缩\专项进阶&#xff0c;如ngnix,webservice,linux,redis等\docker 建议虚拟机内存2G以上 1.下载镜像文件 docker pull beginor/gitlab-ce:11.0.1-ce.0 注意&#xff1a;一定要配置阿里云的加速镜像 创建GitLab 的配置 (etc) 、 日志 (log) 、数…

【CTF Web】CTFShow web2 Writeup(SQL注入+PHP+UNION注入)

web2 1 管理员赶紧修补了漏洞&#xff0c;这下应该没问题了吧&#xff1f; 解法 注意到&#xff1a; <!-- flag in id 1000 -->但是 or 被拦截了。 if(preg_match("/or|\/i",$id)){die("id error");}使用UNION注入&#xff1a; ?id1 union sele…

矩阵区域和 ---- 二维前缀和

题目链接 题目: 分析: 题目的题意是:矩阵和的问题, 应该使用二维前缀和来解决 先预处理一个前缀和, 但是题目中下标是从0开始的, 为了不处理边界情况, 我么预处理出来的矩阵, 要从下标为1的位置开始, 所以前缀和矩阵的大小为m1 * n1预处理前缀和:dp[i][j] 表示: 从[1,1] 位置…

Android 动效整理

Android自定义SeekBar&#xff0c;滑动时弹出气泡指示器显示进度 安卓开发中非常炫的效果集合_android 开发 向右上角收起炫酷动态效果-CSDN博客 https://github.com/shenghuntianlang/Android-Views?tabreadme-ov-file#decentbanner 以前收藏了很多文章&#xff0c;但是过…

服务器端口转发,服务器端口转发的作用、好处与坏处

服务器端口转发&#xff0c;服务器端口转发的作用、好处与坏处。 服务器端口转发是一种关键的网络技术&#xff0c;它在网络安全和通信中发挥着不可替代的作用。其主要功能是将来自一个端口的网络流量转发到另一个端口&#xff0c;从而实现内外网之间的流量交互。这种技术通常…

对竞品分析的理解

一、竞品分析是什么 竞品分析即对竞争对手进行分析&#xff0c;是市场研究中的一项重要工作&#xff0c;它可以帮助企业了解竞争对手的产品、策略、市场表现等信息&#xff0c;通过竞品分析可以为自己的产品制定更加精准的策略。 二、为什么要做竞品分析 1.了解市场情况 了解…

2024.05.22学习记录

1、面经复习&#xff1a; Vue组件通讯、vuex、js严格模式、options请求、vue3 Setup 语法糖、React hook 2、代码随想录刷题&#xff1a;动态规划 3、rosebush组件库 完成Alert和Alert测试 Menu组件初步开发