【问题标题】:how to truncate width of integral types with std::ostringstream?如何使用 std::ostringstream 截断整数类型的宽度?
【发布时间】:2010-12-15 20:11:50
【问题描述】:

假设你有类似的东西:

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,但据我所知,这是同一个故事,没有办法“漂亮”地做到这一点......有什么建议吗?

更新:与 STL 的其他容器和模板对象相比,通常已知 std::ostringstream 和 STL 流执行缓慢。也许我最好制作一个消息队列对象,该对象包装并在内部使用 std::queue,然后仅使用 sprintf_s 进行格式化?

【问题讨论】:

  • "123"1231239999 的正确表示到底怎么可能是正确的?如果这是真的,我认为你根本就没有整数。
  • 这是一个脱离上下文的简单表示,以使问题清晰......在实际使用中,该值表示 posix 时间对象的小数秒,该对象被记录为不准确条目的时间戳的一部分在大多数操作系统上超过 3 位数,浪费空间,并使日志更难阅读。

标签: c++ stl format width ostringstream


【解决方案1】:

大多数现代程序员“不赞成”截断以删除有效数字。在 FORTRAN 格式化的糟糕日子里,得到像这样的输出是很常见的

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

即使是现代的 Excel 也陷入了这个陷阱,其字段宽度溢出指示为 ########

如果输出的数字不适合字段宽度,当前的理念是打破字段宽度的边界并可靠地显示值。唯一的缺点是如果 FORTRAN 程序要读取输入(因此需要严格的列使用)。

【讨论】:

  • 我们曾经在使用 COBOL 时遇到过这样的问题:通过一系列程序传递一个值,在一个程序中的 9(x)V99 中没有足够的 9,得到一个看似合理的错误值。跨度>
  • 截断是因为当 Windows 和大多数操作系统时钟仅精确到 1/60 秒或大约 3数字...它还可以节省日志中的空间。
  • 如果目标只是去除多余的精度,则通过乘以十的幂、截断为整数并除以十的相同幂来算术去除多余的数字。由于浮点精度降低,有可能无法正常工作,但只要知道数字的大小,字符串截断方法就会有效。
【解决方案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。

【讨论】:

  • 它纯粹是为了在日志库中显示小数秒的格式。它只在一个地方使用,但那个地方被大量使用,这就是为什么我担心提议的 hack 的性能,尽管它还没有被证明是有问题的。 boost 已经在我们的应用程序中广泛使用,在这种情况下,并非所有平台都支持 itoa,所以这更好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-17
  • 2020-12-29
  • 1970-01-01
  • 1970-01-01
  • 2019-09-03
  • 1970-01-01
相关资源
最近更新 更多