在C#中将全角字符转换为半角字符,反之亦然

6

正如标题所述,我想在C#中将全角字符转换为半角字符,反之亦然,但是我无法找到如何实现它的方法。因此,将“ラーメン”转换为“ラーメン”,并反向转换。 是否可能编写一个方法,根据输入格式自动确定转换方向?

2个回答

3

您可以使用Strings.StrConv()方法,通过引用Microsoft.VisualBasic.dll,或者您可以p/invoke LCMapString()本地函数:

private const uint LOCALE_SYSTEM_DEFAULT = 0x0800;
private const uint LCMAP_HALFWIDTH = 0x00400000;

public static string ToHalfWidth(string fullWidth)
{
    StringBuilder sb = new StringBuilder(256);
    LCMapString(LOCALE_SYSTEM_DEFAULT, LCMAP_HALFWIDTH, fullWidth, -1, sb, sb.Capacity);
    return sb.ToString();
}

[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
private static extern int LCMapString(uint Locale, uint dwMapFlags, string lpSrcStr, int cchSrc, StringBuilder lpDestStr, int cchDest);

同时,您也可以进行反向操作:

private const uint LCMAP_FULLWIDTH = 0x00800000;

public static string ToFullWidth(string halfWidth)
{
    StringBuilder sb = new StringBuilder(256);
    LCMapString(LOCALE_SYSTEM_DEFAULT, LCMAP_FULLWIDTH, halfWidth, -1, sb, sb.Capacity);
    return sb.ToString();
}

关于检测输入字符串的格式,如果不进行转换并比较结果,我不知道有什么简单的方法。(如果字符串包含全角和半角字符怎么办?)


感谢您的建议。这基本上回答了我的问题。可惜没有简单的方法将两个功能结合起来以实现自动转换。 - yu_ominae
无论如何,这样做都会产生歧义行为。如果我将 "ラーメン"(注意第一个字符是半角)作为输入传递给您的组合函数,您会输出 "ラーメン"(逐个字符转换),"ラーメン"(基于第一个字符转换)还是 "ラーメン"(基于大多数转换)? - John Estropia
你说得没错,它变得非常复杂... 我正在处理包含日语字符的字符串中的子字符串高亮显示。我想在这种情况下覆盖所有可能性需要太多的处理能力,对最终用户的好处很少。顺便说一下,我最终采取了你建议的方法,将字符串转换为全角和半角,并将两者进行比较,以查看是否发生了任何事情,以此来消除汉字。感谢您的帮助! - yu_ominae

2

一种方法是编译一个包含所有需要转换的字符及其对应关系的列表,然后迭代输入字符串并将列表中的所有字符替换为它们的等效字符。

var fullToHalf = new Dictionary<char, char>
{
    ...
    { '\u30E9', '\uFF97' }, // KATAKANA LETTER RA -> HALFWIDTH KATAKANA LETTER RA
    { '\u30EA', '\uFF98' }, // KATAKANA LETTER RI -> HALFWIDTH KATAKANA LETTER RI
    ...
};

var halfToFull = fullToHalf.ToDictionary(kv => kv.Value, kv => kv.Key);

var input = "\u30E9";

var isFullWidth = input.All(ch => fullToHalf.ContainsKey(ch));
var isHalfWidth = input.All(ch => halfToFull.ContainsKey(ch));

var result = new string(input.Select(ch => fullToHalf[ch]).ToArray());
// result == "\uFF97"

Unicode图表:半角和全角字符(FF00-FFEF)


此链接提供了有关半角和全角字符的Unicode编码。

谢谢您的建议。我考虑过使用string.Contains和包含所有字符的数组来实现,但是我担心这需要花费很长时间。使用字典似乎更加简洁,所以我可能会尝试一下这种方法。 - yu_ominae
只是想说:非常感谢您的建议。我喜欢这种方法,但对于我想要实现的目标来说过于复杂了。另外,我对此存在一个潜在问题,就是需要事先创建字典...很奇怪,在纯C#中这应该是唯一的方法,而VB却有StrConv()方法。 - yu_ominae
我已经制作了一个.NET标准库和NuGet包,实现了这种方法:https://github.com/bgever/HalfFullWidth - Bart Verkoeijen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接