iomanip意外地影响ctime函数输出

时间:2016-01-07 01:11:48

标签: c++

我的目标是使用<iomanip>设置50个左右的空格宽度,并<ctime>打印日期和时间,但是这样做<iomanip>不能按预期工作。我以同样的方式使用<iomanip>,输出字符,用于以前的输出,它工作正常,所以我不确定我现在做错了什么。

// Example program
#include <iostream>
#include <string>
#include <ctime>
#include <iomanip>

using namespace std;

void dateTime(){
    time_t now = time(0);
    tm* dt = localtime(&now);
    cout << setfill(' ') << setw(56) << left << 1900 + dt->tm_year << "/" << 1 + dt->tm_mon << "/" << dt->tm_mday << ", " << dt->tm_hour << ":" << dt->tm_min << " |" << endl;
  }

int main()
{
  dateTime();
}

输出我得到(不正确):

2016                                                    /1/6, 17:36 |

预期输出(正确):

2016/1/6, 17:36                                                     |

2 个答案:

答案 0 :(得分:1)

问题是std::setw仅影响一个输出的字段宽度,而不影响构成您关注的日期/时间的整个输出组。幸运的是,该标准提供了一种非常简洁的方法来处理问题:std::put_time操纵器创建一个包含您关注的字段的结果,因此使用它,您可以将输出格式化为:

// Example program
#include <iostream>
#include <string>
#include <ctime>
#include <iomanip>

using namespace std;

void dateTime() {
    time_t now = time(0);
    tm* dt = localtime(&now);

    std::cout << std::setw(56) << std::put_time(dt, "%Y/%m/%d, %H:%M") << "|";
}

int main()
{
    dateTime();
}

...产生这样的输出:

2016/01/06, 17:48                                                       |

答案 1 :(得分:0)

您可以定义自己的ignore_manipulator流对象,以防止从iomanip操纵输出。这是我在vrm_core, one of my C++14 libraries中的实现。

剥离实施:

struct ignore_manipulator
{
    std::string _str;

    ignore_manipulator(const std::string& str) 
        : _str(str) 
    { 
    }

    auto& operator=(const std::string& str)
    {
        _str = str;
        return *this;
    }

    operator const T&() const noexcept
    {
        return _str;
    }

    auto begin() const noexcept
    {
        return std::begin(_str);
    }

    auto end() const noexcept
    {
        return std::end(_str);
    }
};

template <typename T>
auto operator<<(std::ostream& o, const ignore_manipulator& im)
{
    // `o.put` ignores manipulators.
    for(const auto& c : im) o.put(c);
    return o;
}

用法示例:

// "hello" won't be affected by previous manipulators.
cout << setfill(' ') << setw(56) << ignore_manipulator("hello") << "\n";