【C语言基础】:字符串函数(二)

文章目录

      • 一、strncpy函数的使用
      • 二、strncat函数的使用
      • 三、strncmp函数的使用
      • 四、strstr函数的使用和模拟实现
        • 4.1 strstr函数的使用
        • 4.2 strstr函数的模拟实现
      • 五、strtok函数的使用
      • 六、strerror函数的使用

上节回顾:【C语言基础】:字符函数和字符串函数

一、strncpy函数的使用

函数原型:

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

strncpystrcpy的区别:
在这里插入图片描述
在这里插入图片描述
从函数的参数来看,strncpystrcpy前面几个参数都是char * destination, const char * source,也就是将source的内容拷贝到destination里面去,但是strncpy函数多了一个参数size_t num,也就是对拷贝的内容有了数量上的限制,而strcpy则对拷贝的内容没有数量上的限制。

从字符串中复制字符
将源的第一个num字符复制到目标。如果在复制num个字符之前找到源C字符串的结尾(用空字符表示),则目的地将用零填充,直到向其写入总数为num个字符。

如果source大于num,则不会在destination的末尾隐式添加空字符。因此,在这种情况下,destination不应被视为以空结束的C字符串(这样读取会溢出)。

【strncpy的使用】

#include<stdio.h>
#include<string.h>int main()
{char arr1[] = "abcdef";char arr2[20] = { 0 };strncpy(arr2, arr1, 3);printf("%s\n", arr2);return 0;
}

在这里插入图片描述
使用strncpy注意事项

  1. 是否将 \0拷贝
    首先我们要知道将arr1中的内容拷贝到arr2中,那是否会将arr1中的 \0也拷贝到arr2中呢?其实要验证这一点很简单,我们将arr2中的内容改成xxxxxxxxxxxx,然后再拷贝调试看一下。
#include<stdio.h>
#include<string.h>int main()
{char arr1[] = "abcdef";char arr2[20] = "xxxxxxxxxxxx";strncpy(arr2, arr1, 3);printf("%s\n", arr2);return 0;
}

在这里插入图片描述
在这里插入图片描述
在调试的时候可以看到,strncpy并没有将 \0给拷贝过去,另外我们运行之后可以看到打印之后把abc之后的x也打印出来了,如果 \0也拷过来的话,那么用\s打印的话遇到 \0就会停止打印。

  1. 拷贝数量大于原字符数量
    在使用strncpy时如果原字符串的数量小于要求拷贝的数量会怎么样呢?arr1中有abcdef六个字符,那如果要求拷贝10个字符该怎么办呢?我们还是来调试看一下。
#include<stdio.h>
#include<string.h>int main()
{char arr1[] = "abcdef";char arr2[20] = "xxxxxxxxxxxxxxx";strncpy(arr2, arr1, 10);printf("%s\n", arr2);return 0;
}

在这里插入图片描述
在这里插入图片描述
调试之后可以看到,但原字符串数量不够时,会用 \0来补充,不够10位就用 \0来不够10位。用/s打印到 \0就会停止,后面即使有内容也不会打印。

二、strncat函数的使用

函数原型:

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

从字符串中添加字符
将源的第一个num字符附加到目标,加上一个结束的空字符。
如果source中的C字符串的长度小于num,则只复制结束空字符之前的内容。

和上面的类似strncat和strcat的区别也是在于strncat函数多了一个size_t num的参数。
在这里插入图片描述
在这里插入图片描述
【strncat的使用】

#include<stdio.h>
#include<string.h>int main()
{char arr1[] = "abcdef";char arr2[20] = "xx";strncat(arr2, arr1, 3);printf("%s\n", arr2);return 0;
}

在这里插入图片描述
注意事项

  1. 是否追加 \0
    这里因为arr2的xx后面都是 \0,追加之后无法看出是否将 \0也追加了进来,但我们知道strcar是从 \0开始追加的,这里我们让他提前追加就行了。
    在这里插入图片描述
    可以看到,strncat会将 \0也追加进来。
  2. 追加字符数量大于原字符
    在这里插入图片描述
    调试之后可以看到,如果追加的数量大于原字符数量,那么将 \0追加完追后就不会继续追加了。

三、strncmp函数的使用

函数原型:

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

比较两个字符串的字符
比较C字符串str1和C字符串str2的最多num个字符。
这个函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续执行后面的对,直到字符不相同,直到达到终止的空字符,或者直到两个字符串中的num字符匹配,以先发生的为准。

在这里插入图片描述
在这里插入图片描述

【strncmp函数的使用】

#include<stdio.h>
#include<string.h>int main()
{char arr1[] = "abcdef";char arr2[] = "abqdefgui";int ret = strncmp(arr1, arr2, 3);printf("%d\n", ret);return 0;
}

在这里插入图片描述
第三个参数就是最多比较的次数,如果在这之前就比较出了结果,那么后面的也将不会再比较。

四、strstr函数的使用和模拟实现

函数原型:

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

查找子字符串
返回指向str1中str2第一次出现的指针,如果str2不是str1的一部分,则返回空指针。
匹配过程不包括结束的空字符,但它到此为止。
字符串的比较匹配不包含 \0 字符,以 \0 作为结束标志

4.1 strstr函数的使用
#include<stdio.h>
#include<string.h>int main()
{char arr1[] = "this is an apple\n";const char arr2[] = "is";char arr3[] = "pa";char* p = strstr(arr1, arr2);char* pa = strstr(arr1, arr3);printf("%s\n", p);printf("%s\n", pa);return 0;
}

在这里插入图片描述
返回arr2在arr1中第一次出现的指针,如果没有匹配到,就返回空指针。

4.2 strstr函数的模拟实现

模拟实现的函数参数类型以及返回类型:从原函数可以看出,参数是接收的arr1和arr2数组首元素的地址,也就是char* 类型的,我们只是用来进行比较匹配,为了防止被修改,参数前面都要加const进行修改。原函数的返回类型是arr2在arr1中第一次出现的指针,所以返回类型就是 char*。

char* my_strstr(const char* str1, const char* str2)
{}

模拟分析:

第一种情况
str1:abcdef\0
str2:bcd\0

这里arr1从b开始匹配一次就能匹配成功,当str2的指针指向\0时,就说明已经匹配到了,但需要有一个指针记录从哪里开始匹配的。

第二种情况
str1:abbbcdef\0
str2:bbc\0

这种情况就比较复杂,当str1中的第一个b和str2中的b匹配时,str2中的第一个和第二个都能匹配上,当第三个str2是c,而str1却是b,这时候又要回去重新进行匹配,但str2中的指针已经指向c了,没办法回去,所以这里不仅需要一个指针记录开始匹配的位置,还需要一个指针指向str2的开始位置,方便那个指针能指向回来。

第三种情况:
str1:abcdef\0
str2:bbq\0

这种情况最简单,就是匹配不到。

#include<stdio.h>char* my_strstr(const char* str1, const char* str2)
{const char* s1 = NULL;const char* s2 = NULL;const char* cur = str1;if (*str2 == '\0')return (char*)str1;while (*cur){s1 = cur;s2 = str2;while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2){s1++;s2++;}if (*s2 == '\0')  // 匹配完成{return (char*)cur;}cur++;}return NULL;  // 没找到
}int main()
{char arr1[] = "this is an apple\n";const char arr2[] = "is";char arr3[] = "pa";char* p = my_strstr(arr1, arr2);char* pa = my_strstr(arr1, arr3);printf("%s\n", p);printf("%s\n", pa);return 0;
}

在这里插入图片描述

五、strtok函数的使用

函数原型:

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

【strtok函数的使用】

#include<stdio.h>
#include<string.h>int main()
{char arr1[] = "zhangxu@qq.com";char arr2[30] = { 0 };strcpy(arr2, arr1);const char* sep = "@.";char* ret = NULL;for (ret = strtok(arr2, sep); ret != NULL; ret = strtok(NULL, sep)){printf("%s\n", ret);}// ret = strtok(arr2, sep);// printf("%s\n", ret);// ret = strtok(NULL, sep);// printf("%s\n", ret);// ret = strtok(NULL, sep);// printf("%s\n", ret);return 0;
}

在这里插入图片描述

六、strerror函数的使用

函数原型:

char * strerror ( int errnum );

strerror 函数可以把参数部分错误码对应的错误信息的字符串地址返回来。
在不同的系统和C语⾔标准库的实现中都规定了一些错误码,⼀般是放在 errno.h 这个头⽂件中说明
的,C语言程序启动的时候就会使用一个全局的变量errno来记录程序的当前错误码,只不过程序启动
的时候errno是0,表示没有错误,当我们在使用标准库中的函数的时候发生了某种错误,就会将对应
的错误码,存放在errno中,而一个错误码的数字是整数很难理解是什么意思,所以每⼀个错误码都是
有对应的错误信息的。strerror函数就可以将错误对应的错误信息字符串的地址返回。

【strerror函数的使用】

#include<stdio.h>
#include<string.h>int main()
{for (int i = 0; i <= 10; i++){printf("%d:\t%s\n", i, strerror(i));}return 0;
}

在这里插入图片描述

举例

#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{FILE* pFile;pFile = fopen("unexist.ent", "r");if (pFile == NULL)printf("Error opening file unexist.ent: %s\n", strerror(errno));return 0;
}

在这里插入图片描述

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

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

相关文章

软考高级:软件架构评估-质量属性-安全性概念和例题

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

子矩阵(十四届蓝桥杯python组A)

这题思路就是用两次单调队列。 下面是TIE的代码。9/10&#xff1b;用了priority_queue做单调队列&#xff0c;而不是手动写的。 &#xff08;手写单调队列好麻烦~~~&#xff0c;脑子晕死&#xff0c;考试的时候过了9个点也ok&#xff0c;&#xff09; #include<iostream&…

精确率(召回率)的权衡(Machine Learning研习十六)

精确率&#xff08;召回率&#xff09;的权衡 为了理解这种权衡&#xff0c;让我们看看 SGDClassifier如何做出分类决策。 对于每个实例&#xff0c;它根据决策函数计算分数。 如果该分数大于阈值&#xff0c;则将该实例分配给正类&#xff1b; 否则它会将其分配给负类。 图 3…

独孤思维:伪造收益图,进行副业收割

01 早年独孤混群。 刚开始只会发自己的副业项目资料。 资料里面全是钩子。 所以被群主踢了。 刚开始很生气&#xff0c;后来发现自己的社群也有人打广告。 才慢慢理解那种感受。 随后混的群&#xff0c;都是以价值分享和副业心得为主。 给社群的其他小伙伴&#xff0c;…

软考高级:软件架构评估:质量属性 - 易用性 和可测试性概念和例题

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

什么是Scala语言?

Scala 是一种多范式的编程语言&#xff0c;集面向对象编程和函数式编程的特性于一身&#xff0c;运行在 Java 虚拟机&#xff08;JVM&#xff09;上&#xff0c;并兼容现有的 Java 程序。Scala 的名字来源于 Scalable Language&#xff0c;意味着它是为了适应大型复杂软件系统的…

基于Springboot+vue的在线试题题库管理系统+数据库+报告+免费远程调试

项目介绍: Springbootvue的在线试题题库管理系统&#xff0c;Javaee项目&#xff0c;springboot vue前后端分离项目 本文设计了一个基于Springbootvue的前后端分离的在线试题题库管理系统&#xff0c;采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#x…

Github 2024-03-22 Java开源项目日报 Top10

根据Github Trendings的统计,今日(2024-03-22统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Java项目10Swift项目1Python项目1Java生态系统中的Spring框架教程集合 创建周期:3980 天开发语言:Java协议类型:MIT LicenseStar数量:35802…

git tag标签使用

创建标签 git checkout test git tag -a v1.0.0 -m v1.0.0里程碑版本 git push origin v1.0.0 删除标签 git tag -d v1.0.0 git push origin :refs/tags/v1.0.0远程分支可以直接在页面删除

【MySQL】3.1MySQL索引的介绍

目录 一、索引的概念 数据库索引 索引的作用 索引的副作用 索引创建的原则&#xff08;应用场景&#xff09; 适合建立索引 二、索引的分类和创建 1.普通索引 创建普通索引 1.1直接创建 1.2修改表结构的方式创建普通索引 1.3创建表时创建普通索引 2.唯一索引 2.1…

[python]bar_chart_race绘制动态条形图

最近在 B 站上看到了一个宝藏 up 主&#xff0c;名叫 "Jannchie见齐"&#xff0c;专门做动态条形图相关的数据可视化。 可以看到做出的效果还是很不错的&#xff0c;但工具使用的是 JS&#xff0c;不是 Python&#xff0c;于是尝试搜索了一下&#xff0c;看看 Python…

100个openharmony开源demo:1.日历

准备用开发者手机写100个开源的demo不知道能不能实现&#xff0c;日拱一卒&#xff0c;期待蜕变。 第一个demo&#xff1a;日历&#xff0c;借鉴了网上的日历算法&#xff0c;自己用arkts写了界面和点击事件&#xff0c;各位可根据此demo写自己的日历选择器等组件。 1.目录结…

Vue3、element-plus和Vue2、elementUI的一些转换

插槽 Vue3<template #default"scope"></template> <template #footer></template>Vue2<template slot-scope"scope"></template> <template slot"footer"></template>JS定义 Vue3 <script…

【5G NR 协议解读】3GPP TS 38.212 (R18) 复用和信道编码(二)

前言 本文基于3GPP TS 38.212 (R18) 复用和信道编码协议。 本文档规定了5G NR的编码、多路复用和物理信道映射。 5 总体流程 来自/去往MAC层的数据流和控制流会进行编码/解码&#xff0c;以便通过无线传输链路提供传输和控制服务。信道编码方案是错误检测、错误纠正、速率匹配…

ISO 8601:日期和时间的国际标准

ISO 8601 介绍 ISO 8601&#xff0c;介绍一下 ISO 8601 是由国际标准化组织&#xff08;International Organization for Standardization&#xff0c;ISO&#xff09;发布的国际标准&#xff0c;其全称为《数据存储和交换形式信息交换日期和时间的表示方法》。 这一标准提供了…

【网站项目】293学生用品采购系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

供应链投毒预警 | 恶意Py组件tohoku-tus-iot-automation开展窃密木马投毒攻击

概述 上周&#xff08;2024年3月6号&#xff09;&#xff0c;悬镜供应链安全情报中心在Pypi官方仓库&#xff08;https://pypi.org/&#xff09;中捕获1起新的Py包投毒事件&#xff0c;Python组件tohoku-tus-iot-automation 从3月6号开始连续发布6个不同版本恶意包&#xff0c…

【Docker】常用命令 docker search

文章目录 什么是docker search命令基本用法实际示例在Docker Hub搜索名为nginx的镜像搜索包含Python的镜像 常用选项--filter&#xff1a;过滤搜索结果--limit&#xff1a;限制搜索结果数量 总结 在Docker中&#xff0c; docker search命令是用于从Docker Hub或其他镜像仓库搜…

【Python 48小时速成 12】类和对象

在 Python 中&#xff0c;类是一种用于创建对象的蓝图或模板&#xff0c;而对象是根据类创建的实例。类定义了对象的属性和方法。下面是一个简单的类和对象的示例代码&#xff1a; # 定义一个名为 Person 的类 class Person:# __init__ 方法用于初始化对象的属性def __init__(…

sentinel系统负载自适应流控

系统负载自适应流控 规则配置 规则创建 public class SystemRule extends AbstractRule {private double highestSystemLoad -1;private double highestCpuUsage -1;private double qps -1;private long avgRt -1;private long maxThread -1; }SystemRule类包含了以下几…