【问题标题】:Is Repeated Assignment Defined for get_time?是否为 get_time 定义了重复分配?
【发布时间】:2016-06-16 14:03:37
【问题描述】:

我正在处理this answer。我遇到了一个难题:scanf has an assignment suppressing '*':

如果存在此选项,则函数不会将转换结果分配给任何接收参数

但在 get_time 中使用时,'*' 在 Visual Studio、libc++ 和 libstdc++ 上会出现运行时错误:str >> get_time(&tmbuf, "%T.%*Y"),所以我认为它不受支持。

因此,我选择通过两次读取tmbuf.tm_year 来忽略输入:

str >> get_time(&tmbuf, "%H:%M:%S.%Y UTC %b %d %Y");

This works 似乎是我唯一的选择,因为 get_time 不被接受,因为 '*' 不被接受。但众所周知,仅仅因为它有效并不意味着它已被定义。有人可以确认:

  1. get_time中定义了两次赋值同一个变量
  2. 将始终从左到右读取流,因此%Y 的第一个st事件将被踩踏,而不是第二个nd

【问题讨论】:

  • get_timescanf 无关。是什么让您认为scanf 规则适用于get_time?至于重复赋值的有效性,标准并没有说它是无效的,并且还规定格式元素从左到右一个一个地处理。事实上,它指定了处理格式字符串的确切算法。该算法可以毫无错误地处理此类情况。
  • @n.m.我将带着渴望的想法去回答你的问题。但听起来好像这是安全的?也许您会受到启发将其输入答案?

标签: c++ scanf undefined-behavior suppress gettime


【解决方案1】:

该标准规定了处理22.4.5.1.1 time_get membersget_time格式字符串的确切算法。 (time_get::get 是在您执行 str>>get_time(...) 时最终被调用的名称)。我引用了重要的部分:

函数首先计算err = ios_base::goodbit。然后它进入一个循环,在每次迭代时从s 读取零个或多个字符。除非下面另有说明,否则循环会在以下第一个条件成立时终止:

(8.1) — 表达式 fmt == fmtend 的计算结果为真。

跳过无聊的错误处理部分

(8.4) — fmt 的下一个元素等于 ’%’,可选地后跟修饰符,后跟转换说明符字符、格式,共同构成对 ISO/IEC 9945 函数有效的转换规范strptime跳过无聊的错误处理部分函数评估s = do_get(s, end, f, err, t, format, modifier) 跳过更多无聊的错误处理部分函数递增fmt指向刚刚超过转换规范的末尾,并且继续循环。

从描述中可以看出,格式字符串是严格按照从左到右的顺序处理的。没有专门处理重复转换规范的规定。所以答案一定是肯定的,你所做的是定义明确且完全合法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-30
    • 1970-01-01
    • 2013-09-03
    • 2013-01-31
    • 1970-01-01
    • 2013-10-15
    • 2022-09-24
    • 2015-09-11
    相关资源
    最近更新 更多