字符串函数(一)

news2024/12/22 22:14:04

图片来源于网络

✨博客主页:小钱编程成长记
🎈博客专栏:进阶C语言

字符串函数(一)

  • 0.前言
  • 1.求字符串长度的函数
    • 1.1 strlen(字符串长度)
  • 2.长度不受限制的字符串函数
    • 2.1 strcpy(字符串拷贝)
    • 1.3 strcat(字符串追加)
    • 2.3 strcmp(字符串比较)
  • 总结

0.前言

  • C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在常量字符串或者字符数组中。
  • 字符串常量适用于那些多它不做修改的字符串函数。
小知识:

assert断言,需要头文件assert.h 。是用来判断表达式的值不能为某值的。若表达式为假,会报错,而且会指出错误的位置,提醒你修改。

字符串函数的头文件都是string.h

1.求字符串长度的函数

1.1 strlen(字符串长度)

具体介绍链接

size_t strlen (const char *str);
注:
  • 字符串已 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数(不包含 ‘\0’ )。
  • 参数指向的字符串必须要以 ‘\0’ 结束,否则返回的结果为随机值。
  • 注意函数的返回类型为size_t,是无符号整型( 易错 ),用%zd打印。
  • 学会strlen函数的模拟实现
注意:
#include <stdio.h>
#include <string.h>

int main()
{
	const char* str1 = "abcdef";
	const char* str2 = "bbb";
	if (strlen(str2) - strlen(str1) >= 0)//因为strlen返回类型是size_t(无符号整型),所以差也是无符号整型,无符号整型一定>=0。
	{
		printf(">=");
	}
	else
	{
		printf("<");
	}
	return 0;
}

若将返回值强转为整型,差就为-3,打印出<
在这里插入图片描述

strlen的模拟实现的三种方法:

  1. 计数器
#include <stdio.h>
#include <assert.h>

size_t my_strlen1(const char* str)//str指向的字符不需要修改,可以加上const保护字符,防止其被修改
{
	assert(str);//断言(需要头文件assert.h),防止str为空指针。若为空指针(==0),会报错,而且会指出错误的位置,提醒你修改
	int count = 0;
	while(*str++)   // ==  if(*str++ != \0)
	{
		count++;
	}
	return count;
}

int main()
{
	char arr[] = "abcdef";
	printf("%zd\n", my_strlen1(arr));//链式访问(一个函数的返回值是另一个函数的参数)
	return 0;
}
  1. 递归
#include <stdio.h>
#include <assert.h>

size_t my_strlen2(const char* str)//str指向的字符不需要修改,可以加上const保护字符,防止其被修改
{
	assert(str);//断言(需要头文件assert.h),防止str为空指针。若为空指针(==0),会报错,而且会指出错误的位置,提醒你修改
	if (*str != '\0')
	{
		return my_strlen2(str + 1) + 1;
	}
	else
	{
		return 0;
	}
}

int main()
{
	char arr[] = "abcdef";
	printf("%zd\n", my_strlen2(arr));//链式访问(一个函数的返回值是另一个函数的参数)
	return 0;
}

  1. 指针 - 指针
#include <stdio.h>
#include <assert.h>

size_t my_strlen3(const char* str)//str指向的字符不需要修改,可以加上const保护字符,防止其被修改
{
	assert(str);//断言(需要头文件assert.h),防止str为空指针。若为空指针(==0),会报错,而且会指出错误的位置,提醒你修改
	char *start = str;
	while (*str)
	{
		str++;
	}
	return str - start;
}

int main()
{
	char arr[] = "abcdef";
	size_t len = my_strlen3(arr);
	printf("%zd\n", len);//链式访问(一个函数的返回值是另一个函数的参数)
	return 0;
}

2.长度不受限制的字符串函数

不关心目标空间够不够大
不关心操作字符串的长度

2.1 strcpy(字符串拷贝)

具体介绍链接

char* strcpy(char *destination, const char *source);
介绍:

Copies the C string pointed by source into the array pointed by
destination, including the terminating null character (and stopping at that point).
将源指向的 C 字符串复制到目标指向的数组中,包括终止的 null(‘\0’) 字符(并在该点停止)。

注:
  • 源字符串必须以 ‘\0’ 结束。
    在这里插入图片描述
  • 会将源字符串中的 ‘\0’ 拷贝到目标空间。
    在这里插入图片描述
  • 目标空间必须足够大,以确保能存放源字符串。(否则会报错)
    在这里插入图片描述
  • 目标空间必须可变。(因为要把另一个字符串拷贝到这里)
  • 返回值是目标空间的起始地址,然后通过%s来打印,%s是从给的地址开始 *解引用打印,遇到’\0’结束
  • 学会模拟实现。

    模拟实现strcpy:
#include <stdio.h>
#include <assert.h>
char* my_strcpy(char* destination, const char* source)
//source指向的源字符串不需要改变,可以用const保护起来
//destination指向的目标空间必须可变,不能用const修饰

{
	assert(destination && source);//断言(需要头文件assert.h),防止str为空指针。若为空指针(==0),会报错,而且会指出错误的位置,提醒你修改
	char* start = destination;
	while (*destination++ = *source++)
		//当*source=='\0'时,整个表达式的结果为'\0',
		//又因为'\0'的ASCII码(在内存中存储的I)是0,所以为假,循环结束
	
	{
		;
	}
	return start;
}

int main()
{
	char arr1[20] = "xxxxxxxxxx";
	char arr2[] = "abcdef";

	my_strcpy(arr1, arr2);
	printf("%s\n", arr1);//或printf("%s\n", my_strcpy);

	return 0;
}

1.3 strcat(字符串追加)

具体介绍链接

char * strcat ( char * destination, const char * source );
介绍:

将源字符串追加到目标字符串中,源字符串的结束标志 ‘\0’ 被 source的第一个字符覆盖,并且在两者串联形成的新字符串的末尾包含一个’\0’(相当于将源字符串的’\0’也追加过去) 。

注:
  • 目标空间必须要有’\0’,保证能找到目标空间的末尾,进行追加。(编译器认为从左到右第一个’\0’是字符串的末尾)

  • 源字符串必须以 ‘\0’ 结束。(在追加时源字符串的’\0’也追加过去)
    在这里插入图片描述

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

  • 目标空间必须可修改。

  • strcat返回的是目标空间的起始地址。

  • 学会模拟实现。

    模拟实现strcat :

//模拟实现strcat
#include <stdio.h>
#include <assert.h>

char* my_strcat(char* des, const char* sou)
{
	char* start = des;
	assert(des && sou);//断言

	//1.找到目标字符串的末尾('\0')
	while (*des)//找到末尾'\0'后跳出循环
	{
		des++;
	}

	//2.数据追加
	while (*des++ = *sou++)//将源字符串的末尾'\0'拷贝过去的同时也结束拷贝
	{
		;
	}
	return start;
}

int main()
{
	char arr1[20] = "abc";
	char arr2[] = "def";

	my_strcat(arr1, arr2);
	printf("%s\n", arr1);//printf("%s\n", strcat(arr1, arr2));
	
	return 0;
}

  • 字符串自己给自己追加,会发生什么呢?
  1. 若用刚刚自己模拟的函数追加,会死循环。
    在这里插入图片描述

在这里插入图片描述
2. 用vs自带的库函数却能正常追加
在这里插入图片描述
这说明vs库函数中strcat的实现方式和自己的实现方式有所差异,其实不同编译器对库函数的实现方式都可能有所差异。所以stccat在VS上能自己追加自己,但其他编译器不一定可以。
若非要自己追加自己,建议使用strncat。

2.3 strcmp(字符串比较)

具体介绍链接

int strcmp ( const char * str1, const char * str2 );
介绍:
  1. 此函数开始比较每个字符串的第一个字符,如果它们相等,则继续向下比较,直到字符不同或达到终止空字符(‘\0’)
  2. 比较的不是长度,而是对应位置上字符的大小ASCII码,因为字符在内存中是以ASCII码的形式存储的)
C语言标准规定:
返回值(整型)解释
大于 0第一个字符串大于第二个字符串
0第一个字符串等于第二个字符串
小于 0第一个字符串小于第二个字符串
不同的编译器具体返回的值不同
模拟实现strcmp :
//模拟实现strcmp
#include <stdio.h>
#include <assert.h>

int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 && str2);//断言,防止为空指针
	while (*str1 == *str2)
	{
		if (*str1 == '\0')//同时为'\0'时,两个字符串才相等
		{
			return 0;
		}
		str1++;
		str2++;
	}
	return *str1 - *str2;
	//或
	//if (*str1 > *str2)
	//{
	//	return 1;
	//}
	//else
	//{
	//	return -1;
	//}
	
}

int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abp";
	if (my_strcmp(arr1, arr2) > 0)
	{
		printf(">\n");
	}
	else if(my_strcmp(arr1, arr2) == 0)
	{
		printf("=\n");
	}
	else
	{
		printf("<\n");
	}
	return 0;
}

在这里插入图片描述

从这分成两篇博文:

总结

我们一起学习了计算字符串长度的函数和长度不受限制的字符串函数。
感谢大家的阅读,大家一起进步!

点赞收藏加关注,C语言学习不迷路!
图片来源于网络

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

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

相关文章

CTF-python爬虫学习笔记

学习链接 【Python爬虫】爆肝两个月&#xff01;拜托三连了&#xff01;这绝对是全B站最用心&#xff08;没有之一&#xff09;的Python爬虫公开课程&#xff0c;从入门到&#xff08;不&#xff09;入狱 &#xff01; 。知识 1.1 出现错误 复制红框中的内容去查找 1.2 打印…

七、2023.10.1.Linux(一).7

文章目录 1、 Linux中查看进程运行状态的指令、查看内存使用情况的指令、tar解压文件的参数。2、文件权限怎么修改&#xff1f;3、说说常用的Linux命令&#xff1f;4、说说如何以root权限运行某个程序&#xff1f;5、 说说软链接和硬链接的区别&#xff1f;6、说说静态库和动态…

字符串函数(二)—— 长度受限制的字符串函数

✨博客主页&#xff1a;小钱编程成长记 &#x1f388;博客专栏&#xff1a;进阶C语言 &#x1f388;相关博文&#xff1a;字符串函数&#xff08;一&#xff09; 字符串函数&#xff08;二&#xff09;—— 长度受限制的字符串函数 3.长度受限制的字符串函数3.1 strncpy&#x…

594.最长和谐子序列(滑动窗口)

目录 一、题目 二、代码 一、题目 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 二、代码 class Solution { public:int findLHS(vector<int>& nums) {sort(nums.begin(), nums.end());int left 0, right 0;int MaxLength 0;while…

【网络安全-SQL注入】SQL注入----一篇文章教你access数据库SQL注入以及注入点利用。SQL注入【3】

前言&#xff1a; 本篇文章以凡诺企业网站管理系统为例&#xff0c;讲解了access数据库是如何进行SQL注入的&#xff0c;以及注入点如何利用&#xff0c;如何判断查询字段个数&#xff0c;如果用联合查询爆出数据库数据等&#xff1b; 之前有两篇文章详细介绍了MySQL数据库的…

Qt Creator 预览界面 快捷键

一般来说&#xff0c;我们运行Qt程序所花费的时间是比较长的&#xff0c;那有时我们只改变了界面&#xff0c;那么此时花费如此长的时间去运行程序来观察界面改动的效果是非常浪费时间的行为。 此时我们可以选择预览界面来观察界面改动后的效果&#xff1a;

九、GC收集日志

JVM由浅入深系列一、关于Java性能的误解二、Java性能概述三、了解JVM概述四、探索JVM架构五、垃圾收集基础六、HotSpot中的垃圾收集七、垃圾收集中级八、垃圾收集高级👋GC收集日志 ⚽️1. 认识GC收集日志 垃圾收集日志是一个重要的信息来源,对于与性能相关的一些悬而未决的…

基本的五大排序算法

目录&#xff1a; 一&#xff0c;直接插入算法 二&#xff0c;希尔排序算法 三&#xff0c;选择排序 四&#xff0c;堆排序 五&#xff0c;冒泡排序算法 简介&#xff1a; 排序算法目前是我们最常用的算法之一&#xff0c;据研究表明&#xff0c;目前排序占用计算机CPU的时…

1003 我要通过!

一.问题&#xff1a; “答案正确”是自动判题系统给出的最令人欢喜的回复。本题属于 PAT 的“答案正确”大派送 —— 只要读入的字符串满足下列条件&#xff0c;系统就输出“答案正确”&#xff0c;否则输出“答案错误”。得到“答案正确”的条件是&#xff1a; 字符串中必须仅…

数组和切⽚ - Go语言从入门到实战

数组和切⽚ - Go语言从入门到实战 数组的声明 package main import "fmt" func main() { var a [3]int //声明并初始化为默认零值 a[0] 1 fmt.Println("a:", a) // 输出: a: [1 0 0] b : [3]int{1, 2, 3} //声明同时初始化 fmt.Println("b:…

番外6:下载+安装+配置Linux

#########配置Linux---后续 step08: 点击编辑虚拟机设置&#xff0c;选择下载好的映像文件.iso进行挂载&#xff1b; step09: 点击编辑虚拟机选项&#xff0c;选择UEFI启动模式并点击确定&#xff1b; step10: 点击开启虚拟机&#xff0c;选择Install rhel &#xff1b; 备注&…

架构的未来:微前端与微服务的融合

文章目录 微服务架构简介微前端架构简介微前端与微服务的融合1. 共享服务2. 基于事件的通信3. 统一的身份和认证4. 交付管道的集成 示例&#xff1a;使用微服务和微前端的电子商务平台微服务架构微前端架构融合微服务和微前端 结论 &#x1f389;欢迎来到架构设计专栏~架构的未…

【Linux系统编程】僵尸进程与孤儿进程

文章目录 1. 僵尸进程2. 僵尸进程的危害3. 孤儿进程 1. 僵尸进程 上一篇文章进程的状态中最后我们提出了僵尸状态&#xff1a; 为了方便子进程退出后父进程或操作系统获取该进程的退出结果&#xff0c;Linux进程退出时&#xff0c;进程一般不会立即死亡&#xff0c;而是要维持…

【Spring底层原理】BeanFactory的实现

&#x1f40c;个人主页&#xff1a; &#x1f40c; 叶落闲庭 &#x1f4a8;我的专栏&#xff1a;&#x1f4a8; c语言 数据结构 javaEE 操作系统 Redis 石可破也&#xff0c;而不可夺坚&#xff1b;丹可磨也&#xff0c;而不可夺赤。 容器实现 一、BeanFactory实现的特点1.1 Be…

2023年中国半导体IP行业发展概况及趋势分析:半导体IP的市场空间广阔[图]

半导体指IP指芯片设计中预先没计、验证好的功能模块&#xff0c;处于半导体产业链最上游&#xff0c;为芯片设计厂商提供设计模块。半导体IP按交付方式可分为软核、硬核和固核&#xff1b;按产品类型可分为处理器IP、接口IP、其他物理IP及其他数字IP。 半导体IP分类 资料来源&…

K-Means(上):数据分析 | 数据挖掘 | 十大算法之一

⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ &#x1f434;作者&#xff1a;秋无之地 &#x1f434;简介&#xff1a;CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作&#xff0c;主要擅长领域有&#xff1a;爬虫、后端、大数据…

ubuntu 18.04 LTS安装opencv 3.4.16 + opencv_contrib 3.4.16

1.下载 opencv 3.4.16 opencv_contrib 3.4.16 其中&#xff0c;opencv_contrib解压后的多个文件夹复制到opencv内、合并 2.安装 参考博文&#xff1a; https://zhuanlan.zhihu.com/p/650792342 https://zhuanlan.zhihu.com/p/87197806 其中 &#xff08;1&#xff09;cmake前…

【设计模式】五、原型模式

文章目录 概述示例传统的方式的优缺点原型模式原理结构图-uml 类图 原型模式解决克隆羊问题的应用实例Sheep类实现clone()运行原型模式在 Spring 框架中源码分析 深入讨论-浅拷贝和深拷贝浅拷贝的介绍 小结 概述 示例 克隆羊问题 现在有一只羊 tom&#xff0c;姓名为: tom, 年…

nginx隐藏版本号和标识

1.隐藏版本号:nginx-服务器banner泄漏风险_banner信息泄露_javachen__的博客-CSDN博客 2.隐藏nginx标识 cd /usr/local/nginx-1.24.0/src/corevi nginx.h在第14行 cd /usr/local/nginx-1.24.0/src/httpvi ngx_http_special_response.c在第22,29,36行 cd /usr/local/nginx-1.2…

踩坑日记 uniapp 底部 tabber遮挡住购物车结算

tabbar 被购物车结算遮挡 在小程序上tabbar没有将固定栏遮挡&#xff0c;如果直接调高&#xff0c;浏览器H5页面是对了&#xff0c;但在小程序上面离底部的定位就太高了 原代码 // 底部结算样式.shop-foot {border-top: 2rpx solid #F7F7F7;background-color: #FFF;position: …