简体   繁体   English

对于 GCC <5,是否有 std::put_time 的内置替代方案?

[英]Is there a builtin alternative to std::put_time for GCC <5?

I'm stuck on GCC4.8 for the time being.我暂时被困在 GCC4.8 上。 I want to print out the current time as something other than seconds.我想将当前时间打印为秒以外的时间。 If put_time worked, my code would be something simple, like this:如果put_time有效,我的代码将很简单,如下所示:

std::cout << std::setw(24) << std::put_time(c_time, "[%T%z %F] ");

Without put_time , I'd have to access the elements of c_time manually and do all the formatting manually, which would be a pain in the a** and is something I'm much rather avoid if possible.如果没有put_time ,我必须手动访问c_time的元素c_time手动完成所有格式设置,这在 a** 中会很痛苦,如果可能的话,我宁愿避免这种情况。 Note that this does not mean that I never want to interact with C in any way, even indirectly -- I'd just like to avoid coding in C directly if possible.请注意,这并不意味着我永远不想以任何方式与 C 进行交互,甚至是间接的——如果可能的话,我只想避免直接使用 C 进行编码。

However, I can't find any alternatives to std::put_time , aside from strftime , which I'd like to avoid because it requires almost double the lines of code and is a lot harder to read, at least for me.但是,除了strftime之外,我找不到std::put_time任何替代方案,我想避免这种情况,因为它需要几乎两倍的代码行并且难以阅读,至少对我而言。 Also, this is C++, not C, so I'd like to steer clear of C functions whenever possible.此外,这是 C++,而不是 C,所以我想尽可能避开 C 函数。

Am I missing something?我错过了什么吗? Is there a builtin alternative to std::put_time which works under GCC 4.8?是否有在 GCC 4.8 下工作的std::put_time的内置替代方案?

Note that it doesn't have to work in exactly the same way -- if it, say, printed it directly to the output, rather than being a stream manipulator, that would be perfectly fine too, as would a function which returned a std::string containing the formatted time.请注意,它不必以完全相同的方式工作——比如说,如果它直接将它打印到输出,而不是作为一个流操纵器,那也完全没问题,就像一个返回std::string的函数一样std::string包含格式化的时间。

I've done a good bit of Googling and found <chrono> , but that doesn't work because it doesn't have anything to format the time automatically.我已经做了很多谷歌搜索并找到了<chrono> ,但这不起作用,因为它没有任何可以自动格式化时间的东西。 I'd still have to do it manually, and I'm pretty sure it would be more work, since I'd have to parse the number of seconds since the epoch into a year, month, day, etc.我仍然必须手动完成,而且我很确定这会有效,因为我必须将自纪元以来的秒数解析为年、月、日等。

There are no functions other than put_time for the outputing of time provided in the chrono or the iomanip library.有没有比其他功能put_time在规定的时间outputing chronoiomanip库。

The ctime library does provide: strftime , ctime , and asctime . ctime库确实提供: strftimectimeasctime

Since http://stackoverflow.com does not permit questions about finding 3 rd party libraries, I'm going to guess that you're just asking for someone to direct you on the use of strftime ?由于http://stackoverflow.com不允许有关查找 3 rd方库的问题,我猜您只是要求某人指导您使用strftime std::put_time(c_time, "[%T%z %F] ") could be written in the format: std::put_time(c_time, "[%T%z %F] ")可以写成以下格式:

char foo[24];

if(0 < strftime(foo, sizeof(foo), "[%T%z %F] ", c_time)) cout << foo << endl;

Also, this is C++, not C, so I'd like to steer clear of C functions whenever possible.此外,这是 C++,而不是 C,所以我想尽可能避开 C 函数。

That's a pretty silly mindset.这是一种非常愚蠢的心态。 put_time uses std::strftime underneath the hood. put_time使用std::strftime

ext.manip#10 ext.manip#10

Returns: An object of unspecified type ... where the function f is defined as:返回:未指定类型的对象......其中函数f定义为:

template <class charT, class traits>
void f(basic_ios<charT, traits>& str, const struct tm* tmb, const charT* fmt) {
  /* ... */
  typedef time_put<charT, Iter> TimePut;

  /* ... */
}

And time_put 's definition is in locale.time.put.virtuals#1 :time_put的定义在locale.time.put.virtuals#1 中

Effects: Formats the contents of the parameter t into characters placed on the output sequence s .效果:将参数t的内容格式化为放置在输出序列s上的字符。 Formatting is controlled by the parameters format and modifier, interpreted identically as the format specifiers in the string argument to the standard library function strftime() ...格式由参数格式和修饰符控制,解释为与标准库函数strftime()的字符串参数中的格式说明符相同...

Another solution is to rip off the definition of std::put_time from a later GCC's header, since the underlying facility std::time_put is still present in GCC 4.8 and the definition is not very complicated.另一个解决方案是从后来的 GCC 的头文件中std::put_time的定义,因为底层工具std::time_put仍然存在于 GCC 4.8 中,并且定义不是很复杂。 This is copied from GCC 7.4's <iomanip> and edited for clarity:这是从 GCC 7.4 的<iomanip>复制的,并为清晰起见进行了编辑:

#if __GNUC__ && __GNUC__ < 5
#include <ostream>  // std::basic_ostream
#include <ios>      // std::ios_base
#include <locale>   // std::use_facet, std::time_put
#include <iterator> // std::ostreambuf_iterator

template<typename CharT>
struct _put_time                   
{                                                                     
  const std::tm* time;
  const char *fmt;
};
    
template<typename CharT>
inline _put_time<CharT>
put_time(const std::tm* time, const CharT* fmt)
{ return { time, fmt }; }
  
template<typename CharT, typename Traits>
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits> &os, _put_time<CharT> f)
{   
  typedef typename std::ostreambuf_iterator<CharT, Traits> Iter;
  typedef std::time_put<CharT, Iter> TimePut;
      
  const CharT* const fmt_end = f.fmt + Traits::length(f.fmt);
  const TimePut& mp = std::use_facet<TimePut>(os.getloc());
    
  std::ios_base::iostate err = std::ios_base::goodbit;
  try {
    if (mp.put(Iter(os.rdbuf()), os, os.fill(), f.time, f.fmt, fmt_end).failed())
      err |= std::ios_base::badbit;
  }
  catch (...) {
    err |= std::ios_base::badbit;
  }  
   
  if (err)
    os.setstate(err);

  return os;
} 

#endif

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM