Использование различных спецификаторов формата c в Stack Overflow

Как и в c мы можем использовать различные спецификаторы формата, такие как

  • % й где n — число, чтобы вывести число с общим количеством не менее n пробелов
  • % 0nd То же, что и выше, за исключением предварительного заполнения нулями «% 05d», 3 => 00003
  • % .nf установить точность n после десятичной
  • так далее ….

Так есть ли способ использовать их с станд :: соиЬ ?

Я получил некоторые отрицательные отзывы в недавнем курсе (c ++ для c программистов) в Coursera, для использования Printf вместо соиЬ потому что я хотел немного форматирования 🙁

4

Решение

За %nd %0nd, Эквиваленты C ++ std::setw() а также std::setfill(),

#include <iostream>     // std::cout, std::endl
#include <iomanip>      // std::setfill, std::setw

int main () {
std::cout << std::setfill ('x') << std::setw (10);
std::cout << 77 << std::endl;
return 0;
}

Выход: xxxxxxxx77

%.nf можно заменить на std::setprecision а также std::fixed,

#include <iostream>     // std::cout, std::fixed, std::scientific

int main () {
double a = 3.1415926534;
double b = 2006.0;
double c = 1.0e-10;

std::cout.precision(5);

std::cout << "fixed:\n" << std::fixed;
std::cout << a << '\n' << b << '\n' << c << '\n';
return 0;
}

Выход:

fixed:
3.14159
2006.00000
0.00000
4

Другие решения

Поток C ++s не используют спецификаторы формата, такие как C printf()функции типа; они используют manipulators.

Например:

#include <iostream>
#include <iomanip>int main()
{
std::cout << std::fixed << std::setprecision(6) << 42.0 << std::endl;
}

Выход:

42.000000

Смотри, беги!

5

Обычное решение в C ++ состоит в том, чтобы определить манипуляторы, которые утверждают
что вы пытаетесь отформатировать, а не взламывать физические значения
прямо в точке выхода. (Одним из возможных исключений является
ширина, где std::setw может быть полезным непосредственно.) Таким образом, для
Например, когда вы выводите что-то, вы не будете указывать
заполнение нулями, или фиксированное, с двумя десятичными знаками, но что-то вроде:

std::cout << temperature(2) << theTemporature;

где temperature будет что-то вроде:

class temperature
{
int myMinWidth;
public:
temperature( int minWidth )
: myMinWidth( minWidth )
{
}
friend std::ostream& operator<<( std::ostream& dest, temperature const& manip )
{
dest.setf( std::ios_base::fixed, std::ios_base::floatfield );
dest.precision( 2 );
dest.width( myMinWidth );
return dest;
}
};

Список доступных модификаций формата см. В
спецификация std::ios_baseи поля
std::ios_base::fmtflags,

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

class StateSavingManip
{
public:
void operator()( std::ios& stream ) const;
protected:
StateSavingManip() : myStream( nullptr ) {}
~StateSavingManip();
private:
virtual void setState( std::ios& stream ) const = 0;
private:
mutable std::ios* myStream;
mutable std::ios::fmtflags mySavedFlags;
mutable int mySavedPrec;
mutable char mySavedFill;
};

реализация:

namespace {
int getXAlloc() ;
int ourXAlloc = getXAlloc() + 1 ;

int
getXAlloc()
{
if ( ourXAlloc == 0 ) {
ourXAlloc = std::ios::xalloc() + 1 ;
assert( ourXAlloc != 0 ) ;
}
return ourXAlloc - 1 ;
}
}

StateSavingManip::~StateSavingManip()
{
if ( myStream != nullptr ) {
myStream->flags( mySavedFlags ) ;
myStream->precision( mySavedPrec ) ;
myStream->fill( mySavedFill ) ;
myStream->pword( getXAlloc() ) = NULL ;
}
}

void
StateSavingManip::operator()(
std::ios&           stream ) const
{
void*&              backptr = stream.pword( getXAlloc() ) ;
if ( backptr == nullptr ) {
backptr      = const_cast< StateSavingManip* >( this ) ;
myStream     = &stream ;
mySavedFlags = stream.flags() ;
mySavedPrec  = stream.precision() ;
mySavedFill  = stream.fill() ;
}
setState( stream ) ;
}

Обратите внимание на использование pword поле, чтобы гарантировать, что только первый
временный манипулятор восстанавливает формат; деструкторы будут
называться в обратном порядке построения, но в порядке
конструкция, как правило, не будет указана, если у вас есть больше
чем один такой манипулятор в выражении.

Наконец: не все возможно с использованием этой техники: если вы
хочу систематически добавлять знак градуса к температуре,
нет способа сделать это. В этом случае вам нужно определить
Температура класса, и перегрузка << оператор для него; этот
позволяет все мыслимое (гораздо больше, чем вы могли когда-либо
достичь с printf стиль форматирования).

4

C ++ потоковые манипуляторы (iomanip) были специально разработаны для поддержки всех стандартных операций спецификаторов формата c, только с совершенно другим интерфейсом. Например. setfill а также setw для ширины и заполнения части %02d,

Конечно, если вам действительно нужны строки формата (например, потому что это облегчает i18n), то вам следует взглянуть на boost::formatи если у вас есть C ++ 11, то вы можете легко написать вокруг него небольшую переменную оболочку шаблона, чтобы вызов формата был больше похож на printf.

Что бы вы ни делали, пожалуйста, старайтесь не использовать printf. Он не безопасен для типов и не расширяется для операций вывода для пользовательских типов.

2

Есть потоковые манипуляторы, если они вам нужны.
Но я думаю, что вы хотите знать эту вещь:
cout умнее чем printf(),
Скажем, у вас есть:

int x = 34;
cout<<x;

Теперь компилятор вызовет:

ostream& operator<<(ostream& stream, int arg);

для тебя. И эта функция будет печатать вывод в консоли (так как в вашем случае stream является cout). Стандартная библиотека предоставляет перегрузки для этого << оператор для всех основных типов данных.

1
По вопросам рекламы [email protected]