解决 Visual C 中缺少 vwscanf 的更好方法?

发布于 2024-12-13 15:35:16 字数 1793 浏览 1 评论 0原文

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

帅的被狗咬 2024-12-20 15:35:16

据我所知,在 C 中(也可能在 C++ 中,尽管我还没有找到明确的声明)中使用额外(即超出要求的)参数调用可变参数函数并不是一个错误。

到目前为止,我在 C++ 方面得到的最好的版本是 5.2.2 [expr.call]:

可以将函数声明为接受更少的参数(通过声明
默认参数 (8.3.6)) 或更多参数(通过使用省略号,
...,或者一个函数参数包(8.3.5))比的数量
函数定义中的参数(8.4)

18.10 [support.runtime] 在 va_start() 限制方面遵循 ISO C 4.8.1.1。

我看不到任何地方说“你不能传递额外的参数”,所以假设它不被禁止似乎并不是没有道理的。

如果在 C++ 中提供额外参数是不合法的,那么您仍然可以使用 C++ 来处理默认参数,并调用已“填写”默认值的 C 函数,这样您就只能调用一个 C 函数,无论有多少个提出了论据。

所以在 C++ 中你可以这样做:

extern "C" {
  int real_scanf(
        const char* format,
        void* a01, void* a02, void* a03, void* a04, void* a05,
        void* a06, void* a07, void* a08, void* a09, void* a10,
        void* a11, void* a12
        );
}

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
    )
{
    BasicCodingValue const* const   f   = format->ptr();
    return real_scanf( f,a01,a02,a03,a04,a05,a06,a07,a08,a09,a10,a11,a12 );
}

然后在 C 中你可以这样做:

int real_scanf(
    const char* format,
    void* a01, void* a02, void* a03, void* a04, void* a05,
    void* a06, void* a07, void* a08, void* a09, void* a10,
    void* a11, void* a12
    )
{
    return wscanf( format,a01,a02,a03,a04,a05,a06,a07,a08,a09,a10,a11,a12 );
}

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]:

A function can be declared to accept fewer arguments (by declaring
default arguments (8.3.6)) or more arguments (by using the ellipsis,
..., or a function parameter pack (8.3.5)) than the number of
parameters in the function definition (8.4)

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:

extern "C" {
  int real_scanf(
        const char* format,
        void* a01, void* a02, void* a03, void* a04, void* a05,
        void* a06, void* a07, void* a08, void* a09, void* a10,
        void* a11, void* a12
        );
}

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
    )
{
    BasicCodingValue const* const   f   = format->ptr();
    return real_scanf( f,a01,a02,a03,a04,a05,a06,a07,a08,a09,a10,a11,a12 );
}

and then in C you could do:

int real_scanf(
    const char* format,
    void* a01, void* a02, void* a03, void* a04, void* a05,
    void* a06, void* a07, void* a08, void* a09, void* a10,
    void* a11, void* a12
    )
{
    return wscanf( format,a01,a02,a03,a04,a05,a06,a07,a08,a09,a10,a11,a12 );
}
留一抹残留的笑 2024-12-20 15:35:16

我的林地 的答案:需要默认值参数:

#include <cstdio>
#include <cassert>

template <typename CodingValue>
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)
{
    return wscanf( format,a01,a02,a03,a04,a05,a06,a07,a08,a09,a10,a11,a12 );
}

int main()
{
    int v(0);
    int rc = scanf<wchar_t>(L"%d", &v);
    assert(1 == rc);
    return 0;
}

请参阅 丹尼斯·齐克福斯上述评论一些背景细节。

My version of awoodland's answer: default-valued arguments are required:

#include <cstdio>
#include <cassert>

template <typename CodingValue>
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)
{
    return wscanf( format,a01,a02,a03,a04,a05,a06,a07,a08,a09,a10,a11,a12 );
}

int main()
{
    int v(0);
    int rc = scanf<wchar_t>(L"%d", &v);
    assert(1 == rc);
    return 0;
}

Please, refer to Dennis Zickefoose comments above for some background details.

情未る 2024-12-20 15:35:16

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文