std::setfill и std::setw для входных потоков?

Рассмотрим этот код:

int xx;
std::cin >> std::setfill('0') >> std::setw(4) >> xx;

При отправке 12 на стандартный ввод я ожидаю, что значение xx будет 1200, а при отправке 12345 я ожидаю, что оно будет 1234.

Однако кажется, что std::setfill и std::setw не действуют, и я получаю 12 и 12345 соответственно.

Это баг или так по стандарту? Есть ли хороший способ получить ожидаемую функциональность?

Также обратите внимание, когда я меняю тип xx на std::string, std::setw вступает в силу, а std::setfill все еще нет.

Мой компилятор gcc-7.0.1.


person Vahagn    schedule 01.03.2017    source источник
comment
Может быть, я пропустил это. С каких это пор std::setfill поддерживается в операциях с потоком input? Я знаю, что std::setw есть, но теперь std::setfill тоже???   -  person WhozCraig    schedule 01.03.2017
comment
нет, это неправильный код.   -  person Richard Hodges    schedule 01.03.2017
comment
Я не думаю, что std::setfill поддерживается во входном потоке. en.cppreference.com/w/cpp/io/manip/setfill   -  person Shravan40    schedule 01.03.2017
comment
xx получит любое введенное вами значение. Вам нужно показать, что вы делаете с ним потом, и это можно отформатировать   -  person Eyal K.    schedule 01.03.2017
comment
Тот факт, что приведенный выше код компилируется, как бы узаконивает мотивацию иметь желаемую функциональность.   -  person Vahagn    schedule 01.03.2017


Ответы (2)


Согласно стандарту C, setfill относится к выходному потоку. Что касается setw, то он работает для входного потока при использовании вместе с char* или string. Например, следующая программа выводит abcd для входной строки abcdef1234 для 123456):

string a;
cin >> setw(4) >> a;
cout << a;
person lukeg    schedule 01.03.2017

setw и setfill применяются не так универсально.

Похоже, вы хотите имитировать эффект форматирования данного ввода в столбце фиксированной ширины, а затем перечитать его. Библиотека предоставляет инструменты именно для этого:

int widen_as_field( int in, int width, char fill ) {
    std::stringstream field;
    field << std::setw( width ) << std::setfill( fill );
    field << std::setiosflags( std::ios::left );
    field << in;
    int ret;
    field >> ret;
    return ret;
}

Демо.

Однако эта функция не будет обрезать 12345 до 1234. Это потребует еще одного преобразования через string.

person Potatoswatter    schedule 01.03.2017
comment
Это безумно неэффективно, поскольку дважды преобразует цифры в int. - person Chaoran; 29.11.2018