字符函数和字符串函数(1)

前言

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

1.求字符串长度
strlen

1.1 strlen

size_t strlen ( const char * str );

字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' )。

参数指向的字符串必须要以 '\0' 结束。
注意函数的返回值为size_t,是无符号的( 易错 )
学会strlen函数的模拟实现

 

 strlen是一个库函数,是用来求字符串的长度的,len1和len2的值是一样的,因为str是char*类型的指针,指向的是a的地址。

#define _CRT_SECURE_NO_WARNINGS 1
#include <string.h>
#include<stdio.h>
int main()
{const char* str = "abcdef";size_t len1 = strlen("abcdef");size_t len2 = strlen(str);printf("%d\n", len1);printf("%d\n", len2);return 0;
}

 需要注意的是strlen遇到\0就会停止统计,假设我们在c的后面放上\0,那么答案就是3.


 我们需要注意的是strlen的返回值是size_t,是无符号数,所以-3被认定为无符号数,最高位的1被认为是正数,所以结果是>=0。

#define _CRT_SECURE_NO_WARNINGS 1
#include <string.h>
#include<stdio.h>
int main()
{//两个无符号数相减得到的还是无符号数//  3             - 6//-3//10000000000000000000000000000011//11111111111111111111111111111100//11111111111111111111111111111101//if (strlen("abc") - strlen("abcdef") > 0)printf(">=\n");elseprintf("<\n");return 0;
}


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

 2.1 strcpy

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

源字符串必须以 '\0' 结束。
会将源字符串中的 '\0' 拷贝到目标空间。
目标空间必须足够大,以确保能存放源字符串。
目标空间必须可变。
学会模拟实现。

strcpy这个库函数的作用是 将指向的 C 字符串复制到目标指向的数组中,包括终止的 null 字符(并在该点停止)。

#define _CRT_SECURE_NO_WARNINGS 1
#include <string.h>
#include<stdio.h>
int main()
{char arr1[20] = {0};char arr2[] = "HELLO";strcpy(arr1, arr2);printf("%s\n", arr1);return 0;
}

 如果我们这样使用strcpy的话,就会出错,因为p里面存放的是常量字符串,是不能被修改的。

#define _CRT_SECURE_NO_WARNINGS 1
#include <string.h>
#include<stdio.h>
int main()
{char* p = "abcdefghi";char arr2[] = "HELLO";strcpy(p, arr2);//errprintf("%s\n", p);return 0;
}

2.2 strcat

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

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

 strcat这个库函数的参数跟strcpy是一样的。这个库函数运行的第一步应该是找到目标字符串的末尾,也就是\0,找到之后再把源字符串的内容追加到目标字符串里面去,并且源字符串的\0也会追加过去。

#define _CRT_SECURE_NO_WARNINGS 1
#include <string.h>
#include<stdio.h>
int main()
{char arr1[20] = "abc";char arr2[] = "def";strcat(arr1, arr2);printf("%s\n", arr1);return 0;
}

 


2.3 strcmp

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

 标准规定:
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字

 strcmp比较的不是长度,而是对应位置上的字符的大小(ASCII码值)。

如果第一个字符大小相同则进行后面的比较。

 这里我们需要重要的是strcmp的返回值是int类型,两个参数都是char*的指针,是不能被改变的。

 strcmp规定是:

目标字符串>源字符串则返回>0;

目标字符串<源字符串则返回<0;

目标字符串=源字符串则返回=0;

 但是在vs编译器上分别是1,-1,0。在各个编译器上的返回值是不一样的,满足条件即可。

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

3.长度受限制的字符串函数介绍
strncpy
strncat
strncmp

3.1strncpy

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

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

 

 strncpy和strcpy的前两个参数是一样的,只是返回值是char*的指针,返回的是目标字符串。并且strncpy还多了一个参数size_t num,下面这个代码的意思就是将源字符串的前三个字符拷贝到目标字符数组里面去。

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

 


3.2 strncat

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

 strncat和strcat的区别也是strncat要多一个参数size_t num,num就是我们要在目标字符串里面追加源字符串的字符个数,同时会将\0放在追加后的目标字符串的末尾。

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


3.2 strncmp

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

 strncmp和strcmp的区别也是strncmp要多一个参数size_t num,num就是两个字符串要比较的字符个数。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{char arr1[] = "abczef";char arr2[] = "abcqw";int ret = strncmp(arr1, arr2, 4);printf("%d\n", ret);return 0;
}

 因为'z'的ASCII码值大于’q‘,所以返回的是1.


4.strstr

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

 strstr就是在字符串中查找字符串,且是返回第一次出现的指针,如果没有则返回NULL。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{char arr1[] = "abcdefghiabcdeqghi";char arr2[] = "deq";char * ret = strstr(arr1, arr2);if (ret == NULL){printf("找不到\n");}else{printf("%s\n", ret);}return 0;
}

 

 如果次字符串出现多次,也是返回第一次出现的指针。


5.strtok

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

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

 strtok是用来切割字符串的,比如说下面这个代码,p里面是分隔符的集合,此时调用strtok函数就会在arr里面去找@,然后改成\0,同时返回z的地址。

#include<string.h>
int main()
{char arr[] = "sauxchnajd@yeah.net";char* p = "@.";char* s=strtok(arr, p);printf("%s\n", s);return 0;
}

 strtok函数会改变被操作的字符串,所以我们最好用一个临时拷贝的内容并且可修改,所以使用strcpy将字符串的内容拷贝过来,这个时候想怎么改buf都可以,对arr没有影响。

int main()
{char arr[] = "sauxchnajd@yeah.net";char* p = "@.";char buf[200] = {0};strcpy(buf, arr);char* s=strtok(buf, p);printf("%s\n", s);return 0;
}

strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。所以我们如果要找第二个分隔符,我们就进行第二次调用strtok,第一个参数用NULL,这时strtok就会在第一个标记开始往后查找。

int main()
{char arr[] = "sauxchnajd@yeah.net";char* p = "@.";char buf[200] = {0};strcpy(buf, arr);char* s=strtok(buf, p);printf("%s\n", s);s = strtok(NULL, p);printf("%s\n", s);return 0;
}

 我们再次调用效果和第二次就是一样的了,在标记后往后查找。

int main()
{char arr[] = "sauxchnajd@yeah.net";char* p = "@.";char buf[200] = {0};strcpy(buf, arr);char* s=strtok(buf, p);printf("%s\n", s);s = strtok(NULL, p);printf("%s\n", s);s = strtok(NULL, p);printf("%s\n", s);return 0;
}

如果字符串中不存在更多标记的时候,则返回空指针。 

strtok函数的真正用法是下面这个代码:

当使用p第一次切割arr的时候,如果返回值不是NULL,则打印出s指向的字符串,然后调整阶段就二次调用,使用NULL。这个for循环的初始化部分只执行了一次,因为strtok这个函数只有第一次传的是非空指针,后面都是NULL。

int main()
{char arr[] = "sauxchnajd@yeah.net";char* p = "@.";char buf[200] = {0};strcpy(buf, arr);char* s = NULL;for (s = strtok(buf, p);s!=NULL;s=strtok(NULL,p)){printf("%s\n", s);}return 0;
}

 


6.strerror

char * strerror ( int errnum );

strerror这个函数是将错误码翻译成错误信息,返回错误信息的字符串的起始地址 。

那么什么是错误码呢?无论是使用库函数还是进行正规的软件设计的时候都会设计错误码,就是当程序发生错误的时候,会报出错误信息。在C语言中,如果发生错误就会将错误码放在errno的变量中,errno是一个全局变量,可以直接使用。我们如果想知道0,1,2,3这种数字在错误码中代表着上面,那我们就使用strerror来试一下:

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

 但正常的使用方法是发生什么问题我们就将这个问题的错误码传给strerror,然后翻译出来。

这里举一个打开文件的例子,fopen 以读的形式打开文件,如果文件存在,打开成功,如果文件不存在,打开失败。

int main()
{FILE* pf = fopen("add.txt", "r");if (pf == NULL){printf("打开文件失败,原因是:%s\n", strerror(errno));return 1;}else{printf("打开文件成功\n");}return 0;
}

 

 这里还有一个函数叫perror,直接打印错误码,所对应的错误信息。可以这样理解,perror == printf + strerror。

int main()
{FILE* pf = fopen("add.txt", "r");if (pf == NULL){perror("打开文件失败"); return 1;}else{printf("打开文件成功\n");}return 0;
}


今天的分享到这里就结束啦!谢谢老铁们的阅读,让我们下期再见。

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

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

相关文章

Windows安装cuda和cudnn教程最新版(2023年9月)

文章目录 cudacudnn cuda 查看电脑的cuda最高驱动版本&#xff08;适用于N卡电脑-Nvidia&#xff09; winR打开命令行&#xff0c;输入nvidia-smi 右上角cuda -version就是目前支持的最高cuda版本&#xff0c;目前是12.2 nvidia官网下载cuda 下载地址&#xff1a;https://d…

华为NFC设置教程(门禁卡/公交卡/校园卡等)

今天把华为NFC设置教程分享给大家 出门带门禁卡、校园卡、银行卡、身份证……东西又多&#xff0c;携带又麻烦&#xff0c;还容易搞丢&#xff0c;有没有一种方法可以把它们都装下&#xff1f;有&#xff01;只要一部手机&#xff0c;出门不带卡包&#xff0c;各种证件&#x…

010_第一代软件开发(二)

第一代软件开发(二) 文章目录 第一代软件开发(二)项目介绍界面布局功能完善快照功能获取可用串口播放按键提示音 关键字&#xff1a; Qt、 Qml、 QSerialPort、 QPixmap、 QSoundEffect 项目介绍 欢迎来到我们的 QML & C 项目&#xff01;这个项目结合了 QML&#xff…

主打低功耗物联网国产替代,纵行科技ZT1826芯片以速率和灵敏度出圈

在低功耗物联网领域&#xff0c;国产替代的趋势越演越烈。 9月20日&#xff0c;纵行科技在“IOTE 2023深圳物联网通信技术与应用高峰论坛”发表了“自主原创Advanced M-FSK调制技术助力国产替代和泛在物联”的演讲&#xff0c;并推出了ZT1826芯片&#xff0c;以“更低功耗、更…

NetSuite BOM成本查询

这是个23.2的新功能&#xff0c;如题所示是对BOM成本的一个查询工具&#xff0c;是对之前版本那个无用的“Costed Bill of Materials Inquiry”的一次救赎。 其重要的功能是&#xff1a; •基于BOM所使用的版本、工艺路线和成本模板&#xff0c;通过Break Down的方式计算一个装…

超好用的接口自动化框架,lemon-easytest内测版发布,赶紧用起来~

easytest easytest 是一个接口自动化框架。 功能特点&#xff1a; 支持 http 接口测试 支持 json&#xff0c;html,xml 格式的响应断言 支持数据库断言 支持用例标记筛选 支持用例失败重运行 支持多线程 安装 pip install lemon_easytest 快速使用 不需要写任何代码…

整合minio时出现的错误

Action:Correct the classpath of your application so that it contains compatible versions of the classes io.minio.S3Base and okhttp3.RequestBody 这个错误是我在整合minio时报的错&#xff0c;说实话遇到这个错误我还是很头大的&#xff0c;因为之前在springboot项目…

​2:DDD概念大白话

产品代码都给你看了&#xff0c;可别再说不会DDD&#xff08;二&#xff09;&#xff1a;DDD概念大白话 # 这是一个讲解DDD落地的文章系列&#xff0c;作者是《实现领域驱动设计》的译者滕云。本文章系列以一个真实的并已成功上线的软件项目——码如云&#xff08;https://www…

【吴恩达老师《机器学习》】课后习题5之【偏差与方差】

在本练习中&#xff0c;您将实现正则化线性回归&#xff0c;并使用它来研究具有不同偏差-方差特性的模型。 在练习的前半部分&#xff0c;您将实现正则化线性回归&#xff0c;利用水库水位的变化来预测从大坝流出的水量。在后半部分中&#xff0c;您将对调试学习算法进行一些诊…

【C# Programming】值类型、良构类型

值类型 1、值类型 值类型的变量直接包含值。换言之&#xff0c; 变量引用的位置就是值内存中实际存储的位置。 2、引用类型 引用类型的变量存储的是对一个对象实例的引用&#xff08;通常为内存地址)。 复制引用类型的值时&#xff0c;复制的只是引用。这个引用非常小&#xf…

yum和vim工具的使用

目录 yum工具的使用 yum下载原理 软件的查找&下载&删除操作 查找lrzsz软件&#xff08;文件上传或者下载软件&#xff09; 下载lrzsz软件 删除lrzsz软件 vim工具的使用 vim命令模式 命令模式与光标相关的快捷键&#xff1a; 插入模式 底行模式 在本次的博客当中我们主要…

云服务部署:AWS、Azure和GCP比较

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

游戏扫码登录+多功能工具箱 微信小程序源码

一个集合了多种实用功能的微信小程序&#xff0c;这个微信小程序源码不仅具备美观的界面设计&#xff0c;还拥有许多实用的功能&#xff0c;而且最重要的是&#xff0c;它无需服务器和域名&#xff0c;所有功能都无需API接口&#xff0c;因此不用担心功能失效的问题。这意味着&…

利用PPT导出一张高清图的方法,office与WPS只需要使用一个即可,我使用的是office。

利用PPT导出一张高清图的方法&#xff0c;office与WPS只需要使用一个即可&#xff0c;我使用的是office。 1&#xff0c;PPT的功能拓展来解决导出高清图片方法1.1&#xff0c;PPT功能拓展—>安装插件&#xff1a; 2&#xff0c;各种方法导出图片效果显示&#xff1a;2.1&…

Linux下git安装及使用

Linux下Git使用 1. git的安装 sudo apt install git安装完&#xff0c;使用git --version查看git版本 2. 配置git git config --global user.name "Your Name“ ##配置用户 git config --global user.email emailexample.com ##配置邮箱git config --global --list …

NLP BigModel

NLP 基础 建议看 [CS224N 2023]打基础 【NLP入门】1. n元语法模型 / 循环神经网络 【NLP入门】3. Word2Vec / GloVe Language Model&#xff1a;语言模型的马尔可夫假设&#xff08;每个词出现的概率仅依赖前面出现的词&#xff09;&#xff0c;是一个自回归模型&#xff08;…

docker部署nginx下日志自动切割方法

前言&#xff1a;nginx采用docker部署&#xff0c;简单方便&#xff0c;但出现一个问题&#xff0c;就是日志没有自动切割&#xff0c;导致access.log 无限增大。如果非docker安装&#xff0c;则nginx的日志默认有切割的&#xff0c;那docker为何没有呢&#xff0c;最后发现&am…

git | 合并merge、衍合rebase与同步更新cherry-pick

git | 合并merge、衍合rebase与同步更新cherry-pick 文章目录 git | 合并merge、衍合rebase与同步更新cherry-pickgit meregegit rebasegit rebase和git merge的区别总结 cherry-pick 把别的分支的改动内容同步更新到自己的分支Example: Reference 欢迎关注公众号“三戒纪元” …

第 4 章 串(文本行编辑实现)

1. 背景说明 该文本编辑器利用串的堆实现&#xff0c;其中对串的原始存储方式基本不作修改&#xff08;有部分修改之处&#xff09;&#xff0c;优化之处在于在串的末尾加上了一个空字符&#xff0c;目的是区分字符串结尾&#xff0c;便于将串保存在文件中&#xff0c;且该优化…

K8S:Pod容器中的存储方式及PV、PVC

文章目录 Pod容器中的存储方式一&#xff0e;emptyDir存储卷1.emptyDir存储卷概念2.emptyDir存储卷示例 二.hostPath存储卷1.hostPath存储卷概念2.hostPath存储卷示例 三.nfs共享存储卷1.nfs共享存储卷示例 四.PV和PVC1.PV、PVC概念2.PVC 的使用逻辑及数据流向3.storageclass插…