C语言字符串函数进阶:安全版函数 + 错误处理 + 子串查找
适用对象学过 strcpy / strcat / strcmp 的同学本章目标掌握安全版字符串函数 strstr 子串查找 strerror 错误处理引入strcpy 为什么会让人又爱又恨上一章我们学了strcpy它简单粗暴复制速度也快——但它有一个致命问题不检查目标空间是否够用。如果目标空间只有 5 字节但你拷贝了 20 字节的字符串会发生什么内存越界写入可能会把旁边的变量覆盖掉或者触发段错误Segmentation Fault。更可怕的是有时候程序不会马上崩而是在某个完全不相关的地方突然出问题——这种 Bug 极难定位。于是C 语言标准委员会给几大函数都设计了带数字版本strncpy/strncat/strncmp把拷贝/追加/比较的长度交给程序员控制——更安全但也更复杂。第一部分strncpy——安全拷贝 n 个字符1.1 函数原型char*strncpy(char*destination,constchar*source,size_tnum);第三个参数num最多拷贝num个字符。#includestdio.h#includestring.hintmain(){chararr1[20]{0};chararr2[]abcdefghi;strncpy(arr1,arr2,5);// 只拷贝前 5 个字符printf(%s\n,arr1);// 输出 abcdereturn0;}1.2 strncpy 的三个坑坑一源字符串不够 num 个字符时用\0填充chararr1[20]{0};chararr2[]hi;strncpy(arr1,arr2,10);// 源只有 2 个字符printf(%s\n,arr1);// 输出 hi后面的 8 个位置全部填 \0坑二源字符串够长时不保证在第 num 位置写\0chararr1[20]{0};chararr2[]hello;strncpy(arr1,arr2,3);// 只拷贝 3 个字符 helprintf(%s\n,arr1);// 输出 hel没有 \0arr1[3] 不是 \0⚠️提醒strncpy在源字符串长度 ≥ num 时不会自动补\0这是最容易踩的坑。如果你在后面调用printf(%s, arr1)它会继续往后读内存打印出一堆乱码。所以使用strncpy后务必手动确保目标字符串以\0结尾if(numdest_size)arr1[num]\0;1.3 strncpy vs strcpy怎么选对比strcpystrncpy安全性❌ 不检查边界✅ 可控拷贝长度何时用源字符串短小确定不确定源串长度时长度足够时的 \0一定会补不保证第二部分strncat——安全追加 n 个字符2.1 函数原型char*strncat(char*destination,constchar*source,size_tnum);追加最多num个字符但无论源多长都会追加\0这是它比strncpy更安全的地方。#includestdio.h#includestring.hintmain(){chararr1[20]hello ;chararr2[]world;strncat(arr1,arr2,3);// 只追加前 3 个字符worprintf(%s\n,arr1);// 输出 hello worreturn0;}2.2 strncat 的一个陷阱strncat追加到destination的\0位置开始所以destination本身必须以\0结尾。如果destination忘了初始化chararr1[20];// 未初始化里面是垃圾值strncat(arr1,hi,2);// 危险从哪里开始追加正确写法在使用strncat之前先确保destination有\0或者用arr1[0] \0清空。第三部分strncmp——安全比较 n 个字符3.1 函数原型intstrncmp(constchar*str1,constchar*str2,size_tnum);最多比较前num个字符返回规则同strcmp。#includestdio.h#includestring.hintmain(){chararr1[]abcdef;chararr2[]abcqw;intret1strncmp(arr1,arr2,3);// 只比较前3个abc abc → 0printf(%d\n,ret1);// 输出 0intret2strncmp(arr1,arr2,4);// 比较前4个d q → 负数printf(%d\n,ret2);// 输出负数return0;}3.2 典型应用比较字符串前缀// 判断字符串是否以 http:// 开头if(strncmp(url,http://,7)0)printf(这是 HTTP 链接\n);第四部分strstr——在字符串里找子串4.1 函数原型char*strstr(constchar*str1,constchar*str2);在str1里找str2第一次出现的位置。#includestdio.h#includestring.hintmain(){charstr[]This is a simple string;char*pchstrstr(str,simple);if(pch!NULL)printf(找到了%s\n,pch);// 输出 simple stringelseprintf(没找到\n);return0;}返回值找到则返回指向该位置的指针没找到返回NULL。4.2 手写 strstr暴力匹配核心思路双层循环外层遍历str1内层逐字符比较str1和str2。#includeassert.hchar*my_strstr(constchar*str1,constchar*str2){assert(str1!NULL);assert(str2!NULL);// 空字符串直接返回 str1标准行为if(*str2\0)return(char*)str1;constchar*s1str1;constchar*s2str2;while(*s1){// 记录当前位置constchar*curs1;// 逐字符比较while(*s1*s2*s1*s2){s1;s2;}// s2 遍历完了 → 匹配成功if(*s2\0)return(char*)cur;// 没匹配上重置 s2回到 cur 的下一个位置继续s1cur1;s2str2;}returnNULL;}第五部分strerror——把错误码翻译成人话5.1 什么是 errnoC 语言程序启动时系统会初始化一个全局变量errno定义在errno.h。当你调用标准库函数出错了函数会把对应的错误码写进errno。错误码是一个整数比如 2、5、11——直接看数字完全不知道什么意思。#includeerrno.h// 声明全局变量 errno5.2 strerror翻译错误码char*strerror(interrnum);把错误码翻译成人类可读的错误信息字符串。#includestdio.h#includestring.hintmain(){for(inti0;i10;i)printf(%d: %s\n,i,strerror(i));return0;}输出Windows VS20220: No error 1: Operation not permitted 2: No such file or directory 3: No such process 4: Interrupted function call 5: Input/output error 6: No such device or address 7: Arg list too long 8: Exec format error 9: Bad file descriptor 10: No child processes5.3 实战fopen 出错了怎么办#includestdio.h#includestring.h#includeerrno.hintmain(){FILE*pFilefopen(不存在的文件.txt,r);if(pFileNULL){printf(文件打开失败%s\n,strerror(errno));// 输出文件打开失败No such file or directoryreturn1;}// ... 正常读写文件 ...fclose(pFile);return0;}5.4 perror更简洁的写法perror是strerror的快捷版本直接把错误信息打印出来perror(文件打开失败);// 输出文件打开失败No such file or directory相当于下面这行printf(文件打开失败%s\n,strerror(errno));选哪个如果你需要打印错误用perror更简洁如果你需要存起来或者自定义前缀用strerror。第六部分经典面试题精讲面试题一strncpy 和 strcpy 的核心区别是什么strncpy 有什么坑答案strcpy以\0为结束标志拷贝整个源字符串strncpy以num为拷贝上限但有两个坑源不够长时用\0填充剩余位置有时候不是你想要的源够长时不自动补\0比strcpy更危险加分回答面试中如果能用上「源够 num 时不补\0」这个坑点面试官会觉得你理解得很深。建议使用strncpy后手动dest[num] \0收尾。面试题二strstr 返回值是什么类型的指针答案char*指向str1中首次匹配位置的指针。如果匹配失败返回NULL。charstr[]hello world;char*pstrstr(str,world);printf(%s\n,p);// worldprintf(%ld\n,p-str);// 6world 在第6个位置起进阶用法通过指针相减可以算出子串在原串中的位置。面试题三下面的代码会输出什么#includestdio.h#includestring.hintmain(){chars1[]hello;chars2[]world;charbuf[10];strncpy(buf,s1,10);strncat(buf,s2,3);printf(%s\n,buf);return0;}推演strncpy(buf, s1, 10)buf大小 10 字节s1只有 5 字符 \0所以全部拷贝再填充 4 个\0。bufhello\0\0\0\0\0strncat(buf, s2, 3)从buf的\0位置开始追加s2前 3 个字符wor。bufhellowor\0第二个\0被覆盖但后面还有 2 个\0printf(%s\n, buf)从buf[0]打印到\0输出hellowor答案hellowor本章总结安全版字符串函数函数额外参数与基础版的关键区别strncpysize_t num源够 num 时不补\0需手动处理strncatsize_t num追加 num 字符但一定会补\0strncmpsize_t num最多比较前 num 个字符strstr 用法速记找得到 → 返回指针指向匹配位置找不到 → 返回NULL指针相减 → 子串在原串中的位置错误处理速记函数用法特点errno全局变量记录最近一次错误码调用标准库函数后检查strerrorstrerror(errno)→ 字符串可存、可自定义perrorperror(提示)直接打印等价于printfstrerror

相关新闻

多模态LLM实战:从CLIP视觉编码到信息融合的Wiki技能构建

多模态LLM实战:从CLIP视觉编码到信息融合的Wiki技能构建

1. 项目概述:当大语言模型“睁开双眼”最近在折腾一个挺有意思的东西,我把它叫做“多模态 LLM Wiki Skill”。简单来说,就是给一个大型语言模型(LLM)——比如我们熟悉的 Claude 或者 GPT——装上“眼睛”和“耳朵”&am…

2026/10/17 23:52:27 阅读更多 →
android Handler , Looper , Message , MessageQueue 详解

android Handler , Looper , Message , MessageQueue 详解

一、基础Q1:请简述 Handler 机制的工作原理核心回答:Handler 发送消息 → MessageQueue 按时间排序存储 → Looper 无限循环取出 → 回调 Handler 处理。细节:MessageQueue 不是队列,是单向链表,按 when(触…

2026/10/15 14:33:19 阅读更多 →
Claude Code进阶指南:解锁Skills、Superpowers与Auto-mode,打造AI编程副驾驶

Claude Code进阶指南:解锁Skills、Superpowers与Auto-mode,打造AI编程副驾驶

1. 项目概述:从“能用”到“好用”的Claude Code进阶之路如果你已经成功在VSCode里装上了Claude Code,体验过它流畅的代码补全和对话,那么恭喜你,你已经迈出了第一步。但说实话,如果只是把它当成一个“更聪明的代码提示…

2026/10/18 8:30:40 阅读更多 →

最新新闻

C#股票量化实战:掘金行情接口封装与板块数据接入

C#股票量化实战:掘金行情接口封装与板块数据接入

简介:面向C#股票量化开发者的实战资源包,以掘金量化接口为主线,讲解如何获取股票行情与同花顺版块数据,并融入量化交易策略。内容从量化交易的概念与数学模型出发,系统梳理了通过HTTP调用掘金接口获取实时价格、历史K线…

2026/10/18 19:14:15 阅读更多 →
亿图图示 EdrawMax 6.8 绿色便携版部署避坑指南

亿图图示 EdrawMax 6.8 绿色便携版部署避坑指南

简介:亿图图示EdrawMax 6.8中文绿色便携版面向需要快速绘制专业图表的办公人群、学生与设计爱好者,免安装、不写注册表,可直接在U盘或移动硬盘运行,解决多设备切换时无法随时使用图形设计工具的问题。压缩包为rar格式,…

2026/10/18 19:14:15 阅读更多 →
深度强化学习双目标动态感知路径规划:毕设源码拆解与实战

深度强化学习双目标动态感知路径规划:毕设源码拆解与实战

简介:基于深度强化学习的双目标动态感知路径规划毕业设计源码,以Python实现,主要面向计算机、人工智能、自动化、物联网等专业的在校生、教师或研发人员,适用于毕业设计、课程设计、项目演示及深度学习入门进阶。项目聚焦动态环境…

2026/10/18 19:14:15 阅读更多 →
Agent项目落地全流程:从Demo到生产的工程化实务

Agent项目落地全流程:从Demo到生产的工程化实务

做Agent项目这几个月,我最大的感受是:Demo和落地是两回事。会议室里跑通一个“会调用工具、能自动回答问题”的原型只需要一下午,但真要把它放到生产环境里面对真实流量、真实数据、真实用户的奇怪输入,问题一个接一个地冒出来。工…

2026/10/18 19:14:15 阅读更多 →
基于深度学习的机械振动信号故障诊断:从数据生成到模型部署

基于深度学习的机械振动信号故障诊断:从数据生成到模型部署

简介:这份资源面向机械故障诊断方向的学习者与工程实践者,提供一套基于深度学习的完整项目源码,帮助理解如何用Python将振动、温度等传感器数据转化为可用的故障识别模型。包内共88个文件,以45个py源码与43个pyc编译文件为主&…

2026/10/18 19:14:15 阅读更多 →
OpenClaw智能体全流程部署:从环境配置到多Agent自动化实战

OpenClaw智能体全流程部署:从环境配置到多Agent自动化实战

说实话,我早就受够了在不同AI工具之间来回切换、复制粘贴、手工串联任务的繁琐日子。直到我把一个开源智能体框架OpenClaw完整部署下来,从环境准备、角色配置、工具接入到多流程联动跑通,才发现原来AI智能体全流程操作并没有想象中那么玄乎&a…

2026/10/18 19:13:14 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →