字符函数和字符串函数(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;
}

今天的分享到这里就结束啦!谢谢老铁们的阅读,让我们下期再见。
相关文章:
字符函数和字符串函数(1)
前言 C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在 常量字符串 中或者 字符数组 中。 字符串常量 适用于那些对它不做修改的字符串函数. 1.求字符串长度 strlen 1.1 strlen size_t strlen ( const char * s…...
Visual Studio Code从GIT拉取vue项目并运行
安装Visual Studio Code 安装GIT 安装node.js,配置好环境变量 拉取项目 文章一 文章二 运行项目 文章一 提交代码 文章一...
【知识分享】Java获取全年每个月的有几周且每周是几号到几号
加哥本周给大家分享一期怎么用java把全年每个月有几周,本周是几号到几号的工具类。便于大家根据需求获取想要的形式进行改造。话不多说,直接给大家上代码。 package com.techfantasy.common.utils; import com.techfantasy.common.entity.DateRange; i…...
学信息系统项目管理师第4版系列11_信息安全管理
1. 信息安全基础 1.1. 保密性(Confidentiality) 1.1.1. 信息不被未授权者知晓的属性 1.1.2. 确保信息不暴露给未授权的实体或进程 1.2. 完整性(Integrity) 1.2.1. 信息是正确的、真实的、未被篡改的、完整无缺的属性 1.2.2. 只有得到允许的人才能修改数据&…...
sql注入原理分析
...
Mac磁盘空间满了怎么办?Mac如何清理磁盘空间
你是不是发现你的Mac电脑存储越来越满,甚至操作系统本身就占了100多G的空间?这不仅影响了电脑的性能,而且也让你无法存储更多的重要文件和软件。别担心,今天这篇文章将告诉你如何清除多余的文件,让你的Mac重获新生。 一…...
能ping通但无法上网的问题
大家好,今天我要和大家分享一下当你的IP地址能够成功 ping 通,却无法上网时该如何解决这个问题。这是一个相当常见的情况,在网络故障排查中经常遇到。别担心,我将为你揭开这个谜题,提供一些解决方案和技巧。 首先&…...
仿制 Google Chrome 的恐龙小游戏
通过仿制 Google Chrome 的恐龙小游戏,我们可以掌握如下知识点: 灵活使用视口单位掌握绝对定位JavaScript 来操作 CSS 变量requestAnimationFrame 函数的使用无缝动画实现 页面结构 实现页面结构 通过上述的页面结构我们可以知道,此游戏中…...
Redis面试题(五)
文章目录 前言一、使用过 Redis 做异步队列么,你是怎么用的?有什么缺点?二、 什么是缓存穿透?如何避免?什么是缓存雪崩?何如避免?总结 前言 使用过 Redis 做异步队列么,你是怎么用的…...
组队竞赛(int溢出问题)
目录 一、题目 二、代码 (一)没有注意int溢出 (二)正确代码 1. long long sum0 2. #define int long long 3. 使用现成的sort函数 一、题目 二、代码 (一)没有注意int溢出 #include <iostream&g…...
Swift SwiftUI 隐藏键盘
如果仅支持 iOS 15 及更高版本,则可以通过聚焦和取消聚焦来激活和关闭文本字段的键盘。 在最简单的形式中,这是使用 FocusState 属性包装器和 focusable() 修饰符完成的-第一个存储一个布尔值,用于跟踪第二个当前是否被聚焦。 Code struct C…...
Python与数据分析--Pandas-1
目录 1.Pandas简介 2.Series的创建 1.通过数组列表来创建 2.通过传入标量创建 3.通过字典类型来创建 4.通过numpy来创建 3.Series的索引和应用 1. 通过index和values信息 2. 通过切片方法获取信息 4.DataFrame的创建 1.直接创建 2.矩阵方式创建 3.字典类型创建 5.…...
如何完美通过token获取用户信息(springboot)
1. 什么是Token? 身份验证令牌(Authentication Token):在身份验证过程中,“token” 可以表示一个包含用户身份信息的令牌。 例如 Token(JWT)是一种常见的身份验证令牌,它包含用户的…...
2023 “华为杯” 中国研究生数学建模竞赛(B题)深度剖析|数学建模完整代码+建模过程全解全析
华为杯数学建模B题 当大家面临着复杂的数学建模问题时,你是否曾经感到茫然无措?作为2021年美国大学生数学建模比赛的O奖得主,我为大家提供了一套优秀的解题思路,让你轻松应对各种难题。 让我们来看看研赛的B题呀~! 问…...
文件相关工具类
文章目录 1.MultipartFile文件转File2.读取文件(txt、json)3.下载网络文件4.压缩文件 1.MultipartFile文件转File public File transferToFile(MultipartFile multipartFile) { // 选择用缓冲区来实现这个转换即使用java 创建的临时文件 使用 MultipartFile.transferto()…...
18795-2012 茶叶标准样品制备技术条件
声明 本文是学习GB-T 18795-2012 茶叶标准样品制备技术条件. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了各类茶叶(除再加工茶)标准样品的制备、包装、标签、标识、证书和有效期。 本标准适用于各类茶叶(除再加工茶)感官品质…...
C++11互斥锁的使用
是C11标准库中用于多线程同步的库,提供互斥锁(mutex)及其相关函数。 以下是一些基本的使用示例: 1.创建和销毁互斥锁 #include <mutex>std::mutex mtx;2.加锁 std::lock_guard<std::mutex> lock(mtx); // 加锁 // 或者 mtx.lock(); //…...
unity 桌面程序
using System; using System.Collections; using System.Collections.Generic; using System.Runtime.InteropServices; using UnityEngine; public class chuantou : MonoBehaviour { [DllImport(“user32.dll”)] public static extern int MessageBox(IntPtr hwnd,string t…...
echarts统一纵坐标y轴的刻度线,刻度线对齐。
要求: 纵坐标刻度线对齐;刻度间隔为5;去掉千位默认的逗号;刻度最小是0. 效果图: 代码: yAxis: [{type: "value",position: "left",name: "kW",offset: 100,nameTextStyle:…...
一个数据库版本兼容问题
mysql旧的版本号是:5.3.10 本机版本号是:8.0.22 报错:“com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create” 1.程序里做兼容: <dependency><groupId>mysql</groupId>…...
【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...






