Как стать автором
Обновить

Комментарии 49

Вроде бы это в C++23 обещали починить и:

std::println("Привет, мир!");

без дополнительный действий со стороны программиста в Windows консоли напечатает нужный текст, так как C++ runtime определит с чем соединен stdout и вызовет, если нужно SetConsoleOutputCP(CP_UTF8); самостоятельно.

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

https://en.cppreference.com/w/cpp/io/vprint_unicode

On Windows, the stream refers to a terminal if the expression GetConsoleMode(_get_osfhandle(_fileno(stream))) returns nonzero (see Windows documentation for GetConsoleMode, _get_osfhandle, and _fileno). The native Unicode API on Windows is WriteConsoleW.

И новый std::println соотвественно будет использовать "vprint_unicode".

Я об этом узнал на cppcon: https://youtu.be/eD-ceG-oByA?t=4925

Собственно ваш пост — хорошее объяснение, почему в первой главе учебника по С++ стараются использовать ASCII.

Вы не могли бы развернуть немного подробнее? Хотя бы в двух словах. Ваше утверждение может подразумевать десяток различных вещей. А мне хотелось бы конкретики.

А чего тут разворачивать? Вам целую статью написать пришлось чтобы рассказать как обойти грабли совместимости. При том, что обычный ASCII хелловорлд пишется строки в четыре. И на этапе обучения, когда хелловорлд актуален, важнее рассказать о типах данных, ветвлениях, алгоритмическом мышлении. А не о глюках различных ОС.


Кстати о глюках, совет использовать msvs вреден: приходится отдельной строчкой приказывать тамошнему компилятору придерживаться стандарта, а не навязывать свои псевдо-безопасные strcmp_s и подобные функции.


Плюс не забывайте о локализации: если уж вы хотите использовать в своей программе не международный язык, имеет смысл сразу же рассказать про локализацию. Что в исходном коде все сообщения так и так пишутся на английском, а переводы подкладываются отдельно. Ну и соответственно как именно эти переводы сгенерировать, куда подложить и как потом подцепить. Не говоря даже об уважении к пользователю, которому может быть сложно читать на казахском языке, бывают и проблемы с терминалом. Вы вон сами воткнулись в кодировку cp1251 / 866, которая русские буквы не отображает. А так указали бы локаль LC_ALL="C", и весь интерфейс переключился бы на английский. Не очень удобно, но хоть понятно. Да, из соображений переносимости лучше не SetOutputCP + SetConsoleOutputCP делать, а system("chcp 65001");. В других ОС этих windows-специфичных функций нет, соответственно программа просто не соберется. А system просто ругнется что программа chcp не найдена — и продолжит работать дальше. Впрочем, еще лучше все же обернуть в #ifdef, но это уже гораздо больше кода, да и знаний потребует.

Для обучения я думаю использовать только первый блок кода в статье, который технически ничем не отличается от «обычного ASCII хелловорлда», как вы его назвали. Можно было бы остановиться на нем.

Этот пример создаёт ложное впечатление, что программа может работать с кириллицей так же понятно, как и с латиницей. Под Linux это ещё более-менее может работать, там почти все перешли на utf-8. Но под Windows нет. Запишем что-нибудь в файл, получаем проблемы с кодировками. Попытаемся открыть файл с кириллицей в названии через std::filesystemпроблемы с кодировками. Попытаемся зачем-нибудь вызывать WinAPI — снова надо не UTF-8, а что-то другое.

В начале статьи говорите о том, какие все плохие, не показывают юникод в новичковых курсах, а после показываете 100500 способов вывести смайлик в консоль, из которых переносимых между системами, дайте посчитать….

…ноль.

Я дартаньян, вы все пи…, вот вам пугало, смотрите, любуйтесь!

Не смешно самому?

Не-не, я не считаю никого плохим, отнюдь )). Один способ кроссплатформенный я привел.

Вы про какой? Я вижу кроссплатформенные только в смысле "написали один код на C++". А дальше чтобы он корректно отработал надо плясать с бубном на каждой конкретной системе, среде разработке, компиляторе и подбирать ключи компиляции и настройки терминала.

Если у нас есть возможность зафорсировать одну ОС (и выкинуть либо людей с macOS, либо наоборот, либо выкинуть вообще всех, потребовав Linux) и среду разработки — то пожалуйста. Но если есть хоть какое-то разнообразие, то настройка даже одного компилятора — уже достаточное развлечение.

Я согласен, что идеальная кроссплатформенность (для всех операционных систем) невозможна. В статье речь шла про Windows 10 и дистрибутив «Ubuntu» Linux. Использованные при этом компиляторы и ключи описаны в статье.

русскоязычному ученику было бы удобнее и интереснее (это важно!) писать первые программы, выводящие сообщения на русском языке и, к примеру, с эмодзи. Особенно, если речь идет об обучении детей. 

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

Главная цель этой статьи — показать, что обучать программированию на языке C++ можно, сразу начав работу в кодировке UTF-8

Можно, но не нужно. Учебники не дураки пишут.

Согласен с вами, эту статью нельзя использовать в качестве первого урока. Но эта статья изначально написана для тех, кто начинает учить, а не для тех, кто начинает учиться. Ученику на первом уроке достаточно дать код из первого блока кода в статье и сказать о том, что для текстов сейчас используют кодировку UTF-8, поэтому и ему тоже стоит ее использовать для исходного кода.

Чтобы сказать "используй кодировку UTF-8", у человека сначала в голове должна быть концепция "кодировка" как таковая. И навыки для того чтобы проверить какая кодировка используется в открытом файле и как ее изменить, если там выставлено не то что нужно.

Есть разные методы обучения. Например, ученик может сначала просто делать то, что ему говорит учитель, даже не понимая смысла. Главное - показать получение результата. Вы учите ученика работать с выбранным редактором кода, показываете, как там настроить нужную кодировку, как изменить кодировку имеющегося файла и т.д. На первых уроках можно не углубляться, что такое кодировка и какие они бывают вообще. В следующих уроках ученику постепенно и взаимосвязанно с другими темами раскрывается смысл действий и понятий. При таком способе ученику не нужно ничего знать заранее, он узнает о деталях позже.

Второй способ - сначала по максимуму погрузиться в тему, о том, что такое кодировка, как устроены компьютеры, что такое организация ЭВМ, как работает память и процессор, история языков программирования от машинного кода и ассемблера до Python и других высокоуровневых языков, что такое абстракции, платформы, история операционных систем и так далее. Это называется комплексным подходом и практикуется в университетах.

Оба способа хорошие и дадут результат, если правильно взяться.

Второй способ ... практикуется в университетах.

В итоге, когда учащиеся доходят до программирования, то их либо уже не стало (потеря + неразвитие мотивации), либо уже забыли зачем им на первой лекции минут 5 объясняли, что там есть биты-байты, и как там компьютер абы как это в памяти хранит.

Устойчивых реляционных связей между предметами не возникает, нету на это времени и пока неясна, скажем, высокоуровневая структура, запомнить детали будет практически невозможно. А детали становятся интересны именно тогда, когда есть понимание для чего они требуются и где применимы.

Вы описали две крайности, первая - зачастую видная в интернете: статьи обрезки, пошаговые руководства типа "сделай так и будет щастье", индусские копирайтеры в т. ч. Второй: закопаться и не выбраться. Хорошие книги пытаются между ними балансировать. Статьи -- реже (возьмем скопом как плохой пример -- все техническо-прикладные статьи из блогов компаний на Хабре).

Поэтому в гробу я видел второй подход (см. предпредыдущий абзац). А первый у меня лишь с презрением ассоциируется, человек пусть и бестолково, но что-то делает и интерес не теряется.

Сам, признаюсь, из-за систематичного подхода, начинаю слишком часто с bottom-up approach, на это уходит чрезмерно много усилий и времени. Я замечаю, как это не окупается. Пример: выбрать между несколькими альтернативами, это значит потратить минут по 15 на каждый мануал/доку, ни черта не понять, а потом таки начать щупать (первый подход). Это может и работает с физическими вещами, но не софтом, где стоимость пробы может равняться нулю.

Согласен с тем, что можно обучать, балансируя между двумя подходами. Мне кажется, можно в каждом конкретном случае исходить из того, что ученик уже знает (если обучение один на один). Я не хочу углубляться здесь в дискуссию о способах обучения. Я лишь хотел подчеркнуть, что UTF-8 для начинающих с первого урока - это возможно (по-моему, даже необходимо).

Не вижу никаких противоречий или каких-то революционных находок. Очень подходит для таких случаев волшебная фраза: "Сейчас мы с вами просто сделаем так как показано в примере, а чуть позже, когда у вас появится понимание сути вопроса, мы вернемся к этому примеру и разберемся почему мы сделали именно так, какие еще варианты доступны и пр."

Насчет wchar_t и эмодзи, тут я не разбираюсь, но по-моему работать это может, при определенных обстоятельствах и должной поддержке. Вот тут об emoji in SMS: UCS-2 vs UTF-16

Основываясь же на своем предыдущем комментарии, теперь уже после прочтения подчеркну, что забраться в такие дебри... а оно нужно ли? Тем важнее вопрос, на каком уроке? Если первом то у меня бы (как начинающего), наверно голова вспухла ещё до вывода строки. Но при цели поддержки Uncode, без головоломки flat vs wide character + 8-bit ASCII vs UTF-8/UTF-16 (насчитываем, грубо, четыре варианта) невозможно будет обойтись, из-за требований к типам в Win32 API.

С другой стороны, конечно, всякие `C:\Users\Илья\Рабочий стол\урок cpp 1\`

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

В windows можно вызвать setlocale(LC_ALL, ".UTF8") в самом начале программы. Это переведёт стандартную библиотеку на utf-8.

мы ищем опытного C++ девелопера. английский и опыт с linux обязателен. работа удаленная. вопросы шлите сюда: raymond@dcmsys.com

по-моему в С можно просто писать printf("что угодно, включая символы хекскодами") и программа просто зашлет эти байты в консоль, а та уже пусть и разбирается что там за кодировка. Зачем все эти пляски именно внутри программы?
Я заходя в статью думал тут про работу со строками — как порезать, не попав между байтами одного символа например. А вывод в консоль у меня работал по умолчанию еще в 90-х.

Ну вот и попробуйте просто записать в консоль строку с русскими буквами на винде, увидите как она разберётся...

Я под виндой использую цигвиновскую консоль — в ней всё выводится без проблем.
Вы хотите учить детей на родном языке, чтоб им было понятнее, но при этом до того как они смогут вывести хоть что-то, им придется понять что такое кодировка и нахрена они разные для одного языка в одной системе?
Возмите линукс — там утф8 из коробки везде — можно делать вывод на любом языке без прелюдий.

То есть ошибка — в 9 строке исходного кода, в которой определен строковый литерал. Строковый литерал с приставкой «L» не может содержать символ эмодзи ? (U+1F60E), как уже было объяснено выше. Насколько я понимаю, код символа ? (U+1F60E) обрезается так, чтобы символ влез в строку «широких» символов, в итоге получается не то, что ожидалось.

Неа, ошибка тут в стандартной библиотеке, которая рассматривает символ U+1F60E, состоящий из двух whar_t, как два отдельных символа.

Языку 50 лет - а без танцев с бубнами не обойтись

Зачем героически создавать самим себе и не менее героически преодолевать трудности, сначала используя для обучения систему, в которой нет сквозной кодировки символов, потом набирать программу в GUI, а потом её результаты смотреть в консоли?

В Windows можно добавить к исполняемому файлу манифест с указанием использовать utf-8 в качестве активной кодовой страницы при запуске.

Это интересно. Я попробовал добавить внешний файл манифеста, а также включить файл манифеста в состав исполняемого файла с помощью mt.exe. Оба варианта у меня не сработали. В интернетах пишут, что требуется наличие свойства PreferExternalManifest в соответствующей ветке (ветках) реестра Windows 10. Это так? Вы пользовались этим способом, он у вас работал?

В принципе, это разновидность предварительного переключения активной кодовой страницы. Только вместо ручного переключения с помощью команд используется файл манифеста, насколько я понял. Есть еще вариант для PowerShell вставить переключение активной кодовой страницы в файл профиля пользователя.

Хм, действительно, на вывод не влияет. Извиняюсь, что ввёл в заблуждение.

В моём случае в недрах сторонней библиотеки использовалась WideCharToMultiByte с флагом CP_ACP. И в Powershell, настроенный на UTF-8, выводились кракозябры. Тут манифест помог.

Первая проблема с

std::cout << "Привет, мир!\n";

набранном в IDE, это отсутствие понимания в какой кодировке будет сохранён файл. И cp1251 в MSVC не единственный прикол. Например, MounRiver Studio может сохранить код в китайской 1-2 байтовой кодировке ?GBK? в которой есть и кириллица и греческий (забавно выглядит ситуация, когда файлы в этой кодировке попадают в github/gitlab).

Никто не обещает, что строки в исходном коде не поменяют кодировку при компиляции.

BOM-же является Windows-специфичным костылём. О котором лучше бы забыть и научиться настраивать кодировки в свойствах проекта. Но он действует. Как и пачка советов в https://www.cyberforum.ru/cpp-beginners/thread10662.html

Второй комплект проблем связан с самими учебными заданиями, которые перестают быть простыми для многобайтовых кодировок в С++. Как быть с задачами вида:

  • Найдите самое длинное слово.

  • Найдите в тексте слова палиндромы.

  • и т.п. задания где нужен посимвольный доступ.

И это без учёта того, что utf-8 - это уже не про символы, а про Code point. Мы приходим к тому, что, вроде как, нужны библиотеки для работы с Unicode-строками. И начинается много вопросов, как?

Каждый курс обрастает своими костылями и методами решений. Один преподаватель указывает кодировку в коде и вызывает паузу в конце работы программы. Другой преподаёт С++ в Linux, используя его пакетный менеджер для развёртывания среды.

Я был бы вам благодарен, если бы вы привели конкретный (код, если он короткий, или вместо кода ссылку) один пример задачи и ее решения, которые простые в имеющемся учебнике с ASCII, но станут сложными (или вообще не будут работать) при использовании литералов в кодировке UTF-8. (Я не сомневаюсь в существовании таких задач и в ваших словах вообще, но когда есть конкретный пример, то понятнее, о чем идет речь.)

Да хоть бы задача вывести строку задом наперед. Для ASCII это решается банальным циклом. Для wchar_t в общем-то тоже. Но вот для utf-8 уже надо ковырять формат юникода.


#include <stdio.h>
#include <wchar.h>
#include <locale.h>

int main(){
  setlocale(LC_ALL, "");
  wchar_t str[100];
  scanf("%ls", str);
  for(int i=wcslen(str)-1 ; i>=0; i--)printf("%lc", str[i]);
  printf("\n");
}

wchar_t на Windows использует UTF-16, в котором есть суррогатные пары. Так что при перевороте такой строки посимвольно можно получить невалидный юникод.

А еще мой пример с символами-модификаторами вроде ударения не работает. Даже в тех системах, где с юникодом отродясь проблем не было. Впрочем, с ними даже стандартный rev правильно не работает.


Пример-то как раз об этом, что юникод это ни разу не просто как ASCII.

Тут уже проблема с самой постановкой задачи, если не ограничиться кириллицей-латиницей. Я не уверен, что "вывести строку задом наперёд" имеет хоть какой-то смысл для арабской вязи, например. Или что не могут возникать новые графемные кластеры из подряд идущих code points в зависимости от версии Unicode.

Я не уверен, что "вывести строку задом наперёд" имеет хоть какой-то смысл для арабской вязи

Так смысл в любом случае учебный. Для арабского "наоборот" будет не справа налево, а слева направо.


Или что не могут возникать новые графемные кластеры из подряд идущих code points

Да тут бы со старыми разобраться!

Согласен, простой «разворот» байтов в строке в случае работы с UTF-8 «поломает» символы, которые не из таблицы ASCII. Но, мне кажется, можно сначала дать такое задание для символов из таблицы ASCII, а затем объяснить, почему это не сработает в случае кодировки UTF-8, это в качестве дополнительного урока. Можно написать программу, которая «расшифровывает» исходную и развернутую строки в числа (байты), чтобы ученику было понятнее. На выходе что-то вроде такого:

Hello, World!
48 65 6c 6c 6f 2c 20 57 6f 72 6c 64 21
!dlroW ,olleH
21 64 6c 72 6f 57 20 2c 6f 6c 6c 65 48

Привет, ?!
d0 9f d1 80 d0 b8 d0 b2 d0 b5 d1 82 2c 20 f0 9f 98 8e 21
!���� ,�ѵвиЀџ�
21 8e 98 9f f0 20 2c 82 d1 b5 d0 b2 d0 b8 d0 80 d1 9f d0

Тут видно, как в первом случае (символы из таблицы ASCII) разворот байтов работает, а во втором случае (есть символы и из ASCII, и не из ASCII) - не работает. По-моему, такой урок будет гораздо нагляднее, чем только с ASCII.

Рекурсивная функция для проверки, является ли слово палиндромом: https://www.cyberforum.ru/cpp-beginners/thread3071532.html

bool isPal(const string& str, int start, int end)
{
    if (start >= end)
        return true;
    if (str[start] != str[end])
        return false;
    return isPal(str, ++start, --end);
}

И на этом сайте можно найти достаточно много простых задач, которые задают студентам/школьникам.

Приведу обратный пример. Если надо работать с Unicode, то стандартной библиотеки мало. А внешние библиотеки могут потребовать определённых знаний и умений.

Пример: разбиение текста на предложения и слова используя ICU (не плохо о сегментации Unicode строк тут: https://habr.com/ru/articles/518900/):

#include <iostream>
#include <memory>

#include <unicode/brkiter.h>
#include <unicode/locid.h>
#include <unicode/unistr.h>
#include <unicode/ustream.h>
#include <unicode/utf.h>

void print_words(const icu::UnicodeString &str, const icu::Locale &locale)
{
    UErrorCode err = U_ZERO_ERROR;

    std::unique_ptr<icu::BreakIterator> breaker{
        icu::BreakIterator::createWordInstance(locale, err)};
    // TODO: check err;

    breaker->setText(str);
    int32_t first = breaker->first(), last;
    while ((last = breaker->next()) != icu::BreakIterator::DONE) {
        if (breaker->getRuleStatus() != UBRK_WORD_NONE) {
            std::cout << icu::UnicodeString(str, first, last - first) << '\t';
        }
        first = last;
    }
    std::cout << std::endl;
}

void print_sentences(const icu::UnicodeString &str, const icu::Locale &locale)
{
    std::cout << str << std::endl;
    UErrorCode err = U_ZERO_ERROR;

    std::unique_ptr<icu::BreakIterator> breaker{
        icu::BreakIterator::createSentenceInstance(locale, err)};
    // TODO: check err

    breaker->setText(str);
    int32_t first = breaker->first(), last;
    while ((last = breaker->next()) != icu::BreakIterator::DONE) {
        print_words(icu::UnicodeString(str, first, last - first), locale);
        first = last;
    }
    std::cout << std::endl;
}


int main()
{
    icu::Locale locale_rus{"ru_RU"};
    icu::Locale locale_china{"zh_CN"};

    auto hello =
        icu::UnicodeString::fromUTF8("Hello, World! Привет, мир! 你好世界! ?");

    auto poem = icu::UnicodeString::fromUTF8(  //
        "太乙近天都,"                         //
        "连山到海隅。"                         //
        "白云回望合,"                         //
        "青霭入看无。"                         //
        "分野中峰变,"                         //
        "阴晴众壑殊。"                         //
        "欲投人处宿,"                         //
        "隔水问樵夫。");

    print_sentences(hello, locale_rus);
    print_sentences(poem, locale_china);

    return 0;
}

Результат:

Hello, World! Привет, мир! 你好世界! ?
Hello	World	
Привет	мир	
你好	世界	


太乙近天都,连山到海隅。白云回望合,青霭入看无。分野中峰变,阴晴众壑殊。欲投人处宿,隔水问樵夫。
太乙	近	天	都	连	山	到	海隅	
白云	回	望	合	青	霭	入	看	无	
分野	中	峰	变	阴	晴	众	壑	殊	
欲	投	人	处	宿	隔水	问	樵夫

Сложнее, чем было? Намного? А по сравнению с другими языками программирования? Хочется более современный API?

Но всё это не отменяет возможности выводить сообщения на utf-8 в консоль с первых занятий, если есть такая возможность. Так или иначе С++ не должен быть первым языком программирования, и тогда небольшая порция информации по настройке окружения не должна смущать. Главное не давать задачи на обработку не ASCII строк в первых главах.

BOM-же является Windows-специфичным костылём.

BOM есть в RFC 3629

Вторая часть балета начнется, когда пользователь в этой консоли захочет ввести кириллицу.

Вы правы, в Windows 10 есть проблемы со считыванием из консоли символов, не входящих в таблицу ASCII, если мы работаем с кодировкой UTF-8. Например, возьмем простой код

#include <iostream>

int main()
{
    char str[100];
    std::cout << "Введите слово: "; std::cin >> str;
    std::cout << "Вы ввели: " << str << '\n';
    return 0;
}

Тестируем в консоли Windows 10:

C:\Users\Илья\source\repos\test>input
Введите слово: test
Вы ввели: test

C:\Users\Илья\source\repos\test>input
Введите слово: тест
Вы ввели:

Вместо русских букв (и любых не ASCII символов) std::cin возвращает нулевые байты.

С другой стороны, код приведенной выше простой программы успешно работает с любыми символами UTF-8 в Ubuntu (у меня через WSL), а также в веб-компиляторе «OnlineGDB.com». И даже в Windows (как видно из листинга выше) при обучении пояснительные надписи можно вывести на русском (что лучше, чем ничего), а ввод делать на латинице, параллельно продемонстрировав прекрасную работу этого же кода в Linux с любыми символами.

Хм, а msys в win7 нормально собирает:


user@user-w7 MSYS ~
$ cat main.c
#include <stdio.h>
#include <wchar.h>
#include <locale.h>

int main(){
  char str[100];
  scanf("%s", str);
  printf("[%s]\n", str);
}
user@user-w7 MSYS ~
$ gcc main.c

user@user-w7 MSYS ~
$ ./a.exe
ыеквртрвп
[ыеквртрвп]

Хотя у кросскомпилятора mingw проблемы. Но это, возможно, у меня старая версия.


P.S. Только что проверил — даже с mingw работает. Но ведь я точно помню, что были проблемы…
PPS. А, понял. Оно в cp1251 вводит. С выводом-то, понятно, проблем нет, а вот обработка кривая. А у msys — нормальная

Может быть, конечно, это будет сложно для новичка, но я бы лично ознакомил его сначала с пакетными менеджерами (и да, под Windows они тоже есть, Chocolatey, например), и, что самое на мой взгляд главное, компилятор бы посоветовал clang в связке MinGW. CMake, даже мне сейчас после простого Make, кажется сложным, особенно разница заметна в маленких проектах. Почему именно эти 2 компилятора? В принципе, сейчас нет большой разницы в поддержке библиотек, ведь есть CMake, однако, большинство вещей (например, флаги, формат библиотек, компоновщик) в MSVC сильно отличаются от других.

Для кириллицы в последнее время использую только этот способ:

Код
/* main.cpp */

#include <cstdio>
#include <fcntl.h>
#include <io.h>

/* ... */

namespace {
	class CodingChanger {                             
		public:                                       
			CodingChanger() {
                _setmode(_fileno(stdout), _O_U16TEXT);
                                          
                _setmode(_fileno(stdin), _O_U16TEXT); 
                                          
                _setmode(_fileno(stderr), _O_U16TEXT);
            }                    
                                                 
			~CodingChanger() {
                _setmode(_fileno(stdout), O_TEXT);    
                                          
                _setmode(_fileno(stdin), O_TEXT);     
                                          
                _setmode(_fileno(stderr), O_TEXT);  
            }                       
	} codingChangerInstance;
}

/* ... */

Почему именно эти 2 компилятора?

MSVC я взял, потому что работаю с Windows 10 (мне кажется логичным использовать для Windows компилятор Microsoft). А в Ubuntu я выбирал между GCC и Clang и в итоге выбрал GCC, так как у него стаж на 20 лет побольше (это значит, что документации и примеров в интернете должно быть больше, для начинающих это важно).

Для кириллицы в последнее время использую только этот способ

Ваш код, насколько я понял, предназначен для работы с широкими символами (wchar_t)? То есть подразумевается кодировка UTF-16 (или UCS-2)? В статье упор сделан на UTF-8, то есть предполагается работа с узкими символами (char). В Linux это работает без костылей, а в Windows, думаю, в будущем тоже будет работать. Они там, насколько я знаю, сейчас активно над этим трудятся.

MSVC я взял, потому что работаю с Windows 10 (мне кажется логичным использовать для Windows компилятор Microsoft).

Новичкам будет очень трудно с него переходить на кроссплатформенные системы сборки, в то время как сборка под MinGW и (или) clang сама на это вынуждает. Clang отлично сочетается с MinGW и у последнего Windows-специфичный инструментарий уже не хуже, чем у MSVC (конечно, исключая ATL и MFC, но кому они сейчас нужны). Кроме того, MSVC имеет собственный "диалект" C++ (ярким примером его использования являются 2 выше упомянутые библиотеки). Новичок хотя бы немного научится работать с конфигами, потом вручную настроит IDE и отладчик.

Хотя, мне это уже напоминает начало холивара, поэтому, давайте закончим:)

А в Ubuntu я выбирал между GCC и Clang и в итоге выбрал GCC

Такая связка потому, что она лично у меня стоит. Использую neovim как IDE с clangd (как я его называю, "помогатор", исходя из названия работает на clang'е) и vimspector'ом (отладчик).

P. S. Во всяком случае на Windows, Clang не имеет собственной реализации стандартной библиотеки языка C и STL и поэтому есть выбор между MSVC и MinGW.

На Linux же у clang'а вроде есть неведомые libc и, соответственно, libc++.

Ваш код, насколько я понял, предназначен для работы с широкими символами (wchar_t)?

Да, что-то бегло прочитал. Лично у меня кириллица в однобайтовой кодировке нигде никогда и не работала, я даже не знал, что ее можно "впихнуть" в UTF-8.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории