如何在C++或Qt 6中将Unicode分数转换为ASCII分数?
将Unicode分数转换为ASCII分数(纯C++/Qt6实现,无需硬编码字典)
核心原理
Unicode中绝大多数预定义的单个分数字符(如½、¾)都具备规范分解形式(NFD),会被拆分为「数字(分子) + 分数斜线(U+2044) + 数字(分母)」的字符序列。我们可以利用这一Unicode特性,无需硬编码字典,通过字符分解提取分子和分母,再拼接为分子/分母的ASCII格式。
一、Qt6实现
Qt内置了完善的Unicode处理工具,直接通过QChar::decomposition()获取字符的分解序列,即可快速完成转换:
#include <QString> #include <QChar> QString convertUnicodeFractionsToAscii(const QString& input) { QString result; for (const QChar& c : input) { // 获取字符的规范分解序列 QString decomposed = c.decomposition(); // 检查是否符合「数字 + U+2044分数斜线 + 数字」的结构 if (decomposed.size() == 3 && decomposed[1].unicode() == 0x2044) { QChar numerator = decomposed[0]; QChar denominator = decomposed[2]; if (numerator.isDigit() && denominator.isDigit()) { result += numerator; result += '/'; result += denominator; continue; } } // 非目标分数字符,直接保留 result += c; } return result; }
使用示例:
QString testStr = "今天买了½个西瓜,吃了¾,剩下⅓"; QString converted = convertUnicodeFractionsToAscii(testStr); // converted 结果:"今天买了1/2个西瓜,吃了3/4,剩下1/3"
二、纯C++实现(跨平台,基于ICU库)
标准C++对Unicode分解的原生支持有限,推荐使用ICU(International Components for Unicode)库完成跨平台的Unicode处理:
实现代码
#include <iostream> #include <string> #include <unicode/unistr.h> #include <unicode/normalizer2.h> std::string convertUnicodeFractionsToAscii(const std::string& inputUtf8) { icu::UnicodeString input = icu::UnicodeString::fromUTF8(inputUtf8); icu::UnicodeString result; // 获取NFD归一化器实例 const icu::Normalizer2* nfdNormalizer = icu::Normalizer2::getNFDInstance(nullptr); for (int i = 0; i < input.length(); ++i) { UChar32 currentChar = input.char32At(i); icu::UnicodeString decomposed; nfdNormalizer->normalize(currentChar, decomposed); // 验证分解序列是否符合分数结构 if (decomposed.length() == 3 && decomposed.char32At(1) == 0x2044) { UChar32 numerator = decomposed.char32At(0); UChar32 denominator = decomposed.char32At(2); if (numerator >= '0' && numerator <= '9' && denominator >= '0' && denominator <= '9') { result.append(static_cast<UChar>(numerator)); result.append("/"); result.append(static_cast<UChar>(denominator)); continue; } } // 保留原字符 result.append(currentChar); } std::string outputUtf8; result.toUTF8String(outputUtf8); return outputUtf8; } // 测试代码 int main() { std::string test = "I ate ½ of the pizza, leaving ¾ for later"; std::string converted = convertUnicodeFractionsToAscii(test); std::cout << converted << std::endl; // 输出:I ate 1/2 of the pizza, leaving 3/4 for later return 0; }
注意事项
- 上述方法覆盖了绝大多数单个Unicode分数字符(包括
½、¾、⅓、⅛等); - 对于带整数部分的组合分数(如
1½),可直接保留整数部分后单独转换分数字符; - 若无需跨平台,Windows下也可使用
NormalizeStringAPI实现字符分解,但兼容性不如ICU。
内容的提问来源于stack exchange,提问作者Michael21
相关产品推荐
相关产品推荐

