Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 更换msvc上的vsscanf_C++_C_Visual C++ - Fatal编程技术网

C++ 更换msvc上的vsscanf

C++ 更换msvc上的vsscanf,c++,c,visual-c++,C++,C,Visual C++,我在将代码库从linux(gcc)移植到windows(msvc)时遇到了一个问题。C99函数vsscanf似乎不可用,也没有明显的替代品 我读过一个使用内部函数input并静态链接到crt运行时的解决方案,但不幸的是,我无法静态链接,因为它会干扰应用程序加载的所有插件(如DLL) 那么,是否有替代品或方法为vsscanf编写包装器呢 更新2016-02-24: 当第一次问到这一点时,并没有本机替换,但从那个时起,MSVC已经实现了对这一点以及更多方面的支持 然后实现vsscanf和frien

我在将代码库从linux(gcc)移植到windows(msvc)时遇到了一个问题。C99函数vsscanf似乎不可用,也没有明显的替代品

我读过一个使用内部函数input并静态链接到crt运行时的解决方案,但不幸的是,我无法静态链接,因为它会干扰应用程序加载的所有插件(如DLL)

那么,是否有替代品或方法为vsscanf编写包装器呢

更新2016-02-24

当第一次问到这一点时,并没有本机替换,但从那个时起,MSVC已经实现了对这一点以及更多方面的支持

  • 然后实现
    vsscanf
    和friends
  • 还包括支持

一次快速搜索发现了几个建议,包括一个应该有效的黑客:

int vsscanf(const char *s, const char *fmt, va_list ap)
{
  void *a[20];
  int i;
  for (i=0; i<sizeof(a)/sizeof(a[0]); i++) a[i] = va_arg(ap, void *);
  return sscanf(s, fmt, a[0], a[1], a[2], a[3], a[4], a[5], a[6], /* etc... */);
}
int-vsscanf(常量字符*s,常量字符*fmt,变量列表ap)
{
无效*a[20];
int i;

对于(i=0;i<P>,这是标记C++吗?您是否考虑过完全咬住子弹并从完全的代码> SCANF函数行中移开?C++的惯用方法是使用<代码> STD::ISTECHANSWATION/CODE。改写以利用它而不是寻找<代码> VSCANFF < /代码>替换可能更容易,更容易。ble,更不用说具有更高的类型安全性。

如果要包装sscanf,并且使用C++11,可以执行以下操作:

template<typename... Args>
int mysscanf(const char* str, const char* fmt, Args... args) {
  //...
  return sscanf(str, fmt, args...);
}
模板
int myscanf(常量字符*str,常量字符*fmt,Args…Args){
//...
返回sscanf(str、fmt、ARG…);
}
要在msvc上执行此操作,您需要下载此更新:

有趣的是,在今天之前我从未想到过这个问题。我可以发誓我以前使用过这个函数。但无论如何,这里有一个解决方案,它可以工作,并且与参数和格式字符串一样安全:


模板

int VSSCANF_S(LPCTSTR STR STRRC、LPCTSTR ptcFmt、int_PTR(&arr)[u NumArgs]){

输出: Arg1=-52,arg2=456,arg3=@ 按任意键继续。

嗯,我无法正确设置格式,但您可以理解。

修改自:


#如果定义了(_WIN32)和(_MSC)版本,则无法在64位平台上运行。
class vaArgs
      {
      vaArgs() {}
      INT_PTR* m_args[_NumArgs];
      public:
         vaArgs(INT_PTR (&arr)[_NumArgs])
                {
                for(size_t nIndex=0;nIndex<_NumArgs;++nIndex)
                    m_args[nIndex] = &arr[nIndex];
                }
      };

   return sscanf_s(strSrc, ptcFmt, vaArgs(arr));
   }
{
INT_PTR args[3];
int nScanned = VSSCANF_S(_T("-52 Hello 456 @"), _T("%d Hello %u %c"), args);

return printf(_T("Arg1 = %d, arg2 = %u, arg3 = %c\n"), args[0], args[1], args[2]);
}
#if defined(_WIN32) && (_MSC_VER <= 1500)
static int vsscanf(
    const char  *buffer,
    const char  *format,
    va_list     argPtr
)
{
    // Get an upper bound for the # of args
    size_t count = 0;
    const char* p = format;
    while(1)
    {
        char c = *(p++);
        if (c == 0) 
            break;
        if (c == '%' && (p[0] != '*' && p[0] != '%')) 
            ++count;
    }
    if (count <= 0)
        return 0;
    int result;
    // copy stack pointer
    _asm
    {
        mov esi, esp;
    }
    // push variable parameters pointers on stack
    for (int i = count - 1; i >= 0; --i)
    {
        _asm
        {
            mov eax, dword ptr[i];
            mov ecx, dword ptr [argPtr];
            mov edx, dword ptr [ecx+eax*4];
            push edx;
        }
    }
    int stackAdvance = (2 + count) * 4;
    _asm
    {
        // now push on the fixed params
        mov eax, dword ptr [format];
        push eax;
        mov eax, dword ptr [buffer];
        push eax;
        // call sscanf, and more the result in to result
        call dword ptr [sscanf];
        mov result, eax;
        // restore stack pointer
        mov eax, dword ptr[stackAdvance];
        add esp, eax;
    }
    return result;
}
#endif // _WIN32 / _MSC_VER <= 1500