You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 14:13:19