重新实现 ToUpper()

3
6个回答

8
  1. 我下载Unicode表格
  2. 我将表格导入数据库
  3. 我编写了一个名为upper()的方法。

这是一个示例实现 ;)

public static String upper(String s) {
    if (s == null) {
        return null;
    }

    final int N = s.length(); // Mind the optimization!
    PreparedStatement stmtName = null;
    PreparedStatement stmtSmall = null;
    ResultSet rsName = null;
    ResultSet rsSmall = null;
    StringBuilder buffer = new StringBuilder (N); // Much faster than StringBuffer!
    try {
        conn = DBFactory.getConnection();
        stmtName = conn.prepareStatement("select name from unicode.chart where codepoint = ?");
        // TODO Optimization: Maybe move this in the if() so we don't create this
        // unless there are uppercase characters in the string.
        stmtSmall = conn.prepareStatement("select codepoint from unicode.chart where name = ?");
        for (int i=0; i<N; i++) {
            int c = s.charAt(i);
            stmtName.setInt(1, c);
            rsName = stmtName.execute();
            if (rsName.next()) {
                String name = rsName.getString(1);
                if (name.contains(" SMALL ")) {
                    name = name.replaceAll(" SMALL ", " CAPITAL ");

                    stmtSmall.setString(1, name);
                    rsSmall = stmtSmall.execute();
                    if (rsSmall.next()) {
                        c = rsSmall.getInt(1);
                    }

                    rsSmall = DBUtil.close(rsSmall);
                }
            }
            rsName = DBUtil.close(rsName);
        }
    }
    finally {
        // Always clean up
        rsSmall = DBUtil.close(rsSmall);
        rsName = DBUtil.close(rsName);
        stmtSmall = DBUtil.close(stmtSmall);
        stmtName = DBUtil.close(stmtName);
    }

    // TODO Optimization: Maybe read the table once into RAM at the start
    // Would waste a lot of memory, though :/
    return buffer.toString();
}

注意:您可以在unicode.org上找到的Unicode图表中包含字符/代码点的名称。这个字符串将包含大写字母的字符,其名称中包含“SMALL”(请注意空格,否则可能会匹配“SMALLER”等)。现在,您可以搜索一个类似名称,并将“SMALL”替换为“CAPITAL”。如果找到了它,您就找到了大写版。


7

我不认为SO能够在一篇帖子中处理Unicode表的大小 :)

不幸的是,仅仅使用char.ToUpper()来转换每个字符并不那么简单。

例如:

(string-upcase "Straße")    ⇒ "STRASSE"
(string-downcase "Straße")  ⇒ "straße"
(string-upcase "ΧΑΟΣ")      ⇒ "ΧΑΟΣ"
(string-downcase "ΧΑΟΣ")    ⇒ "χαος"
(string-downcase "ΧΑΟΣΣ")   ⇒ "χαοσς"
(string-downcase "ΧΑΟΣ Σ")  ⇒ "χαος σ"
(string-upcase "χαος")      ⇒ "ΧΑΟΣ"
(string-upcase "χαοσ")      ⇒ "ΧΑΟΣ"

(string-upcase "Straße") ⇒ "STRAẞE" 会变成 "STRAẞE" - hangy
Hangy,抱歉,它无法呈现。此外,我的转换是本地独立的(我想我应该提到这一点;p)。 - leppie
我只是从R6RS Scheme规范中简单地粘贴了过来,可能是一个打字错误,会检查测试。 - leppie
看起来没问题。这些Scheme的家伙真是一丝不苟,我会相信他们的话的 :) - leppie
2
大写的ß仅在4月更新ISO标准时被添加到Unicode标准中,因此字体支持确实非常罕见。 :) 此外,Duden尚未将其纳入标准语言,因此您的 正确的。 :) 只是想指出另一种未来可能性。 - hangy
感谢澄清,我会引用你的帖子 :) - leppie

5

没有静态表格是足够的,因为您需要在了解正确的转换之前知道语言。

例如,在土耳其语中,i 需要变成 İ (U+0130),而在其他任何语言中,它需要变成 I (U+0049)。而这个 i 是相同的字符 U+0069。


3
噢,我想这就是为什么一个合适的国际化库需要超过10MB的原因。真是疯狂的人们啊。为什么我们的祖先不能只用一个漂亮简单的书写系统呢? :P - Vilx-

1

我不会赢得奖励分,但这是7位ASCII码:

char toupper(char c)
{
    if ((c < 'a') || (c > 'z')) { return c; }
    else { return c & 0xdf; }
}

这基本上就是在strings.h中使用的宏。 - Paul Tomblin
@Paul Tomblin:不错!我希望能够接近 :) - e.James
那128个字符呢?你是指7位制吗? - leppie
说起来,如果我没记错的话,我认为宏实际上添加了('A'-'a')。是的,@leppie,它只适用于ASCII码,而ASCII码定义是7位。 - Paul Tomblin
检查 (c < 'a') || (c > 'z') 处理了 128..255(如果提供了有符号字符,则为 0..-127)。底线是只有从 'a' 到 'z' 的 26 个字符被修改。 - e.James
显示剩余2条评论

0

让我建议为希伯来语、阿拉伯语、格鲁吉亚语等没有大写字母的语言提供更多的奖励分数。 :-)


对于那些语言来说,这将非常简单... 无论如何,阿拉伯语和希伯来语都有它们自己的字符串操作功能需求。 - hasen

0

在Python中...

touppe_map = { massive dictionary to handle all cases in all languages }
def to_upper( c ):
   return toupper_map.get( c, c )

或者,如果你想用“错误的方式”来做

def to_upper( c ):
  for k,v in toupper_map.items():
     if k == c: return v
  return c

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