C语言char字符串与中文编码的坑

原    创先从C语言标准库string.h的strstr函数说起吧,函数原型大概是这样的:const char * strstr ( const char * str1, const char * str2 );这个函数的用途就是判断str2是不是str1的子串,如果是就返回第一次匹配成功的位置(指针),如果不是就返回NULL。very good,我迫不及待跃跃欲试了:[C] 纯文本查看 复制代码?01020304050607080910111213141516void subEstimate(const char* str, const char* sub) {const char* position = strstr(str, sub);if (position == NULL) {printf("\"%s\" is Not substring of \"%s\"!\n", sub, str);}else {printf("\"%s\" is substring of \"%s\" from \"%s\"\n", sub, str, position);}}int main() {char* str = "abc890xyz";char* sub = "890";subEstimate(str, sub);return 0;}Nice,输出结果符合预期:"890" is substring of "abc890xyz" from "890xyz"然而,生活在中国的我们,处理中文也是在所难免,我们常用的字符集有GB2312/GBK/GB18030。GB2312包含常用简体汉字、拉丁字母、希腊字母、日文假名。GBK在GB2312的基础上补充了不支持的简体字和繁体字,俄语字母等(非国标,等同于微软CP936字码表)。GB18030涵盖了中日韩/朝鲜和中国少数民族的文字。根据使用的不同开发环境,可选的字符集可能有所不同,例如我在VS环境下,默认的是GBK。下面我们来试试中文:[C] 纯文本查看 复制代码?12subEstimate("电子工程世界论坛EEWORLD", "电子");subEstimate("电子工程世界论坛EEWORLD", "庸");结果:"电子" is substring of "电子工程世界论坛EEWORLD" from "电子工程世界论坛EEWORLD""庸" is substring of "电子工程世界论坛EEWORLD" from "庸こ淌澜缏厶矱EWORLD"第一行工作的很好,而第二行就略显异常。问题分析:[C] 纯文本查看 复制代码?1234567void printHex(const char* s) {const unsigned char *t = (const unsigned char*)s;while (*t) {printf("%02X ", *t++);}putchar('\n');}[C] 纯文本查看 复制代码?12printf("下面一行是\"电子工程世界论坛EEWORLD\"的GBK编码:\n");printHex("电子工程世界论坛EEWORLD");结果:下面一行是"电子工程世界论坛EEWORLD"的GBK编码:B5 E7 D7 D3 B9 A4 B3 CC CA C0 BD E7 C2 DB CC B3 45 45 57 4F 52 4C 44“庸”的GBK编码是D3 B9,确实可以从第四个字节开始匹配,但是从中文字符上讲,这确是风马牛不相及的匹配,根本扯不上关系。这个问题的根源,就是编码的缺陷,以GB2312字符集为例,GB2312的第一个字节的取值范围是0xA1-0xF7,第二个字节的取值范围是0xA1-0xFE,因为这两个字节的取值范围在很大程度上重叠,所以前一个汉字的后一个字节和后一个汉字的前一个字节很大概率上就是另外一个汉字(GBK和GB18030的取值范围更广,问题面更大),因此在对待汉字的查找问题上,要多加留意。解决办法呢?方案1. 使用wchar_t类型以及wchar.h中的函数来操作中文字符串。[C] 纯文本查看 复制代码?12#include <wchar.h>const wchar_t * t = wcsstr(L"电子工程世界论坛EEWORLD", L"庸");方案2. 换用Unicode编码,如UTF-8,UTF-8编码不存在这个问题,UTF-8的第一个字节和后续字节不存在重叠,不会出现从中间匹配的现象。Unicode编码是更通用更安全的编码 ,不过在单片机编程领域,GB2312用的好像更多,所以这个方案可行性小。方案3. 自己手动撸码进行各种操作也是可行的。字符串处理一直是编程中最常见的操作,尤其在软件领域,对待字符串要严谨严肃,否则稍不注意就会被人利用漏洞,进行各种攻击。历史上很多软件、操作系统的漏洞就是由字符集问题引发的,比如PHP曾经就出现过一次安全漏洞,在对字符串进行转义的时候未考虑字符编码问题,直接在引号,反斜杠之类的字符前加反斜杠字符,但假如用户输入的字符中包含0xD5,0x27序列,0x27是单引号,在它前面插入0x5C(反斜杠),而D5 5C组成了一个合法的中文字符,这样反斜杠就被吃掉了,后面的内容没有达到转义的效果,就会被用于SQL注入之类的攻击。当然,在我大单片机上编程很少遇到字符串处理上的问题,但稍微了解一下也不是坏事。EEWORLD论坛干货频道全新上线,自荐、推荐干货文章芯币翻倍赚!

(0)

相关推荐

  • Qt跨平台编程之中文编码问题

    前言 在使用 Qt5 进行开发的过程中遇到了一些跨平台的中文编码转换问题,然后进行了一番调查,这里做个总结,希望能帮上他人 字符编码 首先我们认识一下 UNICODE, UNICODE 是由微软等多个 ...

  • 【C语言更新】C语言中字符串的操作

    文/Edward 在C语言的实际使用中,很多时候会去使用指针传递一些字符串,而C语言中也有很多关于字符串处理的库函数给大家来使用,只要在使用的时候包含头文件"string.h"就可 ...

  • C语言如何使用断言避免踩坑

    何为断言 断言一般是用于检测在某个程序位置程序必须满足某些条件的宏.一般用的多的可以分两种种情况: 前置条件:在某个程度点开始的地方 后置条件:在某段程序执行结束后,一般用于检测执行结果 断言发生表示 ...

  • Spring Boot Security 国际化 多语言 i18n 趟过巨坑

    网上很多的spring boot国际化的文章都是正常情况下的使用方法 如果你像我一样用了Spring Security 那么在多语言的时候可能就会遇到一个深渊 Spring Security里面的异常 ...

  • C语言模拟实现字符串操作函数

    链接:https://blog.csdn.net/qq_34021920/article/details/76098237 前言 在编写程序过程中,我们经常使用到一些字符串函数,例如求字符串长度,拷贝 ...

  • (1条消息) 漫画:各语言如何优雅的判断回文字符串(必会)

    今天是小浩算法 "365刷题计划"- 储备日.难顶,我本来今天在写最长回文子串这个题目.然后我突然在想,直接讲这个会不会仍然有同学看不懂,为什么不从最简单的讲起呢.于是,今天的文章 ...

  • R语言Warning踩坑记之人鼠混合样本基因线粒体百分比计算

    前言:之前参加过几个生信培训班也听了一些视频,好几个老师们都是说R语言里面warning不用管,error才重要,我一直牢记于心.Warning从来不看.下面开始正文. 1 首先读入数据,并查看前几行 ...

  • shell字符串单双引号的坑

    入门生信时,我最接触的编程语言是python和R,最后才是shell.学习shell时,我也只是草草了事,没有仔细对比三种编程语言间的差别和特点,自认为很聪明的把python和R的相关基础知识直接迁移 ...

  • C语言将4个16进制char字符合并成一个int数

    串口接收只能按照char字符发送 所以需要拆分数据,下面代码为串口接收到的字符还原为int类型数字(int为32位) int rev_data(int a,int b,int c,int d) {  ...

  • 避坑!导致儿童语言发育迟缓的八大因素!

    作者 / 李鲁萍 编辑 / 嗨脑仁 前几期的内容,李老师已经给大家介绍了关于儿童语言发育的整个发展过程.那么现在我们就可以开始思考: 究竟是什么原因导致了儿童语言发育的迟缓? 导致儿童语言发育迟缓的七 ...