Я написал программу на C, которая разбивает слова на слоги, сегменты и буквы. Он хорошо работает с символами ASCII, но я хочу сделать версии, которые работают для IPA и арабского языка.
У меня проблемы с сохранением и выполнением функций на отдельных персонажах. Мой редактор и консоль настроены на UTF-8 и могут хорошо отображать текст на арабском языке, если я сохраню его как char *, но когда я пытаюсь напечатать wchars, они отображают случайные знаки препинания.
Моя программа должна быть способна распознавать индивидуальный символ UTF-8 для работы. Например, для слова "хотя" он хранит "t" как слог [1] сегмент [1] письмо [1], h как слог [1] сегмент [1] письмо [2] и т.д. Я хочу иметь возможность сделать то же самое для символов, отличных от ASCII.
В течение всего дня я провел целый день, изучая unicode и тестируя различные методы, и я не могу заставить их записывать арабский символ в качестве персонажа.
Я не уверен, что я просто сделал некоторые глупые синтаксические ошибки на этом пути, если я полностью не понял всю концепцию или если на самом деле просто невозможно сделать то, что я хочу в C и я должен просто отказаться и попробовать другой язык...
Я бы в массовом порядке массово оценил любую помощь, которую вы можете предложить! Я новичок в программировании, но unicode полностью помогает моей работе, поэтому я хочу разобраться, как это сделать с самого начала.
Мое понимание того, как работает Юникод (в случае, если я ошибаюсь):
-
Я ввожу текст в свой редактор. Мой редактор кодирует его в соответствии с установленной мной кодировкой. Поэтому, если я установил его в UFT-8, он будет кодировать арабскую букву ب с 2-байтовой последовательностью 0xd8 0xab, которая указывает кодовую точку U + 0628.
-
Я скомпилирую его, разбив 0xd8 0xab на двоичный файл 11011000 10101000.
-
Я запускаю его в командной строке. Командная строка интерпретирует текст в соответствии с кодировкой, которую я установил, поэтому, если я установил ее в UFT-8, она должна интерпретировать 11011000 10101000 как кодовую точку U + 0628. Алгоритмы Unicode также говорят, какая версия U + 0628 будет отображаться для меня, поскольку персонаж имеет разные формы в зависимости от того, где он находится в слове. Поскольку персонаж один, он покажет мне автономную версию ب
Мое понимание способов обработки Unicode в C:
Вариант A - Используйте одиночные байты, кодированные как UTF-8 (http://www.nubaria.com/en/blog/?p=289)
Используйте одиночные байты, кодированные как UTF-8. Оставьте все мои типы данных как символы и char массивы и введите только символы ASCII в моем коде. Если мне абсолютно необходимо жестко закодировать символ юникода, введите его в виде массива в формате:
const char kChineseSampleText[] = "\xe4\xb8\xad\xe6\x96\x87";
Мои проблемы с этим:
- Мне нужно манипулировать отдельными символами
- Чтобы ввести арабские символы в качестве кодовых точек, мы сделаем мой код полностью нечитаемым и сильно замедляем меня.
Вариант B - используйте wchar и друзей (http://icu-project.org/docs/papers/unicode_wchar_t.html)
Обмен с использованием символов для wchars, которые содержат от 2 до 4 байтов в зависимости от компилятора. Строковые функции, такие как strlen, не будут работать, поскольку они ожидают, что символы будут одним байтом, но существуют w-функции, такие как wprintf, которые я могу использовать вместо этого.
Моя проблема с этим:
Я не могу заставить wchars печатать арабские символы вообще! Я могу заставить их печатать английские буквы в порядке, но арабские символы просто вытягиваются как случайные знаки препинания.
Я попытался ввести кодовую точку Юникода, а также фактический арабский символ, и я попробовал напечатать их как на консоли, так и в текстовом файле с кодировкой UTF-8, и я получаю тот же результат, хотя оба консоль и текстовый файл отображает арабский текст, если он введен как char *. Я включил свой код в конце.
(Его стоит сказать здесь, что я знаю, что многие люди думают, что wchars плохие, потому что они arent очень портативны и потому, что они занимают дополнительное пространство для символов ASCII. Но на этом этапе ни одна из этих вещей не вызывает беспокойства для меня - я просто пишу программу для запуска на своем собственном компьютере, и программа будет обрабатывать только короткие строки.)
Вариант C - использование внешних библиотек
Я читал в различных комментариях, что внешние библиотеки - это путь, поэтому я пробовал:
Библиотека программирования C
http://www.cprogramming.com/tutorial/unicode.htmlпредлагает заменить все символы целыми числами без знака и использовать специальные функции для итерации по строкам и т.д. На сайте даже предоставляется библиотека для загрузки.
Моя проблема:
Пока я могу установить символ как целое число без знака, я не могу его распечатать, потому что функции printf и wprintf не работают, и библиотека также не предоставляется на веб-сайте (я думаю, возможно, библиотека была разработана для Linux? Некоторые типы данных недействительны, и их изменение не работает)
Библиотека ICU
Моя проблема:
Я загрузил библиотеку ICU, но когда я изучал, как ее использовать, я видел, что такие функции, как characterIterator, недоступны для использования в C (http://userguide.icu-project.org/strings). Возможность итерации через персонажи полностью фундаментальна для того, что мне нужно делать, поэтому я не думаю, что библиотека будет работать на меня.
Мой код
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <locale.h>
#include <string.h>
int main ()
{
wchar_t unicode = L'\xd8ac';
wchar_t arabic = L'ب';
wchar_t number = 0x062c;
FILE* f;
f = fopen("unitest.txt","w");
char* string = "ايه الاخبار";
//printf - works
printf("printf - literal arabic character is \"م\"\n");
fprintf(f,"printf - literal arabic character is \"م\"\n");
printf("printf - char* string is \"%s\"\n",string);
fprintf(f,"printf - char* string is \"%s\"\n",string);
//wprintf - english - works
wprintf(L"wprintf - literal english char is \"%C\"\n\n", L't');
fwprintf(f,L"wprintf - literal english char is \"%C\"\n\n", L't');
//wprintf - arabic - doesnt work
wprintf(L"wprintf - unicode wchar_t is \"%C\"\n", unicode);
fwprintf(f,L"wprintf - unicode wchar_t is \"%C\"\n", unicode);
wprintf(L"wprintf - unicode number wchar_t is \"%C\"\n", number);
fwprintf(f,L"wprintf - unicode number wchar_t is \"%C\"\n", number);
wprintf(L"wprintf - arabic wchar_t is \"%C\"\n", arabic);
fwprintf(f,L"wprintf - arabic wchar_t is \"%C\"\n", arabic);
wprintf(L"wprintf - literal arabic character is \"%C\"\n",L'ت');
fwprintf(f,L"wprintf - literal arabic character is \"%C\"\n",L'ت');
wprintf(L"wprintf - literal arabic character in string is \"م\"\n\n");
fwprintf(f,L"wprintf - literal arabic character in string is \"م\"\n\n");
fclose(f);
return 0;
}
Выходной файл
printf - literal arabic character is "م"
printf - char* string is "ايه الاخبار"
wprintf - literal english char is "t"
wprintf - unicode wchar_t is "�"
wprintf - unicode number wchar_t is ","
wprintf - arabic wchar_t is "("
wprintf - literal arabic character is "*"
wprintf - literal arabic character in string is ""
Я использую Windows 10, Notepad ++ и MinGW.
Edit Это было отмечено как дубликат Light C Unicode Library, но я не думаю, что это действительно отвечает на мой вопрос. Я загрузил библиотеку и посмотрел, и вы можете назвать меня глупым, если хотите, но я действительно новичок в программировании, и я не понимаю большую часть кода в библиотеке, поэтому мне трудно работать как я могу использовать его, достигая того, чего хочу. Я искал библиотеку для функции печати и не смог найти ее...
Я просто хочу сохранить символ UTF-8, а затем распечатать его снова! Мне действительно нужно установить всю библиотеку для этого? Я просто очень признателен, если кто-то пожалеет меня и расскажет мне в детстве, как я могу это сделать... Люди продолжают говорить, что я должен использовать uint_32 или что-то вместо wchar, - но как мне потом напечатать эти типы данных? Могу ли я сделать это с помощью wprintf?!