C 语言网络编程避坑指南:一个“隐身”回车符引发的 Bug 与 strcspn 的神级救场
C 语言网络编程避坑指南一个“隐身”回车符引发的 Bug 与 strcspn 的神级救场案发现场为什么我的程序“停不下来”今天在写 Linux 系统的 UDP 客户端代码时遇到了一个极其诡异的 Bug。程序的逻辑非常简单使用fgets从终端读取用户输入发送给服务端。如果用户输入了end程序就break跳出循环并结束。我原本是这样处理输入字符串的// 读取用户输入fgets(buff,sizeof(buff),stdin);// 砍掉末尾的回车符坑就在这里buff[strlen(buff)-1]\0;// 判断是否输入了 endif(strcmp(buff,end)0){break;// 诡异的是程序死活运行不到这里}逻辑看起来无懈可击对吧fgets会把输入时的换行符也读进去所以我用strlen(buff)-1精准定位到了最后一个字符把它替换成字符串结束符\0。可是当我自信满满地在终端敲下end并按下回车时程序毫无反应依然在死循环里等待下一次输入。抓鬼过程跨平台的“幽灵字符”\r经过一番排查我发现罪魁祸首竟然是操作系统的换行符差异如果你平时是用 Windows 系统的终端或者通过 VS Code 等工具远程连接 Linux当你按下回车键时系统实际上发送了两个隐藏字符\r回车Carriage Return回到行首。\n换行Line Feed换到下一行。也就是说当我以为我只输入了end\n时由于环境的影响底层的输入缓冲区里其实装的是end\r\n。这个时候再回头看我那句自以为聪明的“砍树”代码buff[strlen(buff)-1] \0;它非常精准地把最后一个字符\n给砍掉了。但是那个隐身的\r却成了漏网之鱼砍完之后buff里的内容变成了end\r。接着拿着end\r去和end做strcmp字符串比对C 语言死板的对比机制立刻判定两者不相等程序自然也就无法结束了。神级救场优雅且健壮的strcspn既然我们无法预知代码运行的环境到底是只给\n还是会给\r\n有没有一种通杀的解决办法答案就是 C 标准库string.h中的这个宝藏函数strcspn。只要把原来那行代码替换成这样buff[strcspn(buff,\r\n)]\0;Bug 瞬间荡然无存这行代码为什么神自动检索它会从左到右扫描buff一旦发现\r或者\n中的任意一个就会立刻停下并返回这个字符所在的索引位置。精准替换外层的buff[...] \0刚好把找到的这个换行符替换成了结束符。极致安全就算你的字符串里原本就没有任何换行符比如就是一个纯净的endstrcspn会扫描到末尾返回\0的索引相当于把\0替换成\0什么也不会破坏。完全避免了用strlen-1时可能误砍掉有效字符的风险。总结在 C/C 开发中处理文本协议或终端输入时永远要在脑子里留一根弦看不见的控制字符可能会随时背刺你。放弃strlen(buff)-1这种硬编码的截断方式吧用strcspn让你的代码无论在 Windows 还是 Linux 下都能做到真正的“金刚不坏”。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2410525.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!