@popov654
Специалист в области веб-технологий

Как реализовать кроссплатформенную поддержку Unicode в аргументах командной строки в C?

Я пишу CLI для библиотеки шифрования. Сама библиотека работает на уровне байтов, однако я хочу, чтобы у пользователя была возможность передавать исходные строки и ключи, содержащие символы Unicode (кроме латиницы и цифр) через командную строку. Соответственно, мне нужно конвертировать массив wchar_t в массив char перед шифрованием, а после дешифровки выполнять обратную конвертацию.

При этом я знаю, что на Windows и Linux консоль использует разные кодировки (UTF-16/UTF-32). Насколько я знаю, функция wprintf() может об этом позаботиться сама, но мне нужен способ выполнять конвертацию в обе стороны.

Я поменял сигнатуру функции main() на int main(int argc, wchar_t* argv[]) (пытался исправлять на wmain, но тогда ругается ld и сборка падает с ошибкой). Также в её коде поменял функции сравнения и добавил к литералам префикс L.

Для конвертации wchar_t* в char* я пробовал использовать функцию wcstombs, однако почему-то у меня она совершенно не работает (при попытке преобразовать строку, содержащую только латиницу, я получаю null). Что касается обратного преобразования - я вообще не знаю, как его можно сделать.

Подскажите, пожалуйста, где можно об этом почитать.

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

input = (char*) malloc(wcslen(argv[1]) * 4 + 1);
wcstombs(input, argv[1], wcslen(argv[1]) * 4);
printf("The converted string is \"%s\"\n", input);
  • Вопрос задан
  • 151 просмотр
Решения вопроса 1
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
Соответственно, мне нужно конвертировать массив wchar_t в массив char перед шифрованием, а после дешифровки выполнять обратную конвертацию.

Этот вывод не следует из исходных данных. Массив данных любого типа может быть проинтерпретирован как массив байтов, без какой бы то ни было конверсии. Т.е. исходные данные в любом формате можно зашифровать, а потом расшифровать обратно. Поэтому имеет смысл отделить преобразование форматов входных данных от шифрования/расшифровки.

Я поменял сигнатуру функции main() на int main(int argc, wchar_t* argv[]) (пытался исправлять на wmain, но тогда ругается ld и сборка падает с ошибкой).

То, что ты меняешь прототип main, никак не влияет на то, как она будет реально вызвана. В стандарте языка C написано, каким может быть прототип main: int main(void), int main(int argc, char *argv[]) или эквивалентным. Там же написано, что набор символов во время выполнения программы -- implementation defined, поэтому нет гарантии, что их можно обработать кросплатформенно.

Для конвертации wchar_t* в char* я пробовал использовать функцию wcstombs, однако почему-то у меня она совершенно не работает (при попытке преобразовать строку, содержащую только латиницу, я получаю null).

wcstombs не занимается выделением памяти, если ты "получаешь null" -- это происходит в каком-то другом месте. Ну и если ты это делаешь внутри main принимающего wchar_t* argv[], то твой код интерпретирует строку char как строку wchar_t, что добавляет хаоса.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
mayton2019
@mayton2019
Bigdata Engineer
Тебе проще всего посмотреть как эта задача уже решена в других Windows/Linux проектах.
Я думаю что ты тут не первооткрыватель. Уже решали эту задачу миллион раз.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы