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/8/14 2:20:15 阅读更多 →
android Handler , Looper , Message , MessageQueue 详解

android Handler , Looper , Message , MessageQueue 详解

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

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

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

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

2026/8/14 2:20:15 阅读更多 →

最新新闻

零基础AI漫剧制作:从脚本到视频发布的完整流程指南

零基础AI漫剧制作:从脚本到视频发布的完整流程指南

这次我们来看一个面向零基础用户的“学渣级教程漫剧教程”,它把从脚本创作到视频发布的完整流程拆解成了可执行的步骤。如果你一直想尝试制作自己的漫剧、动画解说或图文视频,但被复杂的工具链和专业技能门槛劝退,这个教程或许能帮你快速上手…

2026/8/14 3:16:41 阅读更多 →
Grok图像模型拓扑理解力解析:从场景图构建到关系推理实战

Grok图像模型拓扑理解力解析:从场景图构建到关系推理实战

在计算机视觉和人工智能领域,理解图像中物体的空间关系一直是一个核心挑战。最近,一项关于“Grok 图像模型拓扑理解力”的研究引起了广泛关注,其结果表明,在某些衡量空间关系的任务上,该模型的表现超越了现有的一些主流…

2026/8/14 3:16:41 阅读更多 →
React 19组件通信实战:从父子到深层嵌套,构建现代化Todo List应用

React 19组件通信实战:从父子到深层嵌套,构建现代化Todo List应用

1. 项目概述:为什么 Todo List 是 React 学习的“圣杯”?如果你正在学习 React,或者想通过一个项目来检验自己对 React 19 新特性的掌握程度,那么从零搭建一个 Todo List 应用,绝对是一个经典且高效的选择。这听起来可…

2026/8/14 3:16:41 阅读更多 →
VTJ分片渲染:React树形大数据高性能页面管理方案

VTJ分片渲染:React树形大数据高性能页面管理方案

1. 项目概述:从“页面管理”到“VTJ”的深度解构最近在重构一个中后台项目的页面管理模块,团队内部给它起了个代号叫“VTJ”。这名字听起来有点玄乎,其实核心就一件事:如何高效、优雅地管理一个包含成百上千个节点的复杂页面树&am…

2026/8/14 3:16:41 阅读更多 →
从零编写油猴脚本:定制微信读书网页版阅读体验

从零编写油猴脚本:定制微信读书网页版阅读体验

1. 项目缘起:一个阅读者的朴素需求作为一名重度阅读爱好者,我几乎每天都会花上几个小时泡在微信读书里。它的网页版是我在电脑前工作学习时的主要阅读工具,毕竟大屏幕看起来更舒服,查资料、做笔记也更方便。但用久了,一…

2026/8/14 3:16:41 阅读更多 →
深入解析Assimp模型加载:从aiMesh到OpenGL渲染的完整解码流程

深入解析Assimp模型加载:从aiMesh到OpenGL渲染的完整解码流程

1. 项目概述:从“黑盒”到“白盒”的模型加载之旅在三维图形编程的世界里,OpenGL是一个强大的绘图API,但它本身并不负责理解复杂的3D模型文件格式。我们经常看到很多教程和示例,使用Assimp库加载一个.obj或.fbx文件,然…

2026/8/14 3:15:41 阅读更多 →

日新闻

临沂网站建设铭镇:深耕本土数字生态,以匠心铸就企业品牌核心竞争力

临沂网站建设铭镇:深耕本土数字生态,以匠心铸就企业品牌核心竞争力

在这个流量为王、视觉至上的互联网时代,对于临沂乃至整个山东乃至全国的传统中小企业来说,拥有一张精美的“数字名片”早已不再是可选项,而是生存的必答题。每当夜幕降临,沂河两岸灯火辉煌,物流之都的喧嚣逐渐沉淀为对未来的思考。我们常常听到老板们在茶余饭后探讨:为什…

2026/8/14 0:00:26 阅读更多 →
Flutter与OpenHarmony实现剧本杀组队表单开发实战

Flutter与OpenHarmony实现剧本杀组队表单开发实战

1. 项目概述在移动应用开发领域,跨平台框架Flutter因其高效的开发体验和出色的性能表现,已经成为众多开发者的首选。而OpenHarmony作为新兴的操作系统平台,其开放性和灵活性为开发者提供了全新的可能性。本文将聚焦于一个实际应用场景——剧本…

2026/8/14 0:00:26 阅读更多 →
大连网站建设找简维科技:为您打造懂业务更懂用户的数字化转型引擎

大连网站建设找简维科技:为您打造懂业务更懂用户的数字化转型引擎

在这个数字化浪潮席卷全球的今天,企业想要在激烈的市场竞争中站稳脚跟,拥有一张好看的“数字名片”已经远远不够了。很多老板在刚开始接触互联网业务时,都有一个共同的困惑:为什么我花了钱建的网站,就像是在真空中自嗨?访客进来转了两圈就跑了,线索石沉大海,甚至连客服…

2026/8/14 0:01:27 阅读更多 →

周新闻

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁 【免费下载链接】baidupankey 在线查询网盘提取码(维护中 rm repo) 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 你是否曾经在深夜寻找一份重要资料&#x…

2026/8/13 2:38:34 阅读更多 →
如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南 【免费下载链接】chinese_license_plate_generator 中国车牌生成器 项目地址: https://gitcode.com/gh_mirrors/ch/chinese_license_plate_generator 中国车牌生成器是一个基于Python的开源项目&#xff0c…

2026/8/13 10:41:52 阅读更多 →
收藏!小白程序员轻松入门大模型,从Harness工程开始实践

收藏!小白程序员轻松入门大模型,从Harness工程开始实践

文章强调学习大模型不应只关注模型本身,而应重视模型外的系统搭建,即Harness。提出AgentModelHarness的实用公式,详细介绍Harness的四个层次:持久化层、执行层、控制层和观察与验证层。文章还探讨了上下文工程、工具设计、AGENTS.…

2026/8/13 10:41:51 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/13 10:41:50 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/13 10:41:49 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/13 10:41:49 阅读更多 →