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