我遇到了将代码库从linux(gcc)移植到windows(msvc)的问题。看起来C99函数vsscanf不可用,没有明显的替代品。
我已经阅读了使用内部函数_input_l并静态链接到crt运行时的解决方案,但遗憾的是我无法静态链接,因为它会混淆应用程序加载的所有插件(如dll)。
那么有什么替代品或者为vsscanf编写包装器的方法吗?
更新2016-02-24 :
当第一次询问时,没有原生替代品,但从那以后MSVC已经实现了对此的支持以及更多。
答案 0 :(得分:3)
应该有效的黑客攻击:
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... */);
}
将20替换为您认为可能需要的最大args数。这段代码不是非常便携,但它仅用于丢失vsscanf
的一个特定的破碎系统,所以这并不重要。
答案 1 :(得分:0)
快速搜索提出了一些建议,包括http://www.flipcode.net/archives/vsscanf_for_Win32.shtml
答案 2 :(得分:0)
由于这是标记的C ++,您是否考虑过咬住子弹并完全离开scanf
函数行? C ++习惯的方式是使用std::istringstream
。重写使用它而不是寻找vsscanf
替换可能更容易和更便携,更不用说具有更大的类型安全性。
答案 3 :(得分:0)
如果你想包装sscanf而你正在使用C ++ 11,你可以这样做:
template<typename... Args>
int mysscanf(const char* str, const char* fmt, Args... args) {
//...
return sscanf(str, fmt, args...);
}
要在msvc上运行,您需要下载此更新:
http://www.microsoft.com/en-us/download/details.aspx?id=35515
答案 4 :(得分:0)
有趣的是它在今天之前从来没有出现过。我可以发誓过去我曾经使用过这个功能。但无论如何,这是一个有效的解决方案,并且与您的参数和格式字符串一样安全:
template < size_t _NumArgs >
int VSSCANF_S(LPCTSTR strSrc, LPCTSTR ptcFmt, INT_PTR (&arr)[_NumArgs]) {
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 _tmain(int, LPCTSTR argv[])
{
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]);
}
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));
}
Arg1 = -52,arg2 = 456,arg3 = @ 按任意键继续 。 。 。
好吧,我无法正确的格式化,但你明白了。
答案 5 :(得分:0)
修改自: http://www.gamedev.net/topic/310888-no-vfscanf-in-visual-studio/
#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
仅在Visual Studio 2008上测试