Какие манипуляторы iomanip являются «липкими»?

130
задан Benjamin Christoffersen 12 July 2018 в 16:26
поделиться

3 ответа

Важные примечания из комментариев ниже:

Мартин:

@Chareles: Тогда по этому требованию все манипуляторы являются липкими. За исключением setw, который, кажется, сбрасывается после использования.

Чарльз:

Совершенно верно! и единственная причина, по которой setw, похоже, ведет себя иначе, заключается в том, что существуют требования к операциям форматированного вывода для явного .width (0) потока вывода.

Ниже приводится обсуждение, которое приводит к приведенному выше выводу:


Глядя на В коде следующие манипуляторы возвращают объект, а не поток:

setiosflags
resetiosflags
setbase
setfill
setprecision
setw

Это обычный метод применения операции только к следующему объекту, который применяется к потоку. К сожалению, это не мешает им быть липкими. Тесты показывают, что все они, кроме setw , липкие.

setiosflags:  Sticky
resetiosflags:Sticky
setbase:      Sticky
setfill:      Sticky
setprecision: Sticky

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

[no]boolalpha
[no]showbase
[no]showpoint
[no]showpos
[no]skipws
[no]unitbuf
[no]uppercase

dec/ hex/ oct

fixed/ scientific

internal/ left/ right

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

ws/ endl/ ends/ flush

Вывод состоит в том, что setw кажется единственным манипулятором в моей версии, который не является липким.

Для Чарльза простой трюк, влияющий только на следующий элемент в цепочке:
Таким образом, любая информация о состоянии, которую они изменяют, должна быть записана в объект потока и, таким образом, является постоянной (до тех пор, пока другой манипулятор не изменит состояние). Таким образом, следующие манипуляторы должны быть липкими манипуляторами.

[no]boolalpha
[no]showbase
[no]showpoint
[no]showpos
[no]skipws
[no]unitbuf
[no]uppercase

dec/ hex/ oct

fixed/ scientific

internal/ left/ right

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

ws/ endl/ ends/ flush

Вывод состоит в том, что setw кажется единственным манипулятором в моей версии, который не является липким.

Для Чарльза простой трюк, влияющий только на следующий элемент в цепочке:
Таким образом, любая информация о состоянии, которую они изменяют, должна быть записана в объект потока и, таким образом, является постоянной (до тех пор, пока другой манипулятор не изменит состояние). Таким образом, следующие манипуляторы должны быть липкими манипуляторами.

[no]boolalpha
[no]showbase
[no]showpoint
[no]showpos
[no]skipws
[no]unitbuf
[no]uppercase

dec/ hex/ oct

fixed/ scientific

internal/ left/ right

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

ws/ endl/ ends/ flush

Вывод состоит в том, что setw, кажется, единственный манипулятор в моей версии, который не является липким.

Для Чарльза простой трюк, влияющий только на следующий элемент в цепочке:

[no]boolalpha
[no]showbase
[no]showpoint
[no]showpos
[no]skipws
[no]unitbuf
[no]uppercase

dec/ hex/ oct

fixed/ scientific

internal/ left/ right

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

ws/ endl/ ends/ flush

Вывод состоит в том, что setw кажется единственным манипулятором в моей версии, который не является липким.

Для Чарльза простой трюк, влияющий только на следующий элемент в цепочке:

[no]boolalpha
[no]showbase
[no]showpoint
[no]showpos
[no]skipws
[no]unitbuf
[no]uppercase

dec/ hex/ oct

fixed/ scientific

internal/ left/ right

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

ws/ endl/ ends/ flush

Вывод состоит в том, что setw, кажется, единственный манипулятор в моей версии, который не является липким.

Для Чарльза простой трюк, влияющий только на следующий элемент в цепочке:
Вот пример того, как объект можно использовать для временного изменения состояния, а затем вернуть его обратно с помощью объекта:

#include <iostream>
#include <iomanip>

// Private object constructed by the format object PutSquareBracket
struct SquareBracktAroundNextItem
{
    SquareBracktAroundNextItem(std::ostream& str)
        :m_str(str)
    {}
    std::ostream& m_str;
};

// New Format Object
struct PutSquareBracket
{};

// Format object passed to stream.
// All it does is return an object that can maintain state away from the
// stream object (so that it is not STICKY)
SquareBracktAroundNextItem operator<<(std::ostream& str,PutSquareBracket const& data)
{
    return SquareBracktAroundNextItem(str);
}

// The Non Sticky formatting.
// Here we temporariy set formating to fixed with a precision of 10.
// After the next value is printed we return the stream to the original state
// Then return the stream for normal processing.
template<typename T>
std::ostream& operator<<(SquareBracktAroundNextItem const& bracket,T const& data)
{
    std::ios_base::fmtflags flags               = bracket.m_str.flags();
    std::streamsize         currentPrecision    = bracket.m_str.precision();

    bracket.m_str << '[' << std::fixed << std::setprecision(10) << data << std::setprecision(currentPrecision) << ']';

    bracket.m_str.flags(flags);

    return bracket.m_str;
}


int main()
{

    std::cout << 5.34 << "\n"                        // Before 
              << PutSquareBracket() << 5.34 << "\n"  // Temp change settings.
              << 5.34 << "\n";                       // After
}


> ./a.out 
5.34
[5.3400000000]
5.34
83
ответ дан 24 November 2019 в 00:12
поделиться

Причина того, что width не кажется «липким», заключается в том, что определенные операции гарантированно вызывают .width (0) в выходном потоке. Это:

21.3.7.9 [lib.string.io]:

template<class charT, class traits, class Allocator>
  basic_ostream<charT, traits>&
    operator<<(basic_ostream<charT, traits>& os,
               const basic_string<charT,traits,Allocator>& str);

22.2.2.2.2 [lib.facet.num.put.virtuals]: все do_put перегрузки для num_put шаблон. Они используются перегрузками оператора << , принимающими basic_ostream и встроенный числовой тип.

22.2.6.2.2 [lib.locale.money.put.virtuals] : Все перегрузки do_put для шаблона money_put .

27.6.2.5.4 [lib.ostream.inserters.character]: Перегрузки оператора << беря basic_ostream и один из типов char экземпляра basic_ostream или char , signed char или unsigned char или указатели на массивы этих типов char.

Честно говоря, я не уверен в обосновании этого, но никаких других состояний ostream должен быть сброшен функциями форматированного вывода. Конечно, такие вещи, как badbit и failbit , могут быть установлены в случае сбоя в операции вывода, но этого следовало ожидать.

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

Например

std::cout << std::setw(6) << 4.5 << '|' << 3.6 << '\n';

"   4.5     |   3.6      \n"

Чтобы «исправить» это потребует:

std::cout << std::setw(6) << 4.5 << std::setw(0) << '|' << std::setw(6) << 3.6 << std::setw(0) << '\n';

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

std::cout << std::setw(6) << 4.5 << '|' << std::setw(6) << 3.6 << '\n';
30
ответ дан 24 November 2019 в 00:12
поделиться

setw () влияет только на следующую вставку. Именно так ведет себя setw () . Поведение setw () такое же, как ios_base :: width () . Я получил информацию о setw () с cplusplus.com .

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

cout.width(6);
cout << right << "a" << endl;
cout.width(6);
cout << "b" << endl;
cout.width(6);
cout << "c" << endl;

даст вам

>     a
>     b
>     c

, а

cout.width(6);
cout << right << "a" << endl;
cout << "b" << endl;
cout << "c" << endl;

даст вам

>     a
>b
>c

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

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

Resetiosflags ведет себя аналогично setiosflags , за исключением того, что он сбрасывает указанные флаги.

setbase устанавливает базу целых чисел, вставленных в поток (таким образом, 17 в базе 16 будет «11», а в базе 2 будет «10001»).

setfill устанавливает символ заполнения для вставки в поток, когда используется setw .

setprecision устанавливает десятичную точность, которая будет использоваться при вставке значений с плавающей запятой.

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

6
ответ дан 24 November 2019 в 00:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: