как обрезать ширину целых типов с помощью std :: ostringstream?

Скажем, у вас есть что-то вроде:

std::ostringstream oss;
int value(42);
oss.fill('0');
oss << std::setw(3) << value;
cout << oss.str();

ВЫХОД: 042

Этот вывод связан с тем, что std :: setw обеспечивает минимальную ширину, и мы сказали потоку заполнить 0, однако как сделать наоборот и указать максимальную ширину, чтобы отображение было усечено в STL и нативном C ++, предпочтительно ...

В настоящее время у меня есть кое-что, что я считаю уродливым и неэффективным взломом:

std::ostringstream oss;
int value(1239999);
oss.fill('0');
oss << std::setw(3) << boost::lexical_cast<std::string, int>(value).substr(0, 3);
cout << oss.str();

ВЫХОД: 123

Я посмотрел на boost :: format, но там та же история, насколько я могу судить, нет способа сделать это "красиво" ... есть предложения?

ОБНОВЛЕНИЕ: потоки std :: ostringstream и STL в целом, как известно, работают медленно по сравнению с другими контейнерами и объектами шаблонов STL. Возможно, мне было бы лучше создать объект очереди сообщений, который обертывает и внутренне использует std :: queue, а затем просто использует sprintf_s для целей форматирования?


person AJG85    schedule 15.12.2010    source источник
comment
Как может быть правильным, что "123" является правильным представлением как 123, так и 1239999? Если это правда, я не думаю, что у вас вообще есть целые числа.   -  person SingleNegationElimination    schedule 16.12.2010
comment
это простое представление вне контекста, чтобы прояснить проблему ... при фактическом использовании значение представляет собой доли секунды объекта времени posix, регистрируемого как часть метки времени для записи, которая в большинстве операционных систем является неточной после трех цифр, тратит пространство и затрудняет чтение журнала.   -  person AJG85    schedule 17.12.2010


Ответы (2)


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

Что-то типа:

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

void First3( std::ostream & os, int value ) {
    std::ostringstream oss;
    oss.fill('0');
    oss << std::setw(3) << value;
    os << oss.str().substr( 0, 3 );
}

int main() {
    First3( std::cout, 1239999 );
    std::cout << " ";
    First3( std::cout, 1 );
}

Обратите внимание, что использование Boost не требуется.

person unquiet mind    schedule 15.12.2010
comment
это чисто для форматирования отображения долей секунд в библиотеке журналов. Он используется только в одном месте, но это место активно используется, поэтому я обеспокоен производительностью предлагаемого взлома, хотя он еще не оказался проблематичным. boost уже широко используется в наших приложениях, и в этом случае itoa поддерживается не на всех платформах, так что это лучше. - person AJG85; 17.12.2010

Усечение для удаления значащих цифр не одобряется большинством современных программистов. В старые плохие времена форматирования FORTRAN было довольно распространено получать такие выходные данные, как

Total Sales
-----------
9,314,832.36
1,700,328.04
*,***,***,**
8,314,159.26
...

Даже современный Excel попадает в эту ловушку с индикатором переполнения ширины поля ########.

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

person wallyk    schedule 15.12.2010
comment
Раньше у нас была эта проблема с COBOL: передавать значение через цепочку программ, не иметь достаточного количества девяток в 9(x)V99 в одной программе, получать правдоподобно плохое значение. - person David Thornley; 16.12.2010
comment
Усечение связано с тем, что время posix, которое я использую для библиотеки журналов, переводит дробные секунды до 6+ цифр, когда окна и большинство часов ОС имеют точность только до 1/60 секунды или около 3 цифр ... это также экономит место в журнале. - person AJG85; 17.12.2010
comment
Если цель состоит в том, чтобы просто удалить лишнюю точность, то арифметически удалите лишние цифры, умножив их на степень десяти, усекая до целого числа и разделив на такую ​​же степень десяти. Есть вероятность, что это может не сработать из-за пониженной точности с плавающей запятой, но метод усечения строки будет работать эффективно, пока известна величина числа. - person wallyk; 17.12.2010