发布时间:2026/8/14 2:20:18
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

相关新闻

2026/8/14 2:20:18

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

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

2026/8/14 2:20:18

android Handler , Looper , Message , MessageQueue 详解

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

2026/8/14 4:45:26

java知识点自理1

一、开发环境与程序结构 JDK / JRE / JVM 关系:JDK ⊃ JRE ⊃ JVM(JDK JRE 开发工具,JRE JVM 核心类库)。 环境变量:需配置 JAVA_HOME(指向JDK安装目录)并添加到 Path(%JAVA_HOM…

2026/8/14 4:45:26

天津整车包车物流价格全解析

不少天津的发货人第一次问整车包车物流,开口就是“多少钱”。报低了怕服务打折扣,报高了又担心被多收,这种纠结很真实。整车包车运费不是一个固定数字,它像打车,距离远近、车型大小、货物特殊性,甚至装卸难…

2026/8/14 4:45:26

餐厅网站建设方案全解析:如何打造高转化率的本地美食在线入口

在这个手机不离手、外卖刷不停的年代,如果你还觉得拥有一个网页只是为了“展示存在”,那真的是太小看现代餐饮营销的威力了。很多开店的老板跟我聊天时,第一反应往往是:“我有大众点评,有小红书,有抖音,还要那个什么网站干什么?”这个问题非常实在,也很典型。但我想诚…

2026/8/14 4:27:24

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

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

2026/8/14 4:27:24

当 LLM 遇见大文档:主流开源项目如何处理上下文超限

从 Agentic Loop 到 Repo Map,七种策略与六类陷阱引言:128K vs 10MB 的硬冲突 2026 年的 LLM 上下文窗口已达到 128K ~ 1M token(≈ 0.5MB ~ 4MB 文本),但 LLM 想要处理的真实数据规模远远超过这个量级:真实…

2026/8/14 0:00:09

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

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

2026/8/14 0:00:09

VSCode高效Git管理:从入门到实战技巧

1. 为什么选择VSCode进行Git代码管理作为微软推出的轻量级代码编辑器,Visual Studio Code(简称VSCode)已经成为全球开发者使用率最高的编辑器之一。根据2023年Stack Overflow开发者调查,VSCode的市场占有率高达74.48%。它内置的Gi…

2026/8/14 4:27:24

实测才敢推 AI论文网站 2026最新测评与推荐

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。一、综…

2026/8/14 4:27:24

2026必备!AI论文网站测评:最新推荐与深度对比

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

2026/8/14 4:27:24

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…