6

Привет!
Есть таблица некоторых строковых переменных (string). Необходимо эту таблицу вывести в адекватном форматированном виде. Проблема заключается в том, что при использовании манипулятора setw () строки, разные по длине, занимают разную ширину поля, а не фиксированную.

#include <string>
#include <iostream>
#include <iomanip>

using namespace std;

int main ()
{
  string one = "Один", two = "Два", eight = "Восемь";
  cout << setw (10) << one <<endl;
  cout << setw (10) << two <<endl;
  cout << setw (10) << eight <<endl;
  return 0;
}

Ожидаемый вывод:

  один
   два
восемь

Что выходит на самом деле:

  один
    два
восемь

Собственно вопрос - почему так? И как всё таки можно выводить строки выровненными - одну под другой?

ixSci
  • 23,825
The Cat
  • 115

1 Answers1

7

Эх. Судя по всему, это проблемы интернационализации и utf-8.

Дело в том, что C++ не знает об utf-8, и считает ширину поля в байтах, а не в реальных символах. А для utf-8 количество байт не равно количеству символов. Обратите внимание, что у вас ширина поля получилась не 10, а меньше — текст "Один" в utf-8 занимает больше четырёх байт, поэтому количество недостающих до 10 байт меньше.

Попробуйте перейти на широкие строки:

wstring one = L"Один", two = L"Два", eight = L"Восемь";
wcout << setw (10) << one << endl;
wcout << setw (10) << two << endl;
wcout << setw (10) << eight << endl;

Если вы работаете под Windows, вам придётся прибегнуть к небольшой акробатике, чтобы заставить консоль правильно понимать широкие строки. Под линуксом, кажется, достаточно в начале программы применить заклинание

setlocale(LC_ALL, "");

Заметьте, что консольный ввод/вывод приложения должен быть либо полностью «узкий», либо полностью «широкий»: переключиться после первого выведенного символа уже нельзя.

VladD
  • 206,799
  • На широких строках вывод действительно происходит форматированным, но состоит усключительно из вопросительных знаков – The Cat Nov 26 '15 at 17:26
  • Хм. А какая ОС? И какой компилятор? – VladD Nov 26 '15 at 17:30
  • Kubuntu (14.04), g++ – The Cat Nov 26 '15 at 17:32
  • И gcc? Я-то думал, у линукса этих проблем мету :-\ – VladD Nov 26 '15 at 17:32
  • Сейчас гляну, что можно сделать. – VladD Nov 26 '15 at 17:33
  • 1
    @TheCat: А если добавить в начало программы setlocale (LC_ALL,"");? – VladD Nov 26 '15 at 17:34
  • Так вот где собака зарыта. setlocale я писал всегда, но вторым аргументом я указывал не пустые кавычки, а совал туда "rus" локаль, так как считал, что "" принимает локаль системную и не сможет мне помочь. Спасибо за то, что ткнули носом (= – The Cat Nov 26 '15 at 17:39
  • 1
    @TheCat: То есть, сработало? Аргумент в локали означает «системная локаль вот такая». А пустая строка означает «само выясняй, я не знаю точно». – VladD Nov 26 '15 at 17:41
  • Да, сработало.
    Кстати, проблем с utf-8 изначально действительно не было. Но через некоторое время, с приходом некоторого обновления или с приходом мною установленной библиотеки, появились проблемы с кириллицей в написанном мною коде. Так что, с gnu компилятором, я думаю, всё нормально, чего не скажешь о моих руках (=
    – The Cat Nov 26 '15 at 17:46
  • @TheCat: ... или со стандартом :-\ Он мог измениться, а gcc-то что, обязан поддерживать. – VladD Nov 26 '15 at 17:48