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

news2024/9/20 15:42:48

前言:

        字符串在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;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

判断dom元素是否滚动到底、是否在可视区域

概览 我们日常开发中&#xff0c;在面对懒加载、虚拟列表需求时&#xff0c;经常需要判断dom元素是否滚动到底、是否在可视区域。但是由于涉及的属性太多了&#xff0c;比如scrollTop、clientHeight、scrollHeight、getBoundingClientRect()等属性&#xff0c;现根据这两个场景…

Docker环境安装并使用Elasticsearch

1、拉取es docker pull elasticsearch:7.10.12、查看镜像 docker images3、启动es docker run -d --name esearch -p 9200:9200 -p 9300:9300 elasticsearch:7.10.14、如果启动ES时出现一下问题 Unable to find image docker.elastic.co/elasticsearch/elasticsearch:7.10.…

基于springboot+vue的班级综合测评管理系统

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

台灯的功能作用有哪些?看完就知道台灯怎么选!

作为一位家长&#xff0c;我深刻意识到保护孩子眼部健康的重要性。随着科技的飞速发展&#xff0c;孩子们越来越多地使用电子设备&#xff0c;如平板电脑、手机和电视&#xff0c;长时间盯着屏幕成为了他们日常生活的一部分。然而&#xff0c;这些屏幕发出的蓝光和闪烁的光线&a…

C++的第一道门坎:类与对象(一)

1.面向过程与面向对象 1.1面向过程 我们之前学习的C语言就是一种面向过程的语言&#xff0c;面向过程的语言强调的是具体实现的过程&#xff0c;一般用函数来具体实现。我们用面向过程的思想&#xff0c;就可以把炒菜分为以下几个步骤: 1.2面向对象 而对于面向对象的语言而言…

duckdb 插件机制研究

本文研究 duckdb 内置的 extensions 工作机制。 插件架构 在 duckdb 源码内&#xff0c;内置了一组原生插件&#xff0c;位于顶层 extension 目录下&#xff1a; 除此之外&#xff0c;还支持 Out-of-Tree Extension&#xff0c;简单说就是独立的插件&#xff0c;不是集成在源…

零代码创建属于自己的情伤治愈者

前言 在这个社会物质文明生活发展迅速的年代&#xff0c;很多人都有心底里难以说出的痛楚&#xff0c;他们往往都与情伤相关&#xff0c;面对这样的情况&#xff0c;我们结合文心智能体设计出一款适合所有人的情伤治愈工具 体验智能体 文心智能体平台是一款基于自然语言处理和…

【鱼眼镜头10】等距Equidistant模型的Kannala-Brandt模型,opencv的鱼眼标定使用的模型。kalibr中的 pinhole + equidistant 都是指该模型。

Kannala Brandt 模型 / opencv中的fisheye / kalibr中的 pinhole equidistant 都是指该模型。 opencv https://docs.opencv.org/4.x/db/d58/group__calib3d__fisheye.html kalibr https://github.com/ethz-asl/kalibr/wiki/supported-models 在之前的博客【鱼眼镜头1】鱼眼…

linux centos磁盘清理相关

清理磁盘流程 1、查看磁盘挂载路径及使用率 df -h2、查看当前文件下文件大小 du -sh *3、制空文件内容 > 文件名 ###制空当前文件内容&#xff0c;直接清0 列子 >access.loglinux操作系统中&#xff0c;经常会遇到磁盘空间满的问题。遇到这样的问题&#xff0c;先查下…

实战 | 使用YoloV8实例分割识别猪的姿态(含数据集)

导 读 本文主要介绍如何使用YoloV8实例分割识别猪的姿态&#xff08;含数据集&#xff09;。 背景介绍 在本文中&#xff0c;我将介绍如何使用YoloV8在猪的自定义数据集上进行实例分割&#xff0c;以识别和跟踪它们的不同姿态。 数据集 使用的数据集来源于Kokkenborg Aps&…

【智能算法】青蒿素优化算法(AO)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献5.代码获取 1.背景 2024年&#xff0c;C Yuan受到青蒿素药物治疗疟疾过程启发&#xff0c;提出了青蒿素优化算法&#xff08;Artemisinin Optimization, AO&#xff09;。 2.算法原理 2.1算法思想 AO灵感来…

在C++中自定义命名空间,在命名空间中定义string变量,同时定义一个函数实现单词逆置

代码 #include <iostream> #include <cstring> using namespace std; namespace my_space {string s;void reverse(string s);//定义逆置函数 } using namespace my_space; void my_space::reverse(string s){int lens.size();int i0;int jlen-1;while(i<j){//…

MongoDB 和 AI 赋能行业应用:电信和媒体

欢迎阅读“MongoDB 和 AI 赋能行业应用”系列的第二篇。 本系列重点介绍 AI 应用于不同行业的关键用例&#xff0c;涵盖制造业和汽车行业、金融服务、零售、电信和媒体、保险以及医疗保健行业。 电信行业的经营环境以利润空间狭小为特点&#xff0c;尤其是在差异化极小的商品…

markdown画时序图的时候,如何自动显示每一条时序的序号

1: 现象描述 今天画时序图的时候&#xff0c;发现时序上面没有显示序号&#xff0c;看起来不够清晰&#xff0c;只有单纯的说明; 如下图所示 刚测试CSDN的时序图&#xff0c;默认是带序号的&#xff0c;看起来和实际使用的markdown工具有关系&#xff1b; 2&#xff1a;解决办…

MIT6.828 Lab2-1 Using gdb

Using gdb gdb使用&#xff1a; xv6 gdb调试方法 问题1&#xff1a; Looking at the backtrace output, which function called syscall? 按照提示开启gdb后键入&#xff1a; b syscall c layout src backtrace输出结果&#xff1a; (gdb) backtrace #0 syscall () at k…

nodejs开发入门01启动服务器

目录 1 创建项目2 初始化项目3 创建app.js4 服务器启动代码5 浏览器里访问6 部署到云服务器总结 nodejs是一个服务器运行环境&#xff0c;可以让我们搭建我们自己的服务器&#xff0c;接收客户端的请求&#xff0c;并给出响应。第一篇我们介绍一下服务器的搭建以及启动过程。 1…

Compose学习记录(1)

Compose学习记录(1) 简易使用HelloWorld。 新建一个工程&#xff0c;它已经默认启用了compose特性。MainActivity继承自 ComponentActivity&#xff0c;可以用compose来编写UI界面。 // sample 1: simple VersionsetContent {Text("Hello World.")}一个函数&#xf…

【项目】教你手把手完成博客系统(三)显示用户信息 | 实现退出登录 | 实现发布博客

文章目录 教你手把手完成博客系统&#xff08;三&#xff09;7.实现显示用户信息1.约定前后端交互接口2.前端通过ajax发起请求3.服务器处理请求 8.实现退出登录1.约定前后端的接口2.前端发起请求3.服务器处理请求 9.实现发布博客1.约定前后端的交互接口2.前端构造请求3.服务器处…

.NET调用阿里云人脸核身服务端 (ExecuteServerSideVerification)简易流程保姆级教学

需要注意的是&#xff0c;以下内容仅限基础调用 功能说明 该功能是输入核验人的姓名和身份证以及人脸照片&#xff0c;去阿里库里面匹配&#xff0c;3个信息是否一致&#xff0c;一致则验证通过&#xff0c;需要注意的是&#xff0c;人脸有遮挡&#xff0c;或者刘海&#xff0…

三分钟“手撕”顺序表与ArrayList

前言&#xff1a; 实现顺序表的代码放开头&#xff0c;供大家更好的查阅&#xff0c;每个方法都有代码的实现。 其次我会讲解Java自带的ArrayList的实例&#xff0c;扩容机制ArrayList使用方法&#xff0c;遍历以及它的优缺点。 目录 一、自己实现的顺序表 二、Java的ArrayLi…