Выровняйте символы, отличные от UTF-8, при печати на С++

Я пытаюсь найти общее решение, которое можно использовать для выравнивания текста слева и справа от указанной ширины строки.

Примечание: текст может быть практически на любом международном языке, английском, японском, китайском и т. д.

i.e

  std::wstring str1 = L"Hello1";
  std::wstring str2 = L"Hello2";
  std::cout << std::string(50, '-') << endl;
  std::wcout << std::left << std::setw(25) << str1 << std::right << std::setw(25) << str2 << std::endl;

Производит следующее:

--------------------------------------------------
Hello1                                      Hello2

Строка «----» имеет ширину 50 символов (без учета новой строки), а две строки «Hello1» и «Hello2» выровнены по левому и правому краю.

Но проблема в следующем:

  std::wstring str1 = L"Hello1";
  std::wstring str2 = L"Hello2";
  std::wstring str3 = L"こんにちは";
  std::wstring str4 = L"你好";

  std::cout << std::string(50, '-') << endl;
  std::wcout << std::left << std::setw(25) << str1 << std::right << std::setw(25) << str2 << std::endl;
  std::wcout << std::left << std::setw(25) << str3 << std::right << std::setw(25) << str4 << std::endl;
  std::cout << std::left << std::setw(25) << "こんにちは" << std::right << std::setw(25) << "你好" << std::endl;

Что производит следующее:

--------------------------------------------------
Hello1                                      Hello2
S�kao                                           `}
こんにちは                             你好
  • Я безуспешно пытался найти способ выровнять третий ряд вправо, идеи?
  • Я не понимаю, почему вторая строка представлена ​​​​как «мусор», есть идеи, как исправить эту строку без каких-либо серьезных изменений?

person Henrik    schedule 11.02.2020    source источник
comment
Вы перепутали строки UTF16, UTF8 и ASCII. string и std::string используются для текста UTF8 или ASCII. Текстовые литералы UTF8 используют префикс u8. Для UTF16 правильный тип — u16string. wstring и L предназначены для двухбайтовых строк, которые являются подмножеством UTF16. Таким образом, L"こんにちは" — это двухбайтовая строка, а "こんにちは" — это просто строка ASCII, которая не может представлять ни один из этих символов.   -  person Panagiotis Kanavos    schedule 11.02.2020
comment
В вашем заголовке написано, что это не UTF-8. Есть ли особая причина, по которой вы не хотите использовать UTF-8? Вы используете строковые литералы в своем примере. Убедитесь, что кодировка исходного файла, кодировка компилятора и кодировка, которую вы используете при печати, совпадают (и, пожалуйста, сообщите нам, какие кодировки вы используете). И последнее, но не менее важное: вы, кажется, упускаете из виду, что символы и wchars в многобайтовых строках являются кодовыми точками для многобайтовых символов, которые могут иметь размер от 1 до 4 байтов. Вы хотите подсчитать многобайтовые символы, а затем использовать их в setw.   -  person Max Vollmer    schedule 11.02.2020
comment
Проверьте строку и символ литералы. Поскольку вы хотите использовать UTF8, вы должны использовать префикс u8 во всех строковых литералах. Обратите внимание, что C++20 вводит типы char8_t и u8string, чтобы избежать путаницы между ASCII и UTF8.   -  person Panagiotis Kanavos    schedule 11.02.2020
comment
Как только вы задействуете Unicode, такие вещи, как align, станут действительно сложными. Это не вина Unicode. Он охватывает все языки мира, и их великое множество. Вы видите это в кодовых точках Unicode Right-to-Left (RTL) и Left-to-Right (LTR). Они напрямую влияют на выравнивание   -  person MSalters    schedule 11.02.2020