C语言进阶——字符串函数(一)

news2024/11/15 20:32:58

目录

一.   strlen

二.   strcpy 

三.   strcat

四.   strcmp 

五.   strncpy

六.   strncat

 七.   strncmp

八.   strstr

九.   strtok


一.   strlen

 

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

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

注意函数的返回值为size_t,是无符号的
 

模拟实现

//计数
int my_strlen1(const char* s)
{
	int count = 0;
	while (*s++ != '\0')
	{
		count++;
	}
	return count;
}

//递归
int my_strlen2(const char* s)
{
	if (*s != '\0')
		return 1 + my_strlen2(s + 1);
	return 0;
}

//指针相减
int my_strlen3(const char* s)
{
	char* tail = s-1;
	while (*++tail!= '\0')
	{
		;
	}
	return tail-s;
}

而在我们的模拟实现中,返回值使用的是int,而库函数的返回值是无符号型,这两种其实各有利弊,使用int若字符串长度较大会出现负数的情况,而使用无符号型无法实现strlen相减得到字符串长度的差值。



二.   strcpy 

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

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

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

目标空间必须可变。

模拟实现

char* my_strcpy(char* s1,const char* s2)
{
	assert(s1 && s2);
	while (*s2 != '\0')
	{
		*s1++ = *s2++;
	}
    return s1;
}


三.   strcat


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

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

目标空间必须可修改。

模拟实现

char* my_strcat(char* s1,const char* s2)
{
	assert(s1 && s2);
	while (*s1++ != '\0')
	{
		;
	}
	s1--;
	while (*s2 != '\0')
	{
		*s1++ = *s2++;
	}
    return s1;
}

我们再考虑一个问题,s1和s2能否相同呢

int main()
{
	char s[20] = "abc";
	my_strcat(s, s);
	printf("%s\n", s);
	return 0;
}



可以看到,程序发生了崩溃


 可以看到,若是s1与s2相同,首先s1要加至‘\0’处,在进行赋值时,‘\0’被替换为a,这也就使得s2在向后移动时找不到‘\0’,进而导致死循环。



四.   strcmp 


 

模拟实现

int  my_strcmp(const char* s1,const char* s2)
{
	int ret = 0;
	assert(s1 && s2);
	while (*s1 == *s2)
	{
		s1++;
		s2++;
	}
	if (*s1 > *s2)
		ret = 1;
	if (*s1 < *s2)
		ret = -1;
	return ret;
}


五.   strncpy

 与strcpy的功能类似,只是多了一个参数num,决定拷贝的字符串长度

若拷贝的字符串小于num,则补‘\0’

模拟实现

char* my_strncpy(char* s1, const char* s2, int num)
{
	assert(s1 && s2);
	while (*s2 != '\0'&&num>0)
	{
		*s1++ = *s2++;
		num--;
	}
	return s1;
}


六.   strncat

与strcat的功能类似,只是多了一个参数num,决定拼接的字符串长度

模拟实现

char* my_strncat(char* s1, const char* s2, int num)
{
	assert(s1 && s2);
	while (*s1 != '\0')
	{
		s1++;
	}
	while (*s2 != '\0'&&num>0)
	{
		*s1++ = *s2++;
		num--;
	}
	*s1 = '\0';
    return s1;
}


 七.   strncmp

 num同上

模拟实现

int  my_strncmp(const char* s1, const char* s2, int num)
{
	assert(s1 && s2);
	int ret = 0;
	while (*s1 == *s2&&num>0)
	{
		num--;
		if (num != 0)
		{
			s1++;
			s2++;
		}
		if (*s1 == '\0' || *s2 == '\0')
			break;
	}
	if (*s1 > *s2)
		ret = 1;
	if (*s1 < *s2)
		ret = -1;
	return ret;
}


八.   strstr

 

模拟实现

char*  my_strstr(const char* s1, const char* s2)
{
	assert(s1 && s2);
	char* head1 = s1;
	char* head2 = s2;
	while(*s1!='\0')
	{
		while (*s1 != '\0' && *s1 != *s2)
			s1++;
		if (s1 == '\0')
			return NULL;
		head1 = s1;
		while (*s1 == *s2)
		{
			s1++;
			s2++;
			if (*s2 == '\0')
				return head1;
		}
		s1 = head1 + 1;
		s2 = head2;
	}
	return NULL;
}


九.   strtok

sep参数是个字符串,定义了用作分隔符的字符集合

第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。

strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)

strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。

strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标
记。

如果字符串中不存在更多的标记,则返回 NULL 指针。

int main()
{
    char* p = "sizhitong@abc.com";
    const char* sep = ".@";
    char arr[30];
    strcpy(arr, p);
    char* str;
    str = strtok(arr, sep);
    printf("%s\n", str);
    str = strtok(NULL, sep);
    printf("%s\n", str);
    str = strtok(NULL, sep);
    printf("%s\n", str);
    return 0;
}


 

而若是想要直接打印出去除间隔符后的结果,我们可以利用循环

int main()
{
    char *p = "sizhitong@abc.com";
    const char* sep = ".@";
    char arr[30];
    char *str = NULL;
    strcpy(arr, p);
    for(str=strtok(arr, sep); str != NULL; str=strtok(NULL, sep))
    {
        printf("%s\n", str);
    }
    return 0;
}

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

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

相关文章

陪诊软件开发,陪诊服务具备哪些好处,前景如何

在当下互联网快速发展的时代&#xff0c;我们要首先明确&#xff0c;一个行业的发展最重要的是什么&#xff0c;什么才能促进这个行业的前进。当然是用户的数量&#xff0c;**而我们的陪诊服务&#xff0c;潜在的用户数量是巨大的。因为自己独立不便就医的人群&#xff0c;都可…

maven导入第三方jar包,出现找不到类

我们开发时&#xff0c;会用到第三代第三方的jar包&#xff0c;私服上没有&#xff0c;只能导入使用。 导入步骤&#xff1a; 1、在项目根目录建文件夹lib&#xff0c;降jar包复制过去。 在pom.xml中引入jar包&#xff0c;如引入bcprov-jdk15on-1.59.jar <dependency>&…

c++ - 第21节 - 智能指针

1.为什么需要智能指针 分析一下下面这段程序有没有什么内存方面的问题&#xff1f;前面在异常的博客中&#xff0c;我们分析了下图一的代码Func函数中如果div()函数抛异常则程序会直接跳到主函数的catch捕获程序部分&#xff0c;然后接着主函数catch捕获程序部分往后执行代码&a…

【IOS的safari浏览器】uniapp的H5项目 safari<添加到主屏幕>功能的实现(多页面、单页面)

uniapp的H5项目safari <添加到主屏幕>功能的实现ios添加到主屏幕的需求具体效果实现前提完整的HTML页面如何判断应用是从主屏幕打开还是从浏览器打开特殊情况ios添加到主屏幕的需求 添加到主屏幕——这个功能属于ios的safari浏览器的特性之一&#xff0c;他可以让我们的…

Java环境安装、替换jdk后java编译javac无反应,但java和java -version可以成功:实操解决方案

这里写自定义目录标题问题背景方案一方案二方案三问题背景 最近换了新电脑&#xff0c;安装java环境&#xff0c;一次性下载了3个jdk版本&#xff0c;在配置后返现 cmd命令行下javac编译java文件不成功&#xff0c;但是输入java和java -version没问题 在CSDN看了许多解决方案…

linux安装go

下载地址 https://studygolang.com/dl?id2&id15&id0&id8&adinfo678baidu&adinfo678baidu%3Epage%3E go语言中文网 解压 tar -xvf go1.19.4.linux-amd64.tar.gz 解压之后在 root目录下面 有个 go的文件夹 vim ~/.bashrc 配置环境变量 export GOROOT/roo…

【Dash搭建可视化网站】项目10:疫情数据可视化大屏制作步骤详解

疫情数据可视化大屏制作步骤详解1 项目效果图2 项目架构3 文件介绍和功能完善3.1 assets文件夹介绍3.2 app.py和index.py文件完善3.3 header.py文件完善3.4 cards.py文件完善3.5 api.py和api.ipynb文件完善3.5.1 数据获取3.5.2 数据处理3.5.3 接口数据导入header.py和cards.py文…

SpringMVC基本使用

SpringMVC基本使用1、回顾MVC1.1、什么是MVC1.2、Model1时代1.3、Model2时代1.4、回顾Servlet2、什么是SpringMVC2.1、概述2.2、中心控制器2.3、SpringMVC执行原理3、HelloSpring3.1、配置版3.2、注解版3.3、小结4、Controller 及 RestFul4.1、控制器Controller4.2、实现Contro…

【笔记:第一课】学习开发一个RISC-V上的操作系统 - 汪辰 - 2021春

文章目录前言来源正文小结前言 创作开始时间&#xff1a;2023年1月9日20:02:19 如题&#xff0c;学习一下RISC-V。 来源 https://www.bilibili.com/video/BV1Q5411w7z5/ 正文 打好基础&#xff01;好好学习 本课程目的&#xff1a; 了解 RISC-V 的相关知识学会查看RISC-…

week10

T1 Einstein学画画 题目描述 Einstein 学起了画画。 此人比较懒~~&#xff0c;他希望用最少的笔画画出一张画…… 给定一个无向图&#xff0c;包含 nnn 个顶点&#xff08;编号 1∼n1 \sim n1∼n&#xff09;&#xff0c;mmm 条边&#xff0c;求最少用多少笔可以画出图中所…

解决RuntimeError: CUDA error: out of memory

注意&#xff1a;报错内容只有这一行&#xff0c;RuntimeError: CUDA error: out of memory&#xff0c;没有后面的内存分析。 因为报错的时候忘记截图了&#xff0c;修改好了才来记录的。这里引用别的博主的图片。图片来源 1&#xff1a;刚开始我怀疑是batchsize设的太大了&a…

vue01-基础

一、vue简介 1.1 描述 一套用于构建用户界面的渐进式JavaScript框架 构建用户界面&#xff1a;把数据处理成界面 渐进式&#xff1a;可以从简单应用引入的轻量小巧核心库&#xff0c;扩展至各式vue插件 1.2 特点 1.组件化模式&#xff0c;提高代码复用率且便于维护&#…

【自学Python】Python整型(int)

Python整型(int) Python整型(int)教程 Python 整型专门用来表示整数。 Python 整型支持四种形式&#xff0c;即十进制形式、二进制形式、八进制形式和十六进制形式。 Python整型(int) 十进制形式 Python 最常见的整数就是十进制形式的整数。在使用十进制表示整数值时&…

虚拟化技术学习笔记7

1、KVM虚拟机CPU热添加&#xff1a; # 能够了解虚拟机添加CPU的作用及预准备 # 能够通过virt-manager为虚拟机添加CPU # 能够通过virsh命令为虚拟机添加CPU CPU热添加&#xff0c;不需要重新启动虚拟机。这个是CPU的热添加。 virsh list virsh dominfo centos7-1lscpuvish s…

软件测试中的网络问题

1.背景 在测试过程中&#xff0c;出现的问题&#xff0c;除了代码问题&#xff0c;还有很多的网络问题&#xff0c;所以需要了解网络知识&#xff0c;这样能发现网络问题&#xff0c;尽快解决就能提高效率。 2.计算机网络体系结构 OSI七层模型&#xff1a;物理层&#xff0c…

【链表】leetcode24. 两两交换链表中的节点(C/C++/Java/Js)

leetcode24. 两两交换链表中的节点1 题目2 思路3 代码3.1 C版本&#xff08;递归迭代&#xff09;3.2 C版本&#xff08;递归迭代&#xff09;3.3 Java版本&#xff08;递归迭代&#xff09;3.4 JavaScript版本4 总结1 题目 题源链接 给你一个链表&#xff0c;两两交换其中相…

Deep Learning for Image Super-resolution:A Survey

Abstract图像超分辨率技术是计算机视觉中提高图像和视频分辨率的一类重要的图像处理技术。近年来&#xff0c;深度学习技术在图像超分辨率方面取得了显著进展。本文旨在对基于深度学习的图像超分辨率研究进展进行综述。一般而言&#xff0c;我们可以将现有的SR技术研究大致分为…

C++设计模式:原型模式(详解+实现案例)

文章目录原型模式使用场景实现步骤案例一案例二优缺点原型模式 原型模式&#xff1a; 用原型实例指定创建对象的种类&#xff0c;并通过拷贝这些原型创建新的对象&#xff0c;简单理解就是“克隆指定对象” 使用场景 某些结构复杂的对象的创建工作中由于需求的变化&#xff…

QT之OpenGL光照

QT之OpenGL光照1. 冯氏光照模型概述1.1 环境光照1.2 漫反射光照1.2.1 法向量1.3 镜面光照1.4 冯氏光照公式1.5 着色器demo2. 材质2.1 demo3. 光照贴图3.1 demo4. 投光物4.1 平行光4.1.1 平行光Demo4.2 点光源4.2.1 衰减4.2.1 点光源Demo4.3 聚光4.3.1 聚光Demo4.3.2 平滑/软化边…

Ajax工作原理

Ajax工作原理 HTTP协议原理与ajax工作原理 1.什么HTTP协议 协议指的是规定浏览器跟服务器交互的数据格式 2.浏览器请求 必须是&#xff1a;请求报文 3.服务器响应 必须是&#xff1a;响应报文 4.请求报文与响应报文的数据格式如下 1.请求报文 (1)请求行 &#xff1a; 包含请…