请求实现普通字符与下划线式Unicode字符互转的转换器
请求实现普通字符与下划线式Unicode字符互转的转换器
嘿,我完全懂你的需求——在JavaFX菜单里用带下划线的Unicode字符,又不想因为用图形丢失样式,确实挺头疼的。下面给你几种主流语言的实现方案,分两种思路:一种是直接映射预定义的带下划线Unicode字符(比如你举的ḏ对应d),另一种是用组合下划线字符生成(更通用,毕竟不是所有字母都有预组合的带下划线版本)。
一、Java 实现
方案1:预定义字符映射(针对有对应预组合Unicode的字符)
这种方式适合你提到的像d→ḏ这类有现成预组合Unicode的场景,我们先做一个映射表,然后实现互转方法:
import java.util.HashMap; import java.util.Map; public class UnderlineCharConverter { // 普通字符到带下划线Unicode的映射 private static final Map<Character, Character> charToUnderline = new HashMap<>(); // 带下划线Unicode到普通字符的映射 private static final Map<Character, Character> underlineToChar = new HashMap<>(); static { // 添加你需要的字符映射,比如示例中的d和ḏ addMapping('d', '\u1E0F'); // 可以继续添加其他字符,比如a→ḁ(\u1E01)、b→ḇ(\u1E07)等 addMapping('a', '\u1E01'); addMapping('b', '\u1E07'); } private static void addMapping(Character normal, Character underlined) { charToUnderline.put(normal, underlined); underlineToChar.put(underlined, normal); } // 普通字符串转带下划线字符串 public static String toUnderlined(String input) { StringBuilder sb = new StringBuilder(); for (char c : input.toCharArray()) { sb.append(charToUnderline.getOrDefault(c, c)); } return sb.toString(); } // 带下划线字符串转普通字符串 public static String toNormal(String input) { StringBuilder sb = new StringBuilder(); for (char c : input.toCharArray()) { sb.append(underlineToChar.getOrDefault(c, c)); } return sb.toString(); } // 测试用例 public static void main(String[] args) { String test = "dab"; String underlined = toUnderlined(test); System.out.println("转下划线后:" + underlined); // 输出 ḏḁḇ System.out.println("转回普通字符:" + toNormal(underlined)); // 输出 dab } }
在JavaFX菜单里用的话,直接调用toUnderlined()方法处理菜单文本就行,完全不会丢失样式:
MenuItem menuItem = new MenuItem(UnderlineCharConverter.toUnderlined("File"));
方案2:组合下划线字符(通用所有字母)
如果有些字母没有预组合的带下划线Unicode,我们可以用**组合下划线字符(U+0332)**放在普通字符下方来模拟,这种方式更通用:
public class UnderlineCharConverter { // 普通字符转带下划线(用组合字符) public static String toUnderlinedWithCombining(String input) { StringBuilder sb = new StringBuilder(); for (char c : input.toCharArray()) { sb.append(c).append('\u0332'); } return sb.toString(); } // 组合下划线字符转回普通字符 public static String toNormalFromCombining(String input) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < input.length(); i++) { char c = input.charAt(i); // 跳过组合下划线字符 if (c != '\u0332') { sb.append(c); } } return sb.toString(); } public static void main(String[] args) { String test = "Hello"; String underlined = toUnderlinedWithCombining(test); System.out.println("转下划线后:" + underlined); // 输出 H̲e̲l̲l̲o̲ System.out.println("转回普通字符:" + toNormalFromCombining(underlined)); // 输出 Hello } }
二、JavaScript 实现
同样提供两种方案:
方案1:预定义映射
const charToUnderline = new Map([ ['d', '\u1E0F'], ['a', '\u1E01'], ['b', '\u1E07'] ]); const underlineToChar = new Map([...charToUnderline.entries()].map(([k, v]) => [v, k])); function toUnderlined(input) { return [...input].map(c => charToUnderline.get(c) || c).join(''); } function toNormal(input) { return [...input].map(c => underlineToChar.get(c) || c).join(''); } // 测试 console.log(toUnderlined('dab')); // ḏḁḇ console.log(toNormal('ḏḁḇ')); // dab
方案2:组合下划线
function toUnderlinedWithCombining(input) { return [...input].map(c => c + '\u0332').join(''); } function toNormalFromCombining(input) { return [...input].filter(c => c !== '\u0332').join(''); } // 测试 console.log(toUnderlinedWithCombining('Hello')); // H̲e̲l̲l̲o̲ console.log(toNormalFromCombining('H̲e̲l̲l̲o̲')); // Hello
三、C# 实现
方案1:预定义映射
using System; using System.Collections.Generic; public class UnderlineCharConverter { private static readonly Dictionary<char, char> charToUnderline = new Dictionary<char, char> { {'d', '\u1E0F'}, {'a', '\u1E01'}, {'b', '\u1E07'} }; private static readonly Dictionary<char, char> underlineToChar = new Dictionary<char, char>(); static UnderlineCharConverter() { foreach (var pair in charToUnderline) { underlineToChar.Add(pair.Value, pair.Key); } } public static string ToUnderlined(string input) { char[] result = new char[input.Length]; for (int i = 0; i < input.Length; i++) { result[i] = charToUnderline.TryGetValue(input[i], out char underlined) ? underlined : input[i]; } return new string(result); } public static string ToNormal(string input) { char[] result = new char[input.Length]; for (int i = 0; i < input.Length; i++) { result[i] = underlineToChar.TryGetValue(input[i], out char normal) ? normal : input[i]; } return new string(result); } static void Main() { string test = "dab"; string underlined = ToUnderlined(test); Console.WriteLine($"转下划线后:{underlined}"); // ḏḁḇ Console.WriteLine($"转回普通字符:{ToNormal(underlined)}"); // dab } }
方案2:组合下划线
public class UnderlineCharConverter { public static string ToUnderlinedWithCombining(string input) { char[] result = new char[input.Length * 2]; int index = 0; foreach (char c in input) { result[index++] = c; result[index++] = '\u0332'; } return new string(result); } public static string ToNormalFromCombining(string input) { char[] result = new char[input.Length / 2]; int index = 0; for (int i = 0; i < input.Length; i += 2) { result[index++] = input[i]; } return new string(result); } static void Main() { string test = "Hello"; string underlined = ToUnderlinedWithCombining(test); Console.WriteLine($"转下划线后:{underlined}"); // H̲e̲l̲l̲o̲ Console.WriteLine($"转回普通字符:{ToNormalFromCombining(underlined)}"); // Hello } }
备注:内容来源于stack exchange,提问作者Dan Howard
相关产品推荐
相关产品推荐

