2013-03-31 3 views
1

У меня был аналогичный вопрос, какой язык лучше всего подходит для этой задачи, и Perl был ответом. Но мне все еще любопытно, как разрешить это с помощью C.Как написать этот код на C с Unicode?

Я хочу дать этой программе большой текстовый файл, заполненный образцами немецкого текста, взятых из романов, газет, веб-страниц. Я хочу список частот всех слов в текстовом файле, отсортированных по наиболее распространенному слову. Мне нужен список из 3000 наиболее распространенных немецких слов.

Если это была только проблема ASCII, то это была бы детская игра для меня. Прочитав о Юникоде все утро, я действительно удивляюсь, что это за минное поле.

Как это делается в C?

У меня был друг, который положил что-то вместе в Python, но он все еще новичок, и его код занял около 30 минут в текстовом файле 1,4 МБ.

+0

Что такое кодировка символов большого текстового файла, составляющего ваш состав слов? UTF-8? UTF-16? Что-то другое? –

+2

Я считаю, что это в основном * один лайнер * в Python, игнорируя импорт: 'print (Counter (re.findall (r '(? U) \ w +', open ('input.txt'). Read())) .most_common (3000)) '. Не самый быстрый путь, но это не займет 30 минут. – nneonneo

+0

@AdamRosenfield Это UTF-8. –

ответ

5

Это зависит от кодировки. Самый простой - это UTF-8, в котором вы можете просто хранить строки в массивах char*. Удивительно, но создание частотного списка было бы выполнено с использованием почти того же кода, что и в случае текста ASCII. Это своего рода магия UTF-8, но именно поэтому эта кодировка настолько мощная!

Есть несколько вещи, которую вы должны помнить в этом случае:

  1. Unicode обеспечивает более белые символы, чем ASCII. Вам понадобится их список, чтобы знать, где слова разделены. К счастью, Wikipedia has one.

  2. Unicode не всегда однозначен. Бывают случаи, когда разные последовательности создают один и тот же символ. Обычно это происходит с составленными символами: например. Немецкий Ä может быть представлена ​​в виде:

    • характер U+00C4 - одной буквой Ä
    • последовательности U+0041 U+0308 - латинская буква A и умляутом (умляут) над ним.

    К счастью, на немецком языке имеется только семь неанглийских символов: ÄäÖöÜüß. Вам нужно будет проверить, как выглядят их альтернативные варианты (например, here на страницах 4 и 5 вы должны найти все немецкие символы и их альтернативные формы).

Конечно, чтобы решить обе проблемы, вам также необходимо знать, как все ваши результаты представлены в UTF-8. Это описано в RFC 3629, стр. 3.

В случае других кодировок (или других языков) я предлагаю не заниматься этим самостоятельно, а использовать уже существующую библиотеку. Если вы находитесь в Linux (или большинстве других Unices), вы можете использовать функцию iconv (man 3 iconv), чтобы преобразовать текст в UTF-8 и идти, как я описал ранее.

Другой выбор - использование библиотеки, которая уже имеет дело с различными вариантами Unicode. Наиболее мощным, вероятно, является ICU - International Components For Unicode, проверьте их руководства, чтобы узнать, как выполнить свою задачу, используя его.

0

Вы можете использовать строки wchar_t и функции, определенные в файле заголовка wchar.h.

0

Если вы можете сделать это без проблем в ASCII, это не должно быть намного сложнее в Unicode (по крайней мере, на C99).

Практически все стандартные функции библиотеки, которые работают с строками и символами, имеют широкие эквиваленты символов, а когда вы работаете с широкими символами, вам никогда не придется беспокоиться о базовой кодировке - один широкий символ представляет один фактический характер. Там iswupper, towupper, wcslen и так далее.

Предполагается, что вы работаете в простой среде (например, системе UTF-8, тексте UTF-8), поскольку локаль будет обрабатывать все. Если нет, есть еще работа.

1

Вы не указали явно требованиям вашей программы, но я могу думать только о двух аспектах, которые, возможно, потребуется вам, чтобы заботиться о личности персонажа:

  1. Если ввод текста смешанный случай, вы может захотеть сопоставить все слова в одном и том же случае, чтобы подсчитывались разные версии одного и того же слова.

  2. Если вход в смешанной форме нормализации (некоторые символы предварительно скомпонованы, другие разложены), то вам необходимо выполнить нормализацию, чтобы убедиться, что слова, которые отличаются только таким образом, подсчитываются вместе.

Если, например, ваш вход был полностью строчным NFC, программа, написанная с учетом только ASCII, будет отлично работать для вашей задачи. Поскольку это, вероятно, не так, вам необходимо оценить ваши требования. Для простого выпуска 1 (case) вы, вероятно, можете использовать функции широкоформатного символа stdio (или байт-ориентированные stdio и mbsrtowcs) и towlower, чтобы делать картографирование случаев. Для проблемы 2 (нормализация) вам нужно либо использовать существующую библиотеку Unicode для C, либо использовать ее самостоятельно.

+0

Для немецких, _tschüß_ uppercases для _TSCHÜSS_ и _ue_ является альтернативной формой для _ü_, поэтому 'towlower()' не подходит. – ninjalj

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] } 
} 

Invoke:

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

EDIT:

Это очень близко к тому, что вы ищете для.

+0

Ваш скрипт содержит знаки препинания как части слов, и мне нужен отсортированный список, но я вижу вашу точку зрения. Благодарю. –

+0

@KorganRivera редактировать. Я не боюсь. – yeyo