(20)从strlen到strtok:解码C语言字符函数的“生存指南1”

news2025/4/20 14:58:19

主页图
❤个人主页:折枝寄北的博客
❤专栏位置:简单入手C语言专栏

目录

  • 前言
  • 1. 求字符串长度函数
    • 1.1 strlen
  • 2. 长度不受限制的字符串函数
    • 2.1 strcpy
    • 2.2 strcat
    • 2.3 strcmp
  • 3. 长度受限制的字符串函数
    • 3.1 strncpy
    • 3.2 strncat
    • 3.3 strncmp
  • 4. 字符串查找函数
    • 4.1 strstr
    • 4.2 strtok
  • 感谢您的阅读支持,欢迎交流

前言

当你写下strcpy(dest, src)这行看似无害的代码时,是否意识到自己正在操作系统的血管里进行一场没有安全绳的高空走钢丝?在C语言的世界里,字符串从来都不是温顺的数据羔羊,而是戴着可爱面具的"内存刺客"——那些优雅的str开头的函数库,既是程序员最亲密的工具,也是引发段错误(Segmentation Fault)的经典元凶。

1. 求字符串长度函数

1.1 strlen

库中的规范定义形式如下:

size_t strlen ( const char * str );

strlen函数是用来求字符串长度的常用库函数
在使用的时候要注意以下几点:

  • 字符串已经 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数(不包含 ‘\0’ )
  • 参数指向的字符串必须要以 ‘\0’ 结束。
  • 注意函数的返回值为size_t,是无符号的**( 易错 )**

** strlen函数模拟实现**

//版本1
int my_strlen(const char* str)
{
	assert(str != NULL);//断言
	int count = 0;
	while (*str != '\0')
	{
		count++;
		str++;
	}
	return count;
}


//2递归的方式
int my_strlen(const char* str)
{
	assert(str != NULL);//断言
	int count = 0;
	if (*str != '\0')
	{
		return 1 + my_strlen(str + 1);
	}
	else
		return 0;
}

//3指针-指针的方式
int my_strlen(const char* str)
{
	const char* start = str;
	assert(str != NULL);//断言
	while (*str)
	{
		str++;
	}
	return str - start;
}

int main()
{
	char arr[] = "abcdef";
	int len = my_strlen(arr);
	prinf("%d\n", len);
	return 0;
}

以上三种方式都是Int类型,但是在库中返回类型是size_t strlen是求字符串长度的,求出的长度是不可能为负数的。
所以返回类型是size_t,也是合情合理的 typedef unsigned int size_t size_t strlen (const char * str );

int main()
{
	if (strlen("abc") - strlen("abcdef") > 0)//  -3<0,应输出<
//注意:按实际情况来说,应该输出小于号,但是我们输出结果为">"
//strlen是size_t类型,都是无符号数,所以计算机认为-3是无符号数,其实是很大的数
//所以使用的时候要注意使用场景
		printf(">");
	else
		printf("<");

	return 0;
}

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

2.1 strcpy

库中的规范定义形式如下:

char* strcpy(char* destination, const char* source);

strcpy函数是字符串拷贝函数,在使用时要注意以下几点:

  • 必须保证字符串最后有\0,中间有\0也会被拷贝
  • 使用时要保证空间足够大
int main()
{
	char arr1[20] = "x";
	char* p = "abcdefg";
	char arr2[] = "hello world";
	strcpy(arr1, arr2);
	//strcpy(p, arr2);p是常量字符串,空间不可变,不可作为目的数组
	return 0;
}

模拟实现strcpy函数

模拟实现strcpy
int my_strcpy(char* dest, char* src)
{
	char* ret = dest;
	assert(dest && src);//断言二者不为空,不写也可以,但是这样方便找bug
		while (*dest++=*src++)
		{
			;
		}
		return ret;//返回目标空间起始地址
}
int main()
{
	char arr1[20] = " ";
	char arr2[] = "hello world";
	my_strcpy(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}

2.2 strcat

库中的规范定义形式如下:

char* strcat(char* destination, const char* source);

strcat函数是字符串追加函数,使用时要注意以下几点:

  • 源字符串必须以 ‘\0’ 结束。
  • 目标空间必须有足够的大,能容纳下源字符串的内容。
  • 目标空间必须可修改。
  • 字符串自己给自己追加,会失败,不可这样使用
nt main()
{
	char arr[20] = "hello ";
	strcat(arr, "world!");
	printf("%s\n", arr);
	
	return 0;
}
//遇到\0就停止追加内容

模拟实现strcat函数

char* my_strcat(char* dest, char* src)
{
	assert(dest && src);
	char* ret = dest;
	//1.找目标空间的\0
	while (*dest != '\0')
	{
		dest++;

	}
	//2.追加
	while (*dest++ = *src++)
	{
		;
	}
	return ret;
	//
}
int main()
{
	char arr[20] = "hello ";
	my_strcat(arr, "world!");
	printf("%s\n", arr);

	return 0;
}

2.3 strcmp

库中的规范定义形式如下:

int strcmp ( const char * str1, const char * str2 );

strcmp函数是字符串比较函数,使用时要注意其返回值:

  • 第一个字符串大于第二个字符串,则返回大于0的数字
    第一个字符串等于第二个字符串,则返回0
    第一个字符串小于第二个字符串,则返回小于0的数字
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abq";
	//在vs环境下:
	//>  1
	//<  -1 
	//=  0
	int ret = strcmp(arr1, arr2);
	//比较的是相同位置的字符大小
	printf("%d\n", ret);
	return 0;
}

strcmp函数的模拟实现

int my_strcmp(const char* str1,const char* str2)
{
	assert(str1 && str2);
	while (*str1 == *str2)
	{
		if (*str1 == '\0')
			return 0;
		str1++;
		str2++;
	}
	if (*str1 > *str2)
		/*	return 1;
		else
			return -1;*/
			//也可以写为:
		return *str1 - *str2;
}
int main()
{
	char arr1[] = "abq";
	char arr2[] = "abcdef";
	//在vs环境下:
	//>  1
	//<  -1 
	//=  0
	int ret = my_strcmp(arr1, arr2);


	//比较的是相同位置的字符大小
	printf("%d\n", ret);
	return 0;
}

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

3.1 strncpy

库中的规范定义形式如下:

char* strncpy(char* destination, const char* source, size_t num);

strncpy函数的功能是只拷贝要求数量的字符,使用时要注意以下几点:

  • 拷贝num个字符从源字符串到目标空间。
  • 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。

使用strncpy函数示例

int main()
{
	char arr1[20] = "xxxxxx" ;
	strncpy(arr1, "abcedf", 3);
	//只拷贝3个字符,没有拷贝\0
	printf("%s\n", arr1);

	return 0;

}

3.2 strncat

库中的规范定义形式如下:

char * strncat ( char * destination, const char * source, size_t num );

strncat函数的功能是加上指定数量的字符,使用与strncpy函数类似

strncat函数使用示例

int main()
{
	char* p1 = "abcdef";
	char* p2 = "abcqef";
	int ret = strncat(p1, p2, 4);
	printf("%d\n", ret);

	return 0;
}

3.3 strncmp

库中的规范定义形式如下:

int strncmp ( const char * str1, const char * str2, size_t num );

strncmp函数的功能是只比较要求数量的字符,使用的情况与3.1和3.2类似

strncmp函数使用示例

int main()
{
	char* p1 = "abcdef";
	char* p2 = "abcqef";
	int ret = strncmp(p1, p2, 4);
	printf("%d\n", ret);

	return 0;
}

4. 字符串查找函数

4.1 strstr

库中的规范定义形式如下:

const char * strstr ( const char * str1, const char * str2 );
char* strstr(char* str1, const char* str2);

strstr函数的功能是在字符串中寻找子字符串

strstr函数使用示例

int main()
{
	char arr1[] = "abbbabcdef";
	char arr2[] = "abc";
	char* ret = strstr(arr1, arr2);
	if (ret == NULL)
	{
		printf("没找到对应字符串\n");
	}
	else
	{
		printf("找到对应的字符串\n");
	}

	return 0;	
}

strstr函数简单模拟实现

char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);
		if (*str2 == '\0')
		{
			return (char*)str1;
		}
		//创建三个指针  
		const char* s1 = str1;
		const char* s2 = str2;
		const char* cp = str1;
		
		while (*cp)
		{
			s1 = cp;
			s2 = str2;
			while (*s1!='\0'&&*s2!='\0'&& * s1 == *s2)
			{
				s1++;
				s2++;
			}
			if (*s2 == '\0')
			{
				return (char*)cp;
			}
			cp++;
		}
		return NULL;
}

int main()
{
	char arr1[] = "abbbabcdef";
	char arr2[] = "abdd";
	char* ret = strstr(arr1, arr2);
	if (ret == NULL)
	{
		printf("没找到对应字符串\n");
	}
	else
	{
		printf("找到对应的字符串\n");
	}

	return 0;
}

4.2 strtok

库中的规范定义形式如下:

char * strtok ( char * str, const char * sep );

使用strtok函数时要注意以下几点:

  • sep参数是个字符串,定义了用作分隔符的字符集合
  • 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
  • 函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
  • strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
  • strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
  • 如果字符串中不存在更多的标记,则返回 NULL 指针。

strtok函数使用示例

int main()
{
	char arr[] = "doffer@vip.qq.com";//分隔符:@ .
	char* p = "@.";
	char buf[20] = { 0 };
	strcpy(buf, arr);
	char* ret = NULL;
	/*char* ret= strtok(buf, p);
	printf("%s\n", ret);*/
	ret2开始,继续从后面进行截断
	//char* ret2 = strtok(NULL, p);
	//printf("%s\n", ret2);
	//
	//char* ret3 = strtok(NULL, p);
	//printf("%s\n", ret3);

	//char* ret4 = strtok(NULL, p);
	//printf("%s\n", ret4);
	for (ret = strtok(buf, p); ret != NULL; ret = strtok(NULL, p))
	{
		printf("%s\n", ret);
	}
	return 0;
}

感谢您的阅读支持,欢迎交流

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

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

相关文章

Mongodb数据管理

Mongodb数据管理 1.登录数据库&#xff0c;查看默认的库 [rootdb51~]# mongo> show databases; admin 0.000GB config 0.000GB local 0.000GB> use admin switched to db admin > show tables system.version > admin库&#xff1a;admin 是 MongoDB 的管理…

从短片到长片:王琦携《Mountain》续作迈向新高度

在王琦(Qi Wang)的带领下,广受关注的短片《Mountain》迎来了成长篇续作《Rite of the Mountain》。这一全新长片不仅是她从短片迈向长篇叙事的重要一步,更是一次大胆的艺术挑战。作为制片人的她,将继续以敏锐的视觉风格和深刻的叙事洞察,拓展《Mountain》所触及的情感深度,并构…

DeepSeek应用——与PyCharm的配套使用

目录 一、配置方法 二、使用方法 三、注意事项 1、插件市场无continue插件 2、无结果返回&#xff0c;且在本地模型报错 记录自己学习应用DeepSeek的过程&#xff0c;使用的是自己电脑本地部署的私有化蒸馏模型...... &#xff08;举一反三&#xff0c;这个不单单是可以用…

如何画产品功能图、结构图

功能图的类型 常见的功能图包括数据流图、用例图、活动图、状态图、类图、组件图、部署图等等&#xff0c;不同的应用场景和目标下&#xff0c;需要确定不同的功能图类型。 数据流图 用例图 状态图 类图 组件图 组件图是由软件系统、组件和组件之间的关系组成的图形&#xf…

标准输入输出流,面向对象,构造函数

标准输入输出流 为什么不直接用printf和scanf? 不能输入/输出C新增的内容 std C的一些标识符&#xff0c;都是定义在std这个名字空间下面cout 是什么&#xff1f; 1.是一个ostream对象 output stream:输出流使用 <<&#xff1a;输出流运算符 作用&#xff1a;将右边…

PowerBI 矩阵 列标题分组显示(两行列标题)

先看效果 数据表如下&#xff1a; 我们在powerbi里新建一个矩阵&#xff0c;然后如图加入字段&#xff1a; 我们就会得到这样的矩阵&#xff1a; 我们在“可视化”->“列”&#xff0c;上双击&#xff0c;输入空格&#xff0c;就能消除左上角的"类别"两字 同理修…

服务器部署DeepSeek,通过Ollama+open-webui部署

1. 安装ollama 1.1. linux 安装 Ollama是目前常用的AI模式部署的第三方工具&#xff0c;能一键部署deepSeek Ollama官方网址https://ollama.com/ 选择Download下载对应的服务版本 服务器选择Linux&#xff0c;下面是下载代码 curl -fsSL https://ollama.com/install.…

Ubuntu 连接 air pods

&#xff11;&#xff0e; sudo vim /etc/bluetooth/main.conf , 修改蓝牙模式为blder &#xff12;&#xff0e;sudo /etc/init.d/bluetooth restart, 重启蓝牙&#xff0c;即可连接成功

民用无人驾驶航空器操控员考试

1. 注册 民用无人驾驶航空器综合管理平台 (caac.gov.cn) 2. 选择 操控员资质 3. 安全操控理论培训 -> 在线视频培训 学习完后选择 【在线考试】 共 50道 单项 选择题&#xff0c;每选项3个&#xff0c;80分及格。 4. 查看 我的合格证 证书有效期2年

002 第一个python程序

编程语言 编程语言可以做的事情&#xff1a; 网站开发、软件 、游戏、APP、 小程序、 爬虫、 数据分析、脚本 第一个python程序 找到IDE图标pycharm 新建项目 选择项目路径 创建目录 新建python文件 输入代码 运行程序查看结果 print 介绍 print : 输出内容…

解锁机器学习核心算法 | 决策树:机器学习中高效分类的利器

引言 前面几篇文章我们学习了机器学习的核心算法线性回归和逻辑回归。这篇文章我们继续学习机器学习的经典算法——决策树&#xff08;Decision Tree&#xff09; 一、决策树算法简介 决策树算法是一种典型的分类方法&#xff0c;也是一种逼近离散函数值的方法。它的核心思想…

数据结构——顺序表与链表

目录 前言 一线性表 二顺序表 1实现 2相关面试题 2.1移除元素 2.2删除有序数组中的重复项 3.3合并两个有序数组 3问题 三链表 1链表的分类 1.1单向或者双向 1.2带头或者不带头 1.3循环或者非循环 2实现 2.1尾插与头插 2.2尾删与头删 2.3pos前插入节点与删除…

在 Python 中使用 Ollama API

文章目录 一、环境准备二、使用方法1.简单对话2.流式响应3.结构化输出4.自定义客户端4.1 同步客户端4.2 异步客户端4.3 同步 & 异步客户端不同调用次数耗时对比测试 三、常用的ollama API 接口聊天生成本地模型列表显示模型信息创建模型复制模型删除模型拉取模型推送模型生…

BGP配置华为——RR反射器配置

实验拓扑 与之前实验同理将loop0作为routerID使用&#xff0c;且R1和R2上用loop1接口用于模拟用户其他网段 实验要求 1&#xff0c;在AS100内运行OSPF协议 2.配置路由反射器&#xff0c;使得从R1进入的数据能够反射到全局网络 3.在R1和R2上分别宣告自己的loop1口网段用于观…

一.AI大模型开发-初识机器学习

机器学习基本概念 前言 本文主要介绍了深度学习基础&#xff0c;包括机器学习、深度学习的概念&#xff0c;机器学习的两种典型任务分类任务和回归任务&#xff0c;机器学习中的基础名词解释以及模型训练的基本流程等。 一.认识机器学习 1.人工智能和机器学习 人工智能&am…

力扣做题记录 (二叉树)

二叉树 打算先来了解二叉树基础&#xff0c;都是简单题&#xff0c;目的是熟悉代码格式和解题基础思路。 1、二叉树最大深度 二叉树最大深度 方法一、深度搜索 直接用原函数做递归&#xff0c;比较简单 /*** Definition for a binary tree node.* struct TreeNode {* …

前端里的this指向问题

目录 1.代码输出结果 2.代码输出结果 3.代码输出结果 4.代码输出结果 5.代码输出结果 6.代码输出结果 7.代码输出结果 8.代码输出结果 9.代码输出结果 10.代码输出结果 11.代码输出结果 12.代码输出结果 13.代码输出结果 14.代码输出结果 总结 1.代码输出结果 f…

黑马Redis详细笔记(实战篇---短信登录)

目录 一.短信登录 1.1 导入项目 1.2 Session 实现短信登录 1.3 集群的 Session 共享问题 1.4 基于 Redis 实现共享 Session 登录 一.短信登录 1.1 导入项目 数据库准备 -- 创建用户表 CREATE TABLE user (id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT 用户ID,phone …

基于N-gram模型的中文文本分析系统设计与实现

前言 在数字化人文研究快速发展的背景下&#xff0c;中文古典文本的量化分析面临着独特的挑战。古典文献中繁简异体字共存、语义单元边界模糊、意象隐喻密集等特征&#xff0c;使得传统的词频统计方法难以准确捕捉其深层语言规律。现有文本分析工具多面向现代汉语设计&#xff…

零基础购买阿里云服务器,XShell连接云服务器

目录 1.环境搭建方式 2. 使用云服务器 3.使用终端软件登录到Linux 4.使用XShell登录主机 5.连接失败的原因&#xff1a; 下一篇更新&#xff1a;Linux的基础指令以及如何Linux的环境搭建 1.环境搭建方式 主要有四种: 1.直接安装在物理机上&#xff0c;虽然Linux有图形化…