如何编写涉及Unicode的C代码?

时间:2013-03-31 21:47:45

标签: c word-frequency

我有一个类似的问题,询问哪种语言最适合这项任务,而Perl就是答案。但我仍然很好奇如何用C解决这个问题。

我想给这个程序一个大文本文件,里面装满了从小说,报纸,网页上摘取的德文文本样本。我想要一个文本文件中所有单词的频率列表,按最常见的单词排序。我需要列出3000个最常见的德语单词。

如果这只是一个ASCII问题,那么这对我来说就是孩子的游戏。在整个早上读完Unicode之后,我真的很惊讶雷区是什么。

这是如何在C中完成的?

我有一个朋友在Python中放了一些东西,但他仍然是初学者,他的代码在1.4 MB文本文件上花了大约30分钟。

5 个答案:

答案 0 :(得分:5)

这取决于编码。最简单的是UTF-8,您可以在char*数组中简单地存储字符串。令人惊讶的是,构建频率列表将使用几乎相同的代码完成,就像ASCII文本一样。这是一种UTF-8魔术,但这就是为什么这种编码如此强大!

在这种情况下,你应该记住一些事情:

  1. Unicode提供比ASCII更多的白色字符。您需要一个列表来了解单词的分隔位置。很高兴,Wikipedia has one

  2. Unicode并不总是毫不含糊。有些情况下,不同的序列产生相同的字符。通常使用组合字符:例如:德语Ä可以表示为:

    • 字符U+00C4 - 单个字母Ä
    • 序列U+0041 U+0308 - 拉丁字母A和分音符(umlaut)。

    令人高兴的是,在德语中只有七个非英语字符:ÄäÖöÜüß。您需要检查其替代变体的外观(例如,在第4页和第5页here,您应该找到所有德语字符及其替代形式)。

  3. 当然,要解决这两个问题,您还需要了解所有结果如何用UTF-8表示。这在RFC 3629,第3页中有所描述。

    如果是其他编码(或其他语言),我建议不要自己处理,而是使用一些现有的库。如果您使用的是Linux(或大多数其他Unices),则可以使用iconv函数(man 3 iconv)将文本转换为UTF-8,然后按照我之前的描述进行操作。

    其他选择是使用一些已经处理各种Unicode变体的库。最强大的可能是ICU - International Components For Unicode,请查看他们的手册以了解如何使用它来执行任务。

答案 1 :(得分:1)

您尚未明确规定您的计划要求,但我只能想到您可能需要关注角色身份的两个方面:

  1. 如果输入文本是大小写混合的情况,您可能希望将所有单词映射到同一个案例,以便同一个单词的不同用途版本一起计算。

  2. 如果输入采用混合标准化形式(某些字符预先组合,其他字符已经分解),那么您需要执行标准化以确保仅以这种方式不同的单词一起计算。

  3. 例如,如果您的输入是全小写的NFC,那么用ASCII编写的程序将非常适合您的任务。由于情况可能并非如此,因此您需要评估您的要求。对于问题1(案例),您可以使用宽字符stdio函数(或面向字节的stdio和mbsrtowcs)和towlower来进行大小写映射。对于问题2(规范化),您需要为C使用现有的Unicode库,或者自己动手。

答案 2 :(得分:0)

您可以使用wchar_t字符串以及wchar.h头文件中定义的函数。

答案 3 :(得分:0)

如果你能在没有ASCII问题的情况下做到这一点,那么在Unicode中应该不会那么难(至少在C99中)。

几乎所有处理字符串和字符的标准库函数都具有广泛的字符等价,当你使用宽字符时,你永远不必担心底层编码 - 一个宽字符代表一个实际字符。有iswuppertowupperwcslen等等。

假设您在一个简单的环境中工作(例如UTF-8系统,UTF-8文本),因为语言环境将处理所有事情。如果没有,还有更多的工作。

答案 4 :(得分:0)

您可能希望使用系统工具来解决此问题,如果您的系统区域设置正确,则可以执行此操作。 AWK是一个你可以很容易使用的,例如

BEGIN {
    FS="[^[:alpha:]]"
}
{
    for(i=1; i<=NF; i++) {
        if(array[$i]) {
            array[$i] += 1
        } else {
            array[$i]  = 1
        }
    }
}
END{
    for(i in array) {printf "%s = %d\n", i, array[i] }
}

调用:

$ awk -f script.awk German.txt | sort

编辑:

这是非常关闭你正在寻找的东西。