:前言

造车轮的时候要用到中文字符串的长度辨别,发现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. 齐博x1如何取消禁止跨城市密码登录限制

    为安全起意见,只要用户绑定了手机,或者QQ登录,或者微信登录其中的一项,只要用户的IP所在城市变了,就会禁止密码登录.如下图所示 而必须选择绑定过的手机或QQ或微信其中一种方式登录.以避免密码被盗所带 ...

  2. C语言表白窗口程序

    #include<windows.h> #include<stdio.h> #include<string.h> int main() { char modeCom ...

  3. 词云(WordCloud)

    WordCloud的参数: font_path:可用于指定字体路径 width:词云的宽度,默认为 400: height:词云的⾼度,默认为 200: mask:蒙版,可⽤于定制词云的形状: min ...

  4. Ubuntu安装Docker及镜像加速器

    一.安装Docker sudo apt-get update && sudo apt-get install -y apt-transport-https ca-certificate ...

  5. JUC学习笔记——进程与线程

    JUC学习笔记--进程与线程 在本系列内容中我们会对JUC做一个系统的学习,本片将会介绍JUC的进程与线程部分 我们会分为以下几部分进行介绍: 进程与线程 并发与并行 同步与异步 线程详解 进程与线程 ...

  6. 你认识的C# foreach语法糖,真的是全部吗?

    本文的知识点其实由golang知名的for循环陷阱发散而来, 对应到我的主力语言C#, 其实牵涉到闭包.foreach.为了便于理解,我重新组织了语言,以倒叙结构行文. 先给大家提炼出一个C#题:观察 ...

  7. elasticsearch bucket 之rare terms聚合

    目录 1.背景 2.需求 3.前置准备 3.1 准备mapping 3.2 准备数据 4.实现需求 4.1 dsl 4.2 java代码 4.3 运行结果 5.max_doc_count 和 sear ...

  8. 快速构建一个简单的Springboot-web项目

    web项目基本的核心成分 数据落地 MYSQL数据库 登录标识 JWT :{Java web token } 记录有效登录状态 以及缓存常用数据: Redis 数据库与JAVA实体的快速自动映射ORM ...

  9. 微信小程序根据开发环境切换域名

     domain.js // 获取当前账号信息,线上小程序版本号仅支持在正式版小程序中获取,开发版和体验版中无法获取. // envVersion:'develop','trial','release' ...

  10. typora实现多平台发布文章

    源码下载 前言 之前写过一片文章,typora 使用CSDN作为图床,用来存储 markdown 文章的图片资源文件.后来发现 typora 还可以自定义导出命令,那么也可以利用这个功能实现直接发布到 ...