字符函数和字符串函数(详解)

news2024/10/7 18:32:10

前言:内容包括:strlen,长度不受限制的字符串函数(strcpy,strcat,strcmp)

                             长度受限制的字符串函数(strncpy,strncat,strncmp),strstr 

1 求字符串长度 strlen

头文件:

#include <string.h>

结构:

size_t strlen ( const char * str )

字符串的结束标志是\0,strlen统计的是\0之前出现的字符个数

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = "abcd";
	int len = strlen(arr);
	printf("%d", len);
	return 0;
}

abcd的长度是4

模拟实现:三种方法

way1:计数器

int my_strlen(const char* str)
{
    assert(str);
	int count = 0;
	while (*str++)
	{
		count++;
	}
	return count;
}

可以使用assert断言,确保str不是空指针 ,若是str是空指针,程序会报错

assert的头文件:

#include <assert.h>

my_strlen需要返回字符串的长度,故而返回类型设计为int

my_strlen只负责遍历字符串统计长度,并不会对字符串进行任何修改,故而用const修饰*str保证字符串的内容不会被修改

*str++:++是后置++,故而*str++这个表达式的结果是*str的值,然后str++,再指向下一个字符

way2:递归

int my_strlen(const char* str)
{
    assert(str);
	if (*str != '\0')
	{
		return 1 + my_strlen(str + 1);
	}
	else
	{
		return 0;
	}
}

现有字符串:abcd

 首先判断字符串的首字符是否为\0

   1 若不是,则此字符串的长度:1+my_strlen(str+1)

   字符串abcd的首字符a不是\0,则字符串abcd的长度=1(表示1个字符,即a)+字符串bcd的长度

    2 若此字符串的首字符为\0,则说明此字符串一个字符也没有,长度为0 

way3:指针-指针

int my_strlen(const char* str)
{
    assert(str);
	char* start = str;
	while (*str)
	{
		str++;
	}
	return str - start;
}

指针-指针:计算的是指针和指针之间的元素个数

现有字符串:abcd

我们需要两个指针,一个指针start指向字符串的首字符,一个指针str指向字符串的\0

两个指针相减,即可得到此字符串的元素个数,即字符串的长度

2 字符串拷贝 strcpy

头文件:

#include <string.h>

 结构:

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

strcpy的第一个参数是目标空间的地址,第二个参数是源字符串的地址

#include<stdio.h>
#include<string.h>
int main()
{
    char arr1[] = "abcd";
    char arr2[20] = { 0 };
    strcpy(arr2, arr1);
    printf("%s", arr2);
}

模拟实现:strcpy会拷贝源字符串的\0

char* my_strcpy(char* dest, const char* src)
{
    assert(dest && src);
    char* ret = dest;
    while (*dest++ = *src++)
    {
        ;
    }
    return ret;
}

my_strcpy 只是遍历源字符串并拷贝它的内容到目标空间,不会对源字符串进行任何修改,故而用const修饰*src确保源字符串的内容不被修改

my_strcpy 需要拷贝源字符串的所有字符包括\0

my_strcpy会返回目标空间的起始地址

*dest++ = *src++:1 *dest=*src(拷贝字符) 2 dest++,src++(指向下一个字符)

这样可以做到将\0拷贝完成之后,由于*dest++ = *src++表达式的结果为0,自动结束while循环

3 字符串追加(不可自己追加自己)strcat 

自己追加自己会导致死循环,因为永远也找不到\0,故而无法停止

头文件:

#include <string.h>

结构: 

char * strcat ( char * destination, const char * source )
int main()
{
    char arr1[20] = "hello ";
    char arr2[] = "world";
    strcat(arr1, arr2);
    printf("%s", arr1);
}

 模拟实现:strcat会从目标空间中的字符串的\0开始拷贝,并且拷贝被追加字符串的\0

char* my_strcat(char* dest, const char* src)
{
    assert(dest && src);
    char* ret = dest;
    while (*dest)
    {
        dest++;
    }
    //此时dest指向的就是目标空间中的字符串中的\0
    while (*dest++ = *src++)//拷贝要追加的字符串内容
    {
        ;
    }
    return ret;
}

1 找到目标空间中的字符串的\0

2 从此\0开始拷贝,将被追加的字符串的所有字符包括\0拷贝到目标空间中

my_strcat会返回追加字符串后目标空间的起始地址

4 字符串比较 strcmp

头文件:

#include <string.h>

结构: 

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

返回一个整数值,该值指示字符串之间的关系:

返回值表明
<0第一个不匹配的字符在 str1 中的值低于 str2 中的值
0两个字符串的内容相等
>0第一个不匹配的字符在 str1 中的值大于在 str2 中的值

 

#include<string.h>
#include<stdio.h>
int main()
{
    char arr1[] = "abc";
    char arr2[] = "bde";
    int ret = strcmp(arr1, arr2);
    printf("%d", ret);
}

abc

bde

a与b不等,又a的ASCII码值<b的ASCII码值,故而第二个字符串大于第一个字符串,会返回一个<0的数值

abf

abd

a和a相等,比较下一对:b和b,相等,比较下一对:f和d

f和d不等,又f的ASCII码值>d的ASCII码值,故而第一个字符串>第二个字符串,返回一个>0的数值

abc

abc

这两个字符串的内容全部相等,则返回0

模拟实现:

int my_strcmp(const char* str1, const char* str2)
{
    assert(str1 && str2);
    while (*str1 == *str2)
    {
        if (*str1 == '\0')
        {
            return 0;
        }
        str1++;
        str2++;
    }
    return *str1 - *str2;
}

1 若两个对应位置上的字符相同,则跳过这一对位置,直至找到一对不等的字符

2 判断两个字符串完全相同(只会在while循环内部出现):一直比较至\0说明两个字符串相同,则返回0

   判断两个字符串不同:跳出while循环时说明找到了一对不等的字符,返回*str1-*str2,值>0说明第一个字符串大于第二个字符串,值<0说明第一个字符串小于第二个字符串

5 strncpy

头文件:

#include <string.h>

结构: 

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

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

int main()
{
    char arr1[] = "abf";
    char arr2[20] = { 0 };
    strncpy(arr2, arr1,2);
    printf("%s", arr2);
}

模拟实现: 

char* my_strncpy(char* dest, const char* src, size_t num)
{
    assert(dest && src);
    char* ret = dest;
    while (num--)
    {
        *dest++ = *src++;
    }
    return ret;
}

num:拷贝字符的个数

6 strncat 

头文件:

#include <string.h>

结构: 

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

要追加的字符串被追加完成后,strncat会自动添加一个\0 

int main()
{
    char arr1[20] = "hello ";
    char arr2[] = "world";
    strncat(arr1, arr2,3);
    printf("%s", arr1);
}

 模拟实现:

char* my_strncat(char* dest, const char* src, size_t num)
{
    assert(dest && src);
    char* ret = dest;
    while (*dest)
    {
        dest++;
    }
//此时*dest是目标空间中的字符串的\0
    while (num--)
    {
        *dest++ = *src++;
    }
    *dest = '\0';
    return ret;
}

1 找到目标空间中的字符串的\0

2 从此\0的位置开始拷贝,拷贝num次

3 在拷贝全部结束后在目标空间已经追加好后的字符串末尾,手动加上\0

7 strncmp

头文件:

#include <string.h>

结构:

int strncmp ( const char * str1, const char * str2, size_t num )
int main()
{
    char arr1[] = "abcde";
    char arr2[] = "abcfg";
    int ret = strncmp(arr1, arr2,4);
    printf("%d", ret);
}

ret返回的是<0的数值,第一个字符串小于第二个字符串

模拟实现:

int my_strncmp(const char* str1, const char* str2,size_t num)
{
    assert(str1 && str2);
    while (num--)
    {
        if (*str1 == *str2)
        {
            str1++;
            str2++;
        }
        else
        {
            return *str1 - *str2;
        }
    }
    return 0;
}

循环num次,若是对应位置上的字符相等,则跳过这一对

若是对应位置上的字符不相等,则返回*str1-*str2

当while循环结束后还没有返回过,则说明这num个字符的内容完全相同,返回0

8 字符串中查找某个字符串 strstr

头文件:

#include <string.h>

结构: 

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

在str1字符串中查找str2字符串,若是找不到则返回NULL,若是找到了,则返回str2第一次出现在str1中的地址

int main()
{
    char arr1[] = "abbbbcde";
    char arr2[] = "bbc";
    char *ret = strstr(arr1, arr2);
    if (ret == NULL)
    {
        printf("找不到\n");
    }
    else
    {
        printf("%s", ret);
    }
}

模拟实现: 

char* my_strstr(const char* str1, const char* str2)
{
    assert(str1 && str2);
    char* cp = str1;
    while (*cp)
    {
        char* s1 = cp;
        char* s2 = str2;
        while (*s1 && *s2 && *s1==*s2)
        {
            s1++;
            s2++;
        }
        if (*s2 == '\0')//匹配成功
        {
            return cp;
        }
        cp++;
    }
    return NULL;
}

cp:记录每个开始匹配的位置

str1字符串中的每个字符都有从它的位置开始向后匹配的可能

s1:负责遍历str1字符串

s2:负责遍历str2字符串

若是*s1==*s2,则说明当前匹配的一对字符相同,则s1++,s2++,判断下一对字符

若是*s1!=*s2,则匹配失败,cp++,指向下一个新的开始匹配的位置

当每个可能匹配成功的开始位置都循环遍历了之后还未返回有效地址,则说明在str1字符串中找不到str2字符串,返回NULL

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

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

相关文章

Java笔记029-泛型

泛型泛型的理解和好处看一个需求请编写程序&#xff0c;在ArrayList中&#xff0c;添加3个Dog对象Dog对象含有name和age&#xff0c;并输出name和age(要求使用getXxx)先用传统的方法来解决->引出泛型package com15.generic;import java.util.ArrayList;/*** author 甲柒* ve…

Docker Remote API未授权访问

目录Docker简述Docker 2375端口安全风险Docker命令连接利用声明&#xff1a;本文仅供学习参考&#xff0c;其中涉及的一切资源均来源于网络&#xff0c;请勿用于任何非法行为&#xff0c;否则您将自行承担相应后果&#xff0c;本人不承担任何法律及连带责任。Docker简述 Docke…

[GXYCTF 2019]Ping Ping Ping

禁了空格&#xff0c;并且不能用${IFS},因为{也禁了 ;ls发现 flag也被禁了 看index.php的源码 ;cat$IFS$9index.php 可以base64编码绕过 ;echo$ISF$9Y2F0IGZsYWcucGhw|base64$IFS$9-d|sh bash被禁了&#xff0c;所以用sh 可以内联执行绕过 ;cat$IFS$9ls 这个ls相当于看ind…

自组织( Self-organization),自组织临界性(Self-organized criticality)

文章目录1. 自组织概述原则历史按领域物理化学生物学2. 自组织临界性概述3. 自组织临界性的特征4. 自组织临界模型5. 自然界中的自组织临界6. 自组织临界性和优化7. 自组织临界性的控制7.1 方案7.2 应用1. 自组织 wiki: Self-organization 图 200 C 水热处理过程中微米级 Nb3O…

【游戏爆料】揭开“搬砖党”背后的秘密

在网络游戏行业繁荣的背后&#xff0c;存在着庞大的黑产链条&#xff0c;它严重威胁着游戏厂商的业务安全&#xff0c;破坏游戏属性的平衡&#xff0c;给玩家带来不好的游戏体验。有些玩家可能有疑惑&#xff0c;黑产是什么&#xff1f;分成哪些种类&#xff1f;其实&#xff0…

Windows系统下基于开源软件的多物理场仿真

Windows系统下基于开源软件的多物理场仿真实践技术应用随着计算机技术的发展&#xff0c;计算机仿真技术日益成为继实验和理论之后的第三种重要研究和设计手段。真实世界中遇到的问题往往是固体力学&#xff0c;流体力学&#xff0c;热&#xff0c;电磁等多种现象耦合而成&…

设计模式之不变模式

在并行软件开发过程中&#xff0c;同步操作是必不可少的。当多线程对同一个对象进行读写操作时&#xff0c;为了保证对象数据的一致性和正确性&#xff0c;有必要对对象进行同步操作&#xff0c;但同步操作对系统性能有损耗。不变模式可以去除这些同步操作&#xff0c;提高并行…

奇舞周刊第485期:3 个容易混淆的前端框架概念

记得点击文章末尾的“ 阅读原文 ”查看哟~下面先一起看下本期周刊 摘要 吧~奇舞推荐■ ■ ■3 个容易混淆的前端框架概念大家好&#xff0c;我卡颂。有 3 个容易混淆的前端框架概念&#xff1a;响应式更新 单向数据流 双向数据绑定 在继续阅读本文前&#xff0c;读者可以思考下…

Golang并发编程

Golang并发编程 文章目录Golang并发编程1. 协程2. channel2.1 channel的创建2.2 使用waitGroup实现同步3. 并发编程3.1 并发编程之runtime包3.2 mutex互斥锁3.3 channel遍历3.3.1 for if遍历3.3.2 for range3.4 select switch3.5 Timer3.5.1 time.NewTimer()3.5.2 Stop、reset…

分布式架构-可靠通讯-服务安全

系列目录 分布式架构-可靠通讯-零信任网络 分布式架构-可靠通讯-服务安全 引子 上一节“分布式架构-可靠通讯-零信任网络”里&#xff0c;我们探讨了与微服务运作特点相适应的零信任安全模型。本节&#xff0c;我们将从实践和编码的角度出发&#xff0c;介绍在前微服务时代(以 …

Lambda表达式与函数式接口

目录 自定义函数式接口 常用的内置函数式接口 1.Supplier接口 2.Consumer接口 3.Predicate接口 4.Function接口 自定义函数式接口 需求&#xff1a;实现两数的加减乘除 接口&#xff0c;函数式接口只能有一个抽象方法&#xff0c;且需要用注释FunctionInterface。 Func…

JUC高级一: CompletableFuture

JUC高级: CompletableFuture 1. 线程基础知识复习 1.1 JUC四大口诀 高内聚低耦合前提下&#xff0c;封装思想 线程—>操作---->资源类 判断、干活、通知 防止虚假唤醒,wait方法要注意使用while判断 注意标志位flag&#xff0c;可能是volatile的 1.2 为什么多线程及…

Webpack打包———处理样式资源

基本使用 本质上&#xff0c;webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。当 webpack 处理应用程序时&#xff0c;它会在内部从一个或多个入口点构建一个 依赖图(dependency graph)&#xff0c;然后将你项目中所需的每一个模块组合成一个或多个 bundles&a…

2.JVM常识之 jvm常见配置参数

1.常见的配置参数说明 常见配置 -Xms3072M -Xmx3072M -Xss1M -Xmn2048M -XX:MetaspaceSize256M -XX:MaxMetaspaceSize256M -XX:SurvivorRatio8 **-Xss&#xff1a;**每个线程的栈内存大小 默认是1M 说明一个线程栈里能分配的栈帧越少&#xff0c;但是对JVM整体来说能开启…

文档团队怎样使用GIT做版本管理

有不少小型文档团队想转结构化写作和发布&#xff0c;但是因为有限的IT技能和IT资源而受阻。本文为这样的小型文档团队而准备&#xff0c;描述怎样使用Git做内容的版本管理。 - 1 - 为什么需要版本管理 当一个团队进行协同创作内容时&#xff0c;有以下需要&#xff1a; 在对…

【C++】图

本文包含了图的基本概念 1.相关概念 1.1 无/有向 无向图&#xff1a;每一个顶点之间的连线没有方向 有向图&#xff1a;连线有方向&#xff08;类似离散数学的二元关系 <A,B>代表从A到B的边&#xff0c;有方向&#xff09; <A,B>中A为始点&#xff0c;B为终点在…

JDBC的API详解

&#x1f34e;道阻且长&#xff0c;行则将至。&#x1f353; 目录 一、DriverManager 驱动管理类 1.注册驱动 2.获取数据库连接 二、Connection 数据库连接对象 1.获取执行对象 2.事务管理 三、Statement 1.执行DDL、DML语句 2.执行DQL语句 四、ResultSet 以JDBC快速…

【漏洞复现】Grafana任意文件读取(CVE-2021-43798)

docker环境搭建 #进入环境 cd vulhub/grafana/CVE-2021-43798#启动环境&#xff0c;这个过程可能会有点慢&#xff0c;保持网络通畅 docker-compose up -d#查看环境 docker-compose ps直接访问虚拟机 IP地址:3000 目录遍历原理 目录遍历原理&#xff1a;攻击者可以通过将包含…

CNCF x Alibaba云原生技术公开课 第七章 应用编排与管理:Job和DaemonSet

1、Job&#xff1a;管理任务的控制器 概念 首先 kubernetes 的 Job 是一个管理任务的控制器&#xff0c;它可以创建一个或多个 Pod 来指定 Pod 的数量&#xff0c;并可以监控它是否成功地运行或终止&#xff1b;可以根据 Pod 的状态来给 Job 设置重置的方式及重试的次数&…

【Qt网络编程】实现TCP协议通信

文章目录概要&#xff1a;本期主要讲解QT中对于TCP协议通信的实现。一、TCP协议二、Qt中TCP协议处理1.QTcpSocket2.QTcpServer三、Qt实现TCP通信1.客户端2.服务器端结尾概要&#xff1a;本期主要讲解QT中对于TCP协议通信的实现。 一、TCP协议 传输控制协议&#xff08;TCP&am…