Вывод в консоль cout и wcout одновременно
Тебя где-то справшивали о том, как с этим жить? Вопрос был об устройстве вывода и причинах по которым файлы приобретают ориентацию. Твою блеяние мимо вообще. Ну и потом — твоя ссылка туфта, ибо http://eel.is/c++draft/iostream.objects.overview#6, а C library говорит:
After a stream is associated with a file, but before any operations are performed on the stream, the stream is without orientation. If a wide-character input or output function is applied to a stream without orientation, the stream becomes wide-oriented. Likewise, if a byte input or output operation is applied to a stream with orientation, the stream becomes byte-oriented. Thereafter, only the fwide() or freopen() functions can alter the orientation of a stream. Byte input/output functions shall not be applied to a wide-oriented stream and wide-character input/output functions shall not be applied to a byte-oriented stream.
Слышал, only the fwide() or freopen() functions can alter the orientation of a stream, нет там ничего про способ полоумного анонима с лора.
pavlick ★★
( 31.05.21 08:18:57 MSK ) автор топика
Раз уж тему сделал, смежный вопрос к адекватным участникам: многие клавиши на клаве генерят эскейп последовательности (на уровне io потоков), заметил, что последовательности нестандартизированны вообще никак, нажатие F5 под VT даёт 4 символа, под иксовым ST 5 символов. Как в общих чертах нужно интерпретировать эти последоввательности (видимо терминфо?), может название функции, которой можно последовательность дать. Странно, почему в этой области не появилось никакого стандарта.
pavlick ★★
( 31.05.21 08:32:56 MSK ) автор топика
Ответ на: комментарий от pavlick 31.05.21 08:32:56 MSK
Странно, что ты ещё до сих пор не забанился.
LamerOk ★★★★★
( 31.05.21 09:51:16 MSK )
в теории «высокоуровневые средства упрощают написание кода»
anonymous
( 31.05.21 10:08:08 MSK )
Токсичная среда. Участников, от которых можно получить ценный совет можно по пальцам пересчитать. С остальными история про бисер. Ок, банюсь.
pavlick ★★
( 31.05.21 10:50:17 MSK ) автор топика
Не уверен, что верно понял вопрос, но выскажу мнение. К сожалению, wcout устарел после появления utf-8. В Linux терминалы либо понимают utf-8 и тогда надо использовать cout и string с utf-8, либо понимают только ASCII.
Если надо, чтобы программа работала ещё и в Windows, то там установленный по умолчанию растровый шрифт не умеет в юникод. Можно хитрить с настройками шрифта, и получить относительно нормальный вывод через wcout, но ввод останется кривой. Для себя я пришёл к выводу, что и в Windows надо использовать string с utf-8, а при вводе-выводе его транслировать в однобайтную текущую кодировку через MultiByteToWideChar, WideCharToMultiByte и GetConsoleCP. Возможно, в десятке что-то улучшилось, но мой подход и там работает.
ncurses используется в линуксовых терминалах, поэтому не ясно для чего там wcout. По идее, там тоже должен быть utf-8, а значит только cout. А локаль устанавливается, чтобы запятую для отделения десятичного знака использовать. Но тут могу ошибаться.
Kogrom ★
( 31.05.21 22:30:39 MSK )
Ответ на: комментарий от Kogrom 31.05.21 22:30:39 MSK
chcp 65001 же, utf-8 nls
Старые венды конечно в пролёте, да
mittorn ★★★★★
( 01.06.21 01:05:40 MSK )
Ответ на: комментарий от Kogrom 31.05.21 22:30:39 MSK
mittorn , Kogrom
и забыть о проблеме на всех Windows начиная с Windows XP.
fsb4000 ★★★★★
( 01.06.21 01:12:45 MSK )
Ответ на: комментарий от fsb4000 01.06.21 01:12:45 MSK
mittorn ★★★★★
( 01.06.21 08:40:26 MSK )
Ответ на: комментарий от Kogrom 31.05.21 22:30:39 MSK
К сожалению, wcout устарел после появления utf-8.
Он не устарел. Широкие символы — это абстракция над символом, которая может вместить любой символ целиком. Конечно и здесь есть грабли в виде, например, диакритических символов — в итоге на один символ уйдет более одного wchar_t, но всё равно — каждый wchar_t будет представлять полный code point.
В Linux терминалы либо понимают utf-8 и тогда надо использовать cout и string с utf-8, либо понимают только ASCII.
Это не так работает. В том то и дело — мне вообще не надо заморачиваться по поводу кодировки локали. Я просто читаю с stdin, а libc сама конвертируют в эту абстракцию wchar_t, без разницы что там koir-8, utf или windows 1251 ( в программе нужно установить локаль сначала std::locale::global(locale(«»)) ). Я не говорю, что всё надо делать через wchar_t, как вариант.
ncurses используется в линуксовых терминалах, поэтому не ясно для чего там wcout. По идее, там тоже должен быть utf-8, а значит только cout.
Ну логично исользовать массив с константного размера ячейками, когда мэпишь его на экран, а не массив массивов под переменный utf. Хотя и тут проблемы с теме же диакритическими символами. Вообще юникод пошёл по какому-то странному пути, много лучше было не позволять никаких комбинированнх символов, разное начертание — другая code point. 150К символов в юникоде, utf-8 может закодить грубо 2млрд, неужели нельзя было обойтись без комбинированных символов? А в качестве вишенки всучили ещё precomposed characters для разных вариантов написания одинакового. По-моему, что-то пошло не так.
anonymous
( 01.06.21 08:47:56 MSK )
Ответ на: комментарий от pavlick 31.05.21 08:32:56 MSK

Почему миксовать не получается? В общем хочется деталей для понимания.
Насколько я понимаю, это напрямую связано с наличием внутреннего состояния потоков. Например, если состояние многобайтное, то его нельзя или трудно интерпретировать как юникодное.
Ну если так, то я не могу после ncurses (которая широкая внутренне) печатного цикла использовать cout и мне нужно переоткрывать stdout как пишут в доках. Кто-нибудь не согласен?
ncurses может и не использовать стандартные потоки, либо сделать их копию и использовать её. Стандарт же говорит о потоках, а не файлах, на которые они указывают.
Как в общих чертах нужно интерпретировать эти последоввательности (видимо терминфо?), может название функции, которой можно последовательность дать.
База terminfo сопоставляет последовательности с операциями и наоборот. Есть какие-то стандарты (упоминаются в 1, 2), но вообще всё сложно.
xaizek ★★★★★
( 01.06.21 19:58:29 MSK )
Ответ на: комментарий от fsb4000 01.06.21 01:12:45 MSK
Мы обсуждаем разновидности костылей. Можно выбрать любые по вкусу. Более здоровым подходом будет использование mintty вместо консоли по умолчанию. Так делает git. Но тут придётся таскать с собой дополнительные 4 мегабайта.
Kogrom ★
( 01.06.21 21:22:14 MSK )
Ответ на: комментарий от anonymous 01.06.21 08:47:56 MSK
Широкие символы — это абстракция над символом, которая может вместить любой символ целиком.
Я согласен и был бы рад, если бы wchar_t победил. Но победил utf.
В теории. А на практике есть терминалы, которые будет выводить непонятно что, если использовать для символа больше одного байта. И не важно, wchar_t или utf-8 у нас будет. Другие будут ожидать, что wchar_t содержит 4 байта, а не 2. Поэтому в Linux остаётся выбирать адекватный терминал и пользоваться uft-8.
Думаю оно так, потому что создатели этой системы сами ей не пользуются. Но нас это устраивает. Иначе бы придумали какую-нибудь РУТФ-8, в которой русские буквы находятся среди первых 128 символов, и терминалы, которые это понимают.
А в качестве вишенки всучили ещё precomposed characters для разных вариантов написания одинакового.
Недавно ради интереса попробовал реализовать 64-битный растровый шрифт. В картинку 8 на 8 влез любой символ с клавиатуры. Размер png на 180 клеток вышел 2,9 килобайт. То есть можно ужать если не до 16 бит, то до 32 точно. Вот вам и кодировка в лоб без всяких комбинаций.
Были ещё такие штуки, как 16-сегментные индикаторы, с помощью которых можно было создать любую латинскую букву и почти все кириллические, кроме Ё, Ц, Щ (их тоже можно, но будет нечитаемо). Правда, это касается только заглавных букв. Но в 32 сегмента можно и маленькие вместить. Возможно, даже несколько бит на цвет останется.
Kogrom ★
( 01.06.21 21:59:59 MSK )
Ответ на: комментарий от xaizek 01.06.21 19:58:29 MSK
ncurses может и не использовать стандартные потоки, либо сделать их копию и использовать её.
Использует те же, проверял. Копию не делает, но и ориентацию потоку не задает никакую, видимо из-за использования низкоуровневых write() и друзей. В общем-то проще на всякий случай перед каждой инициализацией/деиниц вызывать (на винде работать не будет):
freopen(nullptr, "r", stdin); freopen(nullptr, "w", stdout); freopen(nullptr, "w", stderr);
Стандарт же говорит о потоках, а не файлах, на которые они указывают.
И с файлами та же история, у них тоже ориентация, которая задётся при первой записи через высокоуровневый интерфейс, склонен думать, что дело именно в конверсии между широкими символами и локалью силами libc.
anonymous
( 02.06.21 01:01:41 MSK )
Мне тут ещё вот чего захотелось — сделать какой-то трейс для софтины, но не так, что после кор дампа или в отладчике, а программа чтобы отработала и в процессе скидывала в файл каждый вызов/выход и функции. Погуглил, несколько готовых вариантов не завелись, накостылил даже свой, работает на основе -finstrument-functions, получаю на выходе вроде такого:
begin initscr b newterm b new_prescr end new_prescr b newterm_sp b _nc_setupterm b _nc_setup_tinfo b _nc_read_entry b _nc_pathlast e _nc_pathlast b _nc_first_db .
меня бы это даже устроил даже не смотря на то, что запускаю под отладчиком и задаю размер таблицы в .dynsym секции руками там же (так не въехал как его узнать иначе). Но есть большой косяк — поделка ище имена символ в таблице экспорта (компилю с -rdynamic), но static функции в данную таблицу не попадают. Может есть готовое решение моей хотелки без данного недостатка?
одновременная работа с std::wcout и std::cout
Когда wcout/cout вызывается впервые, устанавливается определенная ориентация stdout (стандартный поток вывода). В случае cout поток становится однобайтно-ориентированным, а в случае wcout поток становится ориентированным на широкоформатные символы. Согласно стандарту C++ [27.4.1] и стандарту С [7.19.2] (C11 [7.21.2]), однажды установив ориентацию stdout нельзя вызывать функции несовместимые с установленной ориентацией.
Отслеживать
ответ дан 16 авг 2018 в 5:36
1,756 1 1 золотой знак 6 6 серебряных знаков 10 10 бронзовых знаков
Как и было сказано одновременно печатать с разными форматами нельзя. Но. Можно закрыть поток и открыть. Этим редко кто занимается.
# include # include int main()
Отслеживать
ответ дан 16 авг 2018 в 6:13
17.2k 1 1 золотой знак 9 9 серебряных знаков 33 33 бронзовых знака
- c++
- utf-8
- вывод
- кириллица
-
Важное на Мете
Похожие
Подписаться на ленту
Лента вопроса
Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.
Дизайн сайта / логотип © 2024 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2024.1.3.2953
Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.
Обработка строк в C++/WinRT
С помощью C++/WinRT можно вызывать интерфейсы API среды выполнения Windows, используя типы широких строк стандартной библиотеки C++, такие как std::wstring (но не типы узких строк, такие как std::string). В C++/WinRT имеется настраиваемый строковый тип winrt::hstring (определенный в базовой библиотеке C++/WinRT — %WindowsSdkDir%Include\\cppwinrt\winrt\base.h ). Этот строковый тип фактически принимают и возвращают конструкторы, функции и свойства среды выполнения Windows. Но, во многих случаях благодаря конструкторам преобразования hstring и операторам преобразования можно выбирать, следует ли учитывать hstring в коде клиента. Если вы разрабатываете интерфейсы API, вероятность того, что вам нужно знать о hstring, возрастает.
В C++ существует множество строковых типов. Различные варианты существуют во множестве библиотек в дополнение к std::basic_string из стандартной библиотеки C++. В С++17 имеются служебные программы для преобразования строк и std::basic_string_view, чтобы заполнить пробелы между всеми строковыми типами. Тип winrt::hstring дает возможность преобразования с помощью std::wstring_view для обеспечения взаимодействия, для которого был создан std::basic_string_view.
Использование std::wstring (и, при необходимости, winrt::hstring) с Uri
public: Uri(winrt::hstring uri) const;
Но hstring имеет конструкторы преобразования, позволяющие работать с ним, не учитывая этот факт. Ниже приведен пример кода, показывающий, как создать Uri из литерала широкой строки, представления широкой строки и std::wstring.
#include #include using namespace winrt; using namespace Windows::Foundation; int main() < using namespace std::literals; winrt::init_apartment(); // You can make a Uri from a wide string literal. Uri contosoUri< L"http://www.contoso.com" >; // Or from a wide string view. Uri contosoSVUri< L"http://www.contoso.com"sv >; // Or from a std::wstring. std::wstring wideString< L"http://www.adventure-works.com" >; Uri awUri< wideString >; >
Метод доступа к свойству Uri::Domain имеет тип hstring.
public: winrt::hstring Domain();
// Access a property of type hstring, via a conversion operator to a standard type. std::wstring domainWstring< contosoUri.Domain() >; // L"contoso.com" domainWstring = awUri.Domain(); // L"adventure-works.com" // Or, you can choose to keep the hstring unconverted. hstring domainHstring< contosoUri.Domain() >; // L"contoso.com" domainHstring = awUri.Domain(); // L"adventure-works.com"
public: hstring ToString() const;
Uri реализует интерфейс IStringable.
// Access hstring's IStringable::ToString, via a conversion operator to a standard type. std::wstring tostringWstring< contosoUri.ToString() >; // L"http://www.contoso.com/" tostringWstring = awUri.ToString(); // L"http://www.adventure-works.com/" // Or you can choose to keep the hstring unconverted. hstring tostringHstring< contosoUri.ToString() >; // L"http://www.contoso.com/" tostringHstring = awUri.ToString(); // L"http://www.adventure-works.com/"
Можно использовать функцию hstring::c_str для получения стандартной широкой строки из hstring (так же, как и из std::wstring).
#include std::wcout
Если у вас есть hstring, значит, вы можете получить Uri.
Uri awUriFromHstring< tostringHstring >;
Рассмотрим метод, который принимает hstring.
public: Uri CombineUri(winrt::hstring relativeUri) const;
Все параметры, которые мы рассмотрели, также применяются в таких случаях.
std::wstring contact< L"contact" >; contosoUri = contosoUri.CombineUri(contact); std::wcout
Для hstring имеется член-оператор преобразования std::wstring_view, и преобразование осуществляется без дополнительных затрат.
void legacy_print(std::wstring_view view); void Print(winrt::hstring const& hstring)
Функции и операторы winrt::hstring
Для winrt::hstring реализован ряд конструкторов, операторов, функций и итераторов.
Тип hstring является диапазоном, поэтому вы можете использовать его с основанным на диапазоне for или с std::for_each . Он также предоставляет операторы сравнения для естественного и эффективного сравнения с его аналогами в стандартной библиотеке C++. Кроме того, он включает в себя все, что необходимо для использования hstring в качестве основы для ассоциативных контейнеров.
Мы понимаем, что многие библиотеки C++ используют std::string и работают только с текстом UTF-8. Для удобства мы предоставляем вспомогательные методы, такие как winrt::to_string и winrt::to_hstring, для двустороннего преобразования.
WINRT_ASSERT — это макроопределение, которое передается в _ASSERTE.
winrt::hstring w< L"Hello, World!" >; std::string c = winrt::to_string(w); WINRT_ASSERT(c == "Hello, World!"); w = winrt::to_hstring(c); WINRT_ASSERT(w == L"Hello, World!");
Дополнительные примеры и сведения о функциях и операторах hstring приведены в справочных материалах по API winrt::hstring.
Обоснование для winrt::hstring и winrt::param::hstring
Среда выполнения Windows реализуется в знаках wchar_t, но двоичный интерфейс приложения (ABI) среды выполнения Windows не является подмножеством того, что предоставляют std::wstring или std::wstring_view. Их использование приведет к значительной неэффективности. Вместо этого C++/WinRT предоставляет winrt::hstring, представляющий собой неизменяемую строку, согласованную с базовым HSTRING и реализованную за интерфейсом, аналогичным std::wstring.
Можно заметить, что входные параметры C++/ WinRT, которые логически должны принимать winrt::hstring, фактически ожидают winrt::param::hstring. Пространство имен param содержит набор типов, используемых исключительно для оптимизации входных параметров для естественной привязки к типам стандартной библиотеки C++, а также позволяющих избежать копий и других аспектов, снижающих эффективность. Эти типы не следует использовать напрямую. Если вы хотите использовать оптимизацию для собственных функций, применяйте std::wstring_view. Также см. статью о передаче параметров в интерфейс ABI.
Идея состоит в том, что вы можете по большей части игнорировать особенности управления строками среды выполнения Windows и просто эффективно работать с тем, что вам известно. Это важно, учитывая, насколько активно строки используются в среде выполнения Windows.
Форматирование строк
Одно из средств форматирования строк — std::wstringstream. Вот пример, который форматирует и отображает простое сообщение отладочной трассировки.
#include #include #include . void MainPage::OnPointerPressed(winrt::Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e) < winrt::Windows::Foundation::Point const point< e.GetCurrentPoint(nullptr).Position() >; std::wostringstream wostringstream; wostringstream
Правильный способ задать свойство
Для установки свойств значение передается в функцию задания. Приведем пример.
// The right way to set the Text property. myTextBlock.Text(L"Hello!");
Ниже приведен неправильный код. Компиляция происходит, но все, что выполняется — это изменение значения winrt::hstring, возвращаемое функцией получения доступаText(), а затем результаты отклоняются.
// *Not* the right way to set the Text property. myTextBlock.Text() = L"Hello!";
Важные API
- Структура winrt::hstring
- Функция winrt::to_hstring
- Функция winrt::to_string
Wcout c что это
как заставить wcout выводить текст в консоли в местных кодировках (например иврит и арабский)?
Максимум пока чего добился что выводит иероглифы какие то (но явно не то что надо). а то раньше и этого не делал.
Тумаров Александр ( AlexTAI )
alextai3@yahoo.com
Re: wcout и различные кодировки
| От: | Bell |
| Дата: | 20.03.03 14:50 |
| Оценка: |
Здравствуйте, AlexTAI, Вы писали:
ATA>как заставить wcout выводить текст в консоли в местных кодировках (например иврит и арабский)?
ATA>Максимум пока чего добился что выводит иероглифы какие то (но явно не то что надо). а то раньше и этого не делал.
Нужно правильно настроить locale.
Посмоти в MSDN по слову locale.
Любите книгу — источник знаний (с) М.Горький
Re[2]: wcout и различные кодировки
| От: | AlexTAI | alextai.narod.ru |
| Дата: | 20.03.03 14:53 | |
| Оценка: |
Здравствуйте, Bell, Вы писали:
B>Нужно правильно настроить locale.
B>Посмоти в MSDN по слову locale.
Дык не без этого. смотрел но что то ничего путного там не нашлось.
Пробовал через imbue и через setlocale(и через юникодовый вариант тоже) но что то ничего не вышло. Конечно возможно что я их неправильно юзал.
Вот то что было в употребелении:
_wsetlocale( LC_ALL, L"Hebrew" ); SetConsoleOutputCP(1255); std::wcout.imbue(std::locale("he")); std::wcout.imbue(std::locale("hebrew"));
все это пробовалось и по одиночке и в разных комбинациях.
Тумаров Александр ( AlexTAI )
alextai3@yahoo.com
Re: wcout и различные кодировки
| От: | Диагностик |
| Дата: | 21.03.03 03:17 |
| Оценка: |
Здравствуйте, AlexTAI, Вы писали:
ATA>как заставить wcout выводить текст в консоли в местных кодировках (например иврит и арабский)?
ATA>Максимум пока чего добился что выводит иероглифы какие то (но явно не то что надо). а то раньше и этого не делал.
На самом деле, люди не читают газеты, они принимают их каждое утро, так же как ванну. ©Маршалл Мак-Льюэн