C++ 获取UTF-8字符串中的字符个数以及将字符串中的字符全部提取出来再以字符为单位保存在向量中

1. 概要:

  • 在实际的工程开发中,有时候需要统计utf8字符串中字符的个数,单纯统计字节个数是不行的,因为一个字符有时候所占的空间不止一个字节,比如UTF-8编码方案中:一个英文字符占1个字节,一个中文字符占三个字节(在其他编码方案中一个中文字符可能占两个字节)。
  • 在本文的实战演练板块,提供了获取UTF-8字符串中的字符个数以及将字符串中的字符全部提取出来再以字符为单位保存在向量中的实战代码。
  • 详情点击:https://blog.csdn.net/COCO56/article/details/91457885

2. 源码

static int GetUtf8LetterNumber(const char *s)
{
    int i = 0, j = 0;
    while (s[i])
    {
    	//if ((s[i] & 0b11000000) != 0b10000000) j++;
        if ((s[i] & 0xc0) != 0x80) j++;
        i++;
    }
    return j;
}

3. 说明

0xC0=0b11000000
0x80=0b10000000
& 代表 按位逻辑与
UTF-8编码规则:如果只有一个字节则其最高二进制位为0;如果是多字节,其第一个字节从最高位开始,连续的二进制位值为1的个数决定了其编码的字节数,其余各字节均以10开头。UTF-8转换表表示如下:

Unicode/UCS-4bit数UTF-8byte数备注
0000~007F0~70XXX XXXX1
0080~07FF8~11110X XXXX
10XX XXXX
2
0800~FFFF12~161110 XXXX
10XX XXXX
10XX XXXX
3基本定义范围:0~FFFF
1 0000~1F FFFF17~211111 0XXX
10XX XXXX
10XX XXXX
10XX XXXX
4Unicode6.1定义范围:0~10 FFFF
20 0000~3FF FFFF22~261111 10XX
10XX XXXX
10XX XXXX
10XX XXXX
10XX XXXX
5
400 0000~7FFF FFFF27~311111 110X
10XX XXXX
10XX XXXX
10XX XXXX
10XX XXXX
10XX XXXX
6

注:5个字节和6个字节的非unicode编码范围,属于UCS-4 编码早期的规范UTF-8可以到达6字节序列,可以覆盖到31位元(通用字符集原来的极限)。尽管如此,2003年11月UTF-8 被 RFC 3629 重新规范,只能使用原来Unicode定义的区域, U+0000到U+10FFFF。根据规范,这些字节值将无法出现在合法 UTF-8序列中

4. 实战演练

下面是我开发的游戏引擎中的一个模块,用于帮助其他开发者处理快速字符串相关的事件。

  • QString.h
#pragma execution_character_set("utf-8")
/*开头第一句主要是为了完美解决C++ VS输出中文乱码痛点
概要:
使用高版本的VS,将源代码文件保存为utf-8格式,接着在源码开头处告诉编译器要用utf-8编码方案进行解析源代码。
这样做直接就可以了正常解析源码中的中文了,无需使用xml文档或者对源码中的中文字符进行额外的转码处理。
具体参考:https://blog.csdn.net/COCO56/article/details/91350176
*/
#pragma once

/*QuickEngine为我自主开发的游戏引擎
// #include "QuickEngine.h"
// QString是QuickEngine中的一个模块,用于处理快速字符串相关的事件
*/

#include <vector>
#include <string>
using namespace std;

class QString
{
	enum CharSet
	{
		UTF_8 = 0
	};
public:
	/*暂时不处理非UTF_8编码的处理*/
	//获取一个字符串中有多少个字符
	static int getStringLetterNumber(string str, CharSet cs = UTF_8);
	//将一个字符串中的所有字符都识别分离出来,并将每个字符保存为vector<string>中的一个元素
	static vector<string> strToVector(string str, CharSet cs = UTF_8);
};
  • QString.cpp
#pragma execution_character_set("utf-8")

#include "QString.h"

int QString::getStringLetterNumber(string str, CharSet cs)
{
	if (cs != UTF_8)
	{
		return -1;
	}
	const char* s = str.c_str();
	int i = 0, j = 0;
	while (s[i])
	{
		if ((s[i] & 0b11000000) != 0b10000000) j++;
		i++;
	}
	return j;
}

vector<string> QString::strToVector(string str, CharSet cs)
{
	vector<string> vstr;
	if (cs != UTF_8) { return vstr; };

	const char* s = str.c_str();
	int i = 1, j = 0, l=0, sum=0;

	while (1)
	{
		if (s[i])//未到字符串的结尾,即未读取到'\0'
		{
			if ((s[i] & 0b11000000) != 0b10000000)//读取到一个新字符的开头
			{
				l = i - j;
				//CCLOG("f = %d, j=%d, l=%d, s=%s", flag, j, l, str.substr(j, l).c_str());
				vstr.push_back(str.substr(j, l));
				j = i;
			}
			i++;
		}
		else
		{
			l = i - j;
			vstr.push_back(str.substr(j, l));
			break;
		}
	}
	return vstr;
}
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在C++,可以使用正则表达式库来匹配字符串的数字并提取成整数。下面是一个示例代码,演示了如何使用正则表达式提取字符串的数字并转换为整数: ```cpp #include <iostream> #include <regex> #include <string> int main() { std::string input = "abc123def456ghi789"; std::regex pattern("\\d+"); // 匹配一个或多个数字 std::smatch match; std::vector<int> numbers; // 存储提取的整数 // 使用迭代器循环匹配所有数字 for (std::sregex_iterator it(input.begin(), input.end(), pattern), end; it != end; ++it) { std::string match_str = it->str(); // 获取匹配到的字符串 int number = std::stoi(match_str); // 将字符串转换为整数 numbers.push_back(number); // 存储提取到的整数 } // 打印提取到的整数 for (int number : numbers) { std::cout << number << " "; } std::cout << std::endl; return 0; } ``` 在上面的示例代码,我们使用了`std::regex`来定义匹配模式,即`\d+`,它可以匹配一个或多个数字。然后,我们使用`std::sregex_iterator`迭代器来遍历字符串所有匹配的数字。在每次迭代,我们可以通过`it->str()`获取匹配到的字符串,并使用`std::stoi()`将字符串转换为整数。最后,我们将提取到的整数存储在`numbers`向量,并打印出来。 请注意,使用正则表达式可能会带来一些性能开销,因此在处理大量数据时要注意效率。另外,如果字符串的格式不符合预期,可能会导致转换失败或产生异常。因此,建议在实际应用添加一些错误处理机制来保证代码的健壮性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

COCO56(徐可可)

建议微信红包:xucoco56

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值