C++获取含有中文字符的string长度
:前言
造车轮的时候要用到中文字符串的长度辨别,发现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长度的更多相关文章
- Tomcat 中get请求中含有中文字符时乱码的处理
Tomcat 中get请求中含有中文字符时乱码的处理
- jQuery判断字符串是否含有中文字符
//判断字符串是不是中文String.prototype.isChinese = function () { var reg = /[^\x00-\xff]/ig;//判断是否存在中文和全角字符 ...
- CP策略含有中文字符提交失败故障解决
硬件平台:CP5600 系统版本:R80.10 补丁版本:TAKE103 故障现象:提交新增策略失败,日志显示 if the problem persists contact Checkpoint S ...
- perl处理含有中文字符的json编码
例子:1. 有php的 json函数生成的中文串 [root@tts177:/tmp]$/opt/php/bin/php -r 'echo json_encode(Array("a" ...
- Servlet & JSP - 中文字符问题
Servlet 中的中文字符 来自 URL 参数部分的中文字符 Tomcat 默认接收数据的编码是 ISO-8859-1.所以当请求 URL 的参数部分含有中文字符,需要转换字符的编码. Enumer ...
- SpringMVC项目中中文字符乱码问题及解决办法总结(非专业最优解决办法) -- ajax传值乱码; request.getParameter()乱码;
情况一: ajax中传值时是乱码(后台可以获取到中文字符,但用@ResponseBody返回时前台为乱码) 情况二: Controller 中 request.getParameter()获取到的是乱 ...
- [python]有中文字符程序异常的解决方案
一. 含有中文字符无法运行 在python3中用的是Unicode编码,Unicode号称万国码,可以向所有的编码进行兼容.不会出现这种问题. Python2中使用的是ASCII编码,会出现这种问题. ...
- 转义URL 含有中文和特殊符号
方法1: //这个方法被废弃了 NSString *urlString = @"https://www.cnblogs.com/huaida/#/程序员"; NSString* e ...
- java String长度与varchar长度匹配理解(字符和字节长度理解)
java String长度与varchar长度匹配理解(字符和字节长度理解) string中的length()长度,返回的是char的数量,每个char可以存储世界上任何类型的文字和字符,一个char ...
- URL query string中文字符问题
如果URL的query string中包含中文字符,在不做特殊处理的情况下通过 request.getParameter 方法是获取不到正确的信息的,这是由于下面的两个机制造成的 浏览器会自动对URL ...
随机推荐
- 齐博x1标签实例:标签如何调用论坛内容
论坛的内容不像CMS其它模块可以直接用变量 {$rs.content} 因为论坛的内容数据表是放在另一个表的,单独分开的. 当前也是为了考试效率问题而这样设计的. 所以他的调用要用下面的代码 {:fu ...
- 10.APIView视图
from rest_framework import status from rest_framework.response import Response from snippets.models ...
- golang中的锁竞争问题
索引:https://www.waterflow.link/articles/1666884810643 当我们打印错误的时候使用锁可能会带来意想不到的结果. 我们看下面的例子: package ma ...
- java简易两数计算器
public class calculator { public static void main(String[] args) { Scanner scanner = new Scanner(Sys ...
- Oracle中查询表结构的六种方法
首发微信公众号:SQL数据库运维 原文链接:https://mp.weixin.qq.com/s?__biz=MzI1NTQyNzg3MQ==&mid=2247485212&idx=1 ...
- JVM学习笔记——垃圾回收篇
JVM学习笔记--垃圾回收篇 在本系列内容中我们会对JVM做一个系统的学习,本片将会介绍JVM的垃圾回收部分 我们会分为以下几部分进行介绍: 判断垃圾回收对象 垃圾回收算法 分代垃圾回收 垃圾回收器 ...
- 小巧快速的ZooKeeper可视化管理+实时监控工具
Zookeeper: 是一个分布式的.开源的程序协调服务,是 hadoop 项目下的一个子项目.他提供的主要功 能包括:配置管理.名字服务.分布式锁.集群管理. 平时用zkCli.sh进行管理不免有点 ...
- perl使用print输入数据到文件
#!usr/bin/perl use utf8; #引入utf8模块 脚本内的字符串使用utf8作为编码格式 binmode(STDOUT,":encoding(gbk)"); # ...
- Linux Polkit本地权限提升漏洞(CVE-2021-4034)
Linux Polkit本地权限提升漏洞(CVE-2021-4034) 免责声明: 漏洞描述 影响范围 漏洞检测 漏洞复现 修复建议 免责声明: 发现这个漏洞被各大预警平台刷屏了,目前主流Linux系 ...
- Pinely Round 1 (Div. 1 + Div. 2)
比赛链接 A 题意 构造两个长为 \(n\) 排列,使得两排列有长为 \(a\) 公共前缀和长为 \(b\) 的公共后缀. 题解 知识点:构造. 注意到,当 \(a+b\leq n-2\) 时,中间段 ...