:前言

造车轮的时候要用到中文字符串的长度辨别,发现char的识别不准,进行了一番研究。


> 开始研究

在Windows下,中文字符在C++中的内存占用为2字节,此时采用字符串长度获取函数得到的结果会将一个中文字符识别为两个长度:

#include <stdio.h>
#include <string>
using namespace std;//string在std命名空间中 int main()
{
string str = "abc中文def";
printf("字符串为:%s\n", str.data());//data()函数回传字符串的指针,与c_str()相同 int len;
char str1[50]; strcpy(str1, str.data());//赋值 len = strlen(str1);
printf("字符串的长度为(%d)\n", len);
//使用strlen函数获取长度 string str2 = str;//也可以用string str2.assign(str),这是string的赋值函数,不过和=没区别
len = str2.length();//也可以用len = str2.size();
printf("字符串的长度为(%d)\n", len);
//使用string类的长度获取函数length() system("pause");
}
点击查看输出
字符串为:abc中文def
字符串的长度为(10)
字符串的长度为(10)
请按任意键继续. . .

而实际上,字符串的长度为8,并非上述方法的结果10。那么,如何获取真正的长度呢?

>> 上手尝试

其实,我们不妨试试中文字符的值:

char a = '中';
char b = '文';
char c = '字';
char d = '符';
printf("字符‘中’在编码中的值为%d\n",(int)a);
printf("字符‘文’在编码中的值为%d\n",(int)b);
printf("字符‘字’在编码中的值为%d\n",(int)c);
printf("字符‘符’在编码中的值为%d\n",(int)d);
system("pause");
点击查看输出
字符‘中’在编码中的值为-48
字符‘文’在编码中的值为-60
字符‘字’在编码中的值为-42
字符‘符’在编码中的值为-5
请按任意键继续. . .

试试其他中文字符,也都是负数。

>> 总结归纳

依据这一点,我们便可以做出一个获取含有中文的字符串长度的函数:

string版:

int getLength_str(string str)
{
int count = 0;
for (int i = 0; str[i]; i++)
{
if (str[i] < 0) i++;
//负数说明该字符为中文字符,占用两个字节,跳过后一个字节(i++),不进行统计
count++;
}
return count;
}

char版: 虽然char数组也可以传入上面的函数,不过为了避免某些奇葩编译器,还是再写了一个函数,即拷即用:

int getLength_char(char str[])
{
int count = 0;
for (int i = 0; str[i]; i++)
{
if (str[i] < 0) i++;
count++;
}
return count;
}

不过,char版不可以传string。

>> 试验验证

用前面的示例验证:

点击查看代码
#include <stdio.h>
#include <string>
using namespace std; int getLength_str(string str)
{
int count = 0;
for (int i = 0; str[i]; i++)
{
if (str[i] < 0) i++;
//负数说明该字符为中文字符,占用两个字节,跳过后一个字节(i++),不进行统计
count++;
}
return count;
} int getLength_char(char str[])
{
int count = 0;
for (int i = 0; str[i]; i++)
{
if (str[i] < 0) i++;
count++;
}
return count;
} int main()
{
string str = "abc中文def";
printf("字符串为:%s\n", str.data());//data()函数回传字符串的指针,与c_str()相同 int len;
char str1[50]; strcpy(str1, str.data());//赋值 len = strlen(str1);
printf("字符串的长度为(%d)\n", len);
//使用strlen函数获取长度 len = getLength_char(str1);//len = getLength_str(str1);
printf("字符串的长度为[%d]\n", len);
//用上面的函数获取含有中文字符的字符串的真正长度 string str2 = str;//也可以用string str2.assign(str),这是string的赋值函数,不过和=没区别
len = str2.length();//也可以用len = str2.size();
printf("字符串的长度为(%d)\n", len);
//使用string类的长度获取函数length() len = getLength_str(str2);
printf("字符串的长度为[%d]\n", len);
//用上面的函数获取含有中文字符的字符串的真正长度 system("pause");
}
点击查看输出
字符串为:abc中文def
字符串的长度为(10)
字符串的长度为[8]
字符串的长度为(10)
字符串的长度为[8]
请按任意键继续. . .

这个函数也可以获取没有中文字符的字符串长度.


总结

通过对中文字符数值的输出,从而找到char数组对中文字符串的长度处理解决方法。

当然处理中文字符串最好的方法是转换成宽字节,但会比较麻烦。

另外,新版的C++20string好像已经解决了这个长度问题。这篇文是之前在CSDN写的,当时是不可以的。

另:

字符串转宽字节后,采用wcslen(wchar_t*)方法可以准确的读出宽字节字符串的字符数(毕竟宽字节就是为了这事专门设计的)



The End

Yuito 2023

C++获取含有中文字符的string长度的更多相关文章

  1. Tomcat 中get请求中含有中文字符时乱码的处理

    Tomcat 中get请求中含有中文字符时乱码的处理

  2. jQuery判断字符串是否含有中文字符

    //判断字符串是不是中文String.prototype.isChinese = function () {    var reg = /[^\x00-\xff]/ig;//判断是否存在中文和全角字符 ...

  3. CP策略含有中文字符提交失败故障解决

    硬件平台:CP5600 系统版本:R80.10 补丁版本:TAKE103 故障现象:提交新增策略失败,日志显示 if the problem persists contact Checkpoint S ...

  4. perl处理含有中文字符的json编码

    例子:1. 有php的 json函数生成的中文串 [root@tts177:/tmp]$/opt/php/bin/php -r 'echo json_encode(Array("a" ...

  5. Servlet & JSP - 中文字符问题

    Servlet 中的中文字符 来自 URL 参数部分的中文字符 Tomcat 默认接收数据的编码是 ISO-8859-1.所以当请求 URL 的参数部分含有中文字符,需要转换字符的编码. Enumer ...

  6. SpringMVC项目中中文字符乱码问题及解决办法总结(非专业最优解决办法) -- ajax传值乱码; request.getParameter()乱码;

    情况一: ajax中传值时是乱码(后台可以获取到中文字符,但用@ResponseBody返回时前台为乱码) 情况二: Controller 中 request.getParameter()获取到的是乱 ...

  7. [python]有中文字符程序异常的解决方案

    一. 含有中文字符无法运行 在python3中用的是Unicode编码,Unicode号称万国码,可以向所有的编码进行兼容.不会出现这种问题. Python2中使用的是ASCII编码,会出现这种问题. ...

  8. 转义URL 含有中文和特殊符号

    方法1: //这个方法被废弃了 NSString *urlString = @"https://www.cnblogs.com/huaida/#/程序员"; NSString* e ...

  9. java String长度与varchar长度匹配理解(字符和字节长度理解)

    java String长度与varchar长度匹配理解(字符和字节长度理解) string中的length()长度,返回的是char的数量,每个char可以存储世界上任何类型的文字和字符,一个char ...

  10. URL query string中文字符问题

    如果URL的query string中包含中文字符,在不做特殊处理的情况下通过 request.getParameter 方法是获取不到正确的信息的,这是由于下面的两个机制造成的 浏览器会自动对URL ...

随机推荐

  1. 《Java并发编程的艺术》读书笔记:二、Java并发机制的底层实现原理

    二.Java并发机制底层实现原理 这里是我的<Java并发编程的艺术>读书笔记的第二篇,对前文有兴趣的朋友可以去这里看第一篇:一.并发编程的目的与挑战 有兴趣讨论的朋友可以给我留言! 1. ...

  2. AR人体姿态识别,实现无边界的人机交互

    近年来,AR不断发展,作为一种增强现实技术,给用户带来了虚拟和现实世界的融合体验.但用户已经不满足于单纯地将某件虚拟物品放在现实场景中来感受AR技术,更想用身体姿势来触发某个指令,达到更具真实感的人机 ...

  3. .NET中的拦截器filter的使用

    拦截器的使用 使用场景分析 我们先想像一个场景,就是程序员开发软件,他是怎么工作的呢?我们都知道,普通的程序员只需要根据需求文档开发相应的功能即可,他不用和客户谈论软件需求,不用理会软件卖多少钱,他要 ...

  4. etcd定时任务脚本执行失败

    etcd定时任务脚本执行失败 报错如下:etcdctl命令不存在 是因为在脚本中etcdctl命令没有写绝对路径,修改标记部分改成绝对路径 可以先获取路径然后改成绝对路径问题解决 which etcd ...

  5. .NET 7 中 LINQ 的疯狂性能提升

    LINQ 是 Language INtegrated Query 单词的首字母缩写,翻译过来是语言集成查询.它为查询跨各种数据源和格式的数据提供了一致的模型,所以叫集成查询.由于这种查询并没有制造新的 ...

  6. MYSQL ---mysql 数据导入与导出

    1.使用SQLyog导出MySQL中的数据库 打开SQLyog → 右击你想要保存的数据库 → 选择"Backup/Export"→ 选择"Backup Database ...

  7. Linux环境下执行脚本重启Weblogic控制台中部署的应用程序

    之前有写过一篇博文介绍切换登录方式的脚本,脚本中存在一个缺点:仍需手动去Weblogic控制台重启应用程序:本文即介绍如何在脚本中更新Weblogic控制台中部署的应用程序. 一.配置Weblogic ...

  8. linux mint 归档管理器报错Extraction not performd

    解决办法 后缀名的问题,后缀名与文件的真正类型不符合,至于到底是上面压缩类型,那只能靠尝试了,比如我这个是rar, 实际是zip,很坑,网上也没有这个问题的描述 其他 感觉 linux 对于文件类型方 ...

  9. ArcObjects SDK开发 008 从mxd地图文件说起

    1.Mxd文件介绍 ArcGIS的地图文件为.mxd扩展名.Mxd文件的是有版本的,和ArcGIS的版本对应.可以在ArcMap中的File-Save A Copy,保存一个地图拷贝的时候选择Mxd文 ...

  10. MISC相关刷题记录迁移