解决 Visual C 中缺少 vwscanf 的更好方法?
C++11 标准指定 vwscanf
可通过标头
获得(因此
)。然而Visual C++ 似乎缺乏这一点。有了这个函数,我可以写……
inline int scanf( CodingValue const* format, ... )
{
va_list args;
va_start( args, format );
return ::vwscanf( format->ptr(), args );
}
但没有它,即使用 Visual C++ 10.0,它似乎也缺乏对 C++11 可变参数模板的支持,我只能写……
inline int scanf(
CodingValue const* format,
void* a01 = 0, void* a02 = 0, void* a03 = 0, void* a04 = 0, void* a05 = 0,
void* a06 = 0, void* a07 = 0, void* a08 = 0, void* a09 = 0, void* a10 = 0,
void* a11 = 0, void* a12 = 0
)
{
int const nArgs = !!a01 + !!a02 + !!a03 + !!a04 + !!a05 + !!a06 +
!!a07 + !!a08 + !!a09 + !!a10 + !!a11 + !!a12;
BasicCodingValue const* const f = format->ptr();
switch( nArgs )
{
case 0: return ::wscanf( f );
case 1: return ::wscanf( f,a01 );
case 2: return ::wscanf( f,a01,a02 );
case 3: return ::wscanf( f,a01,a02,a03 );
case 4: return ::wscanf( f,a01,a02,a03,a04 );
case 5: return ::wscanf( f,a01,a02,a03,a04,a05 );
case 6: return ::wscanf( f,a01,a02,a03,a04,a05,a06 );
case 7: return ::wscanf( f,a01,a02,a03,a04,a05,a06,a07 );
case 8: return ::wscanf( f,a01,a02,a03,a04,a05,a06,a07,a08 );
case 9: return ::wscanf( f,a01,a02,a03,a04,a05,a06,a07,a08,a09 );
case 10: return ::wscanf( f,a01,a02,a03,a04,a05,a06,a07,a08,a09,a10 );
case 11: return ::wscanf( f,a01,a02,a03,a04,a05,a06,a07,a08,a09,a10,a11 );
case 12: return ::wscanf( f,a01,a02,a03,a04,a05,a06,a07,a08,a09,a10,a11,a12 );
}
}
或者,我可以做一些汇编,就像我喜欢的那样15 年前,当我遇到类似(或者可能相同)的问题时,但感觉不太对劲。
你能建议一些更好的方法吗?
The C++11 standard specifies that vwscanf
is available via header <cwchar>
(and therefore <wchar.h>
). However it seems to be lacking in Visual C++. With that function I could write …
inline int scanf( CodingValue const* format, ... )
{
va_list args;
va_start( args, format );
return ::vwscanf( format->ptr(), args );
}
but without it, i.e. with Visual C++ 10.0, which also appears to lack support for C++11 variadic templates, I’m reduced to writing …
inline int scanf(
CodingValue const* format,
void* a01 = 0, void* a02 = 0, void* a03 = 0, void* a04 = 0, void* a05 = 0,
void* a06 = 0, void* a07 = 0, void* a08 = 0, void* a09 = 0, void* a10 = 0,
void* a11 = 0, void* a12 = 0
)
{
int const nArgs = !!a01 + !!a02 + !!a03 + !!a04 + !!a05 + !!a06 +
!!a07 + !!a08 + !!a09 + !!a10 + !!a11 + !!a12;
BasicCodingValue const* const f = format->ptr();
switch( nArgs )
{
case 0: return ::wscanf( f );
case 1: return ::wscanf( f,a01 );
case 2: return ::wscanf( f,a01,a02 );
case 3: return ::wscanf( f,a01,a02,a03 );
case 4: return ::wscanf( f,a01,a02,a03,a04 );
case 5: return ::wscanf( f,a01,a02,a03,a04,a05 );
case 6: return ::wscanf( f,a01,a02,a03,a04,a05,a06 );
case 7: return ::wscanf( f,a01,a02,a03,a04,a05,a06,a07 );
case 8: return ::wscanf( f,a01,a02,a03,a04,a05,a06,a07,a08 );
case 9: return ::wscanf( f,a01,a02,a03,a04,a05,a06,a07,a08,a09 );
case 10: return ::wscanf( f,a01,a02,a03,a04,a05,a06,a07,a08,a09,a10 );
case 11: return ::wscanf( f,a01,a02,a03,a04,a05,a06,a07,a08,a09,a10,a11 );
case 12: return ::wscanf( f,a01,a02,a03,a04,a05,a06,a07,a08,a09,a10,a11,a12 );
}
}
Or, I could do some assembly, as I did like 15 years ago when I encountered similar (or perhaps the same) problem, but that does not feel quite right.
Can you suggest some better way?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
据我所知,在 C 中(也可能在 C++ 中,尽管我还没有找到明确的声明)中使用额外(即超出要求的)参数调用可变参数函数并不是一个错误。
到目前为止,我在 C++ 方面得到的最好的版本是 5.2.2 [expr.call]:
18.10 [support.runtime] 在
va_start()
限制方面遵循 ISO C 4.8.1.1。我看不到任何地方说“你不能传递额外的参数”,所以假设它不被禁止似乎并不是没有道理的。
如果在 C++ 中提供额外参数是不合法的,那么您仍然可以使用 C++ 来处理默认参数,并调用已“填写”默认值的 C 函数,这样您就只能调用一个 C 函数,无论有多少个提出了论据。
所以在 C++ 中你可以这样做:
然后在 C 中你可以这样做:
As I understand it's not an error to call a variadic function with extra (i.e. more than asked for) arguments in C (and possibly in C++, although I've yet to locate a definitive statement either way on that).
The best I've got on the C++ side so far is 5.2.2 [expr.call]:
18.10 [support.runtime] defers to the ISO C 4.8.1.1 on the subject of restrictions for
va_start()
.I can't see anywhere that says "you must not pass extra arguments", so it seems that it wouldn't be unreasonable to assume that it's not prohibited.
If it's not legal in C++ to give extra arguments then you can use C++ to handle the default arguments still and call a C function with the defaults having been "filled out" so that you only ever call the one C function, regardless of how many arguments were given.
So in C++ you'd do:
and then in C you could do:
我的林地 的答案:需要默认值参数:
请参阅 丹尼斯·齐克福斯上述评论一些背景细节。
My version of awoodland's answer: default-valued arguments are required:
Please, refer to Dennis Zickefoose comments above for some background details.
VS2010 中有一个
int vwscanf(format, ...)
的实现。文件 = wscanf.c
目录 = C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\crt\src
There is an implementation of
int vwscanf(format, ...)
with VS2010.File = wscanf.c
Directory = C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\crt\src