让 Linux 和 Windows 都满意的 sscanf 替代方案
Posted
技术标签:
【中文标题】让 Linux 和 Windows 都满意的 sscanf 替代方案【英文标题】:Alternative to sscanf that makes both Linux and Windows happy 【发布时间】:2019-02-04 23:30:58 【问题描述】:我有一个真正古老的punch-card format 和一个使用sscanf
读取它的C++ 代码,如下所示,
sscanf(longstr1,"%2d %5ld %1c %10s %2d %12lf %11lf %7lf %2d %7lf %2d %2d %6ld ",
&cardnumb,&satrec.satnum,&classification, intldesg, &satrec.epochyr,
&satrec.epochdays,&satrec.ndot, &satrec.nddot, &nexp, &satrec.bstar,
&ibexp, &numb, &elnum );
这里字符串longstr1
的前两个字符组成一个int
读入cardnum
,接下来的五个字符组成一个int
读入satrec.satnum
,依此类推。 (一定年龄的人会认出这是一种 Hollerith 格式。)字符串longstr1
中的字符位置永远不会改变。
这很好用,但我必须让它在 Linux 上与 gcc
和 Windows 上的 Visual Studio C++ (2017) 一起工作。 VS 抱怨 sscanf
不安全(我想是的),并建议将其替换为 sscanf_s
,这是 Microsoft 独有的功能。我需要一个让 VS 满意的替代品,但在 Linux 上也可以使用 gcc
编译。
是否有一些安全且可能简单的方法来完成此操作?
【问题讨论】:
当然。这是 C++ 代码,而不是 C。 @RodneyPricesscanf_s
在 C11 中,但不在 C99 中,从不在 C++ 中。
你知道如何使用格式化提取运算符<<
运算符吗?
有什么理由不忽略或禁用警告并继续使用sscanf
?潜在的问题是"%10s"
可能比相应的缓冲区长,但如果你知道它不是你没问题。如果您感到偏执并想确保sscanf
代码在程序员更改缓冲区大小时自动调整,请将格式更改为"%*s"
并传入..., sizeof intldesg - 1, intldesg, ...
。或者,#ifdef _MSC_VER
sscanf_s(...);
#else
sscanf(...);
#endif
既然这是在 C++ 中使用的,为什么要使用 sscanf()
而不是 C++ 风格的流 I/O?
【参考方案1】:
如果您在 Windows 上定义 _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES
,它将在您编写 sscanf 时使用 sscanf_s。这意味着在 Linux 上代码保持原样工作,在 Windows 上,该功能会自动为您替换为安全版本,但不再生成任何警告,因此两个平台都应该满意。有关详细信息,请参阅 Microsoft 文档网站上的 secure template overloads。
【讨论】:
为什么这被否决了?任何投反对票或能理解原因的人,请详细说明。我怀疑这行不通(sscanf_s
需要不同的参数)?
sscanf_s
在大多数情况下应该可以正常工作,因为字符串文字存在模板化重载。我想可能有些地方它仍然不起作用,尽管我在使用该定义时还没有遇到任何问题。以上是关于让 Linux 和 Windows 都满意的 sscanf 替代方案的主要内容,如果未能解决你的问题,请参考以下文章