Замена для vsscanf на msvc - PullRequest
       16

Замена для vsscanf на msvc

4 голосов
/ 16 марта 2010

Я столкнулся с проблемой переноса кодовой базы из linux (gcc) в windows (msvc). Кажется, что функция C99 vsscanf недоступна и не имеет очевидной замены.

Я читал о решении, использующем внутреннюю функцию _input_l и связывающем статически со средой выполнения crt, но, к сожалению, я не могу связать статически, так как это будет портить все плагины (в виде dll), загружаемые приложением.

Так есть ли замена или способ написания оболочки для vsscanf?

Обновление 2016-02-24 :

Когда об этом впервые спросили, не было собственной замены, но с тех пор MSVC реализовал поддержку этого и многое другое.

  • VS2013 и более поздних версий vsscanf и друзей.
  • C ++ 11 также включает поддержку.

Ответы [ 6 ]

3 голосов
/ 09 июля 2010

Взлом, который должен работать:

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 на максимальное количество аргументов, которое, по вашему мнению, может вам понадобиться. Этот код не очень переносим, ​​но он предназначен для использования только на одной сломанной системе, в которой отсутствует vsscanf, так что это не должно иметь большого значения.

0 голосов
/ 19 февраля 2016

изменено с: 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

0 голосов
/ 07 января 2014

Забавно, что до сегодняшнего дня мне это никогда не приходило в голову. Я мог бы поклясться, что использовал эту функцию в прошлом. Но в любом случае, вот решение, которое работает и так же безопасно, как ваши аргументы и строка формата:

template < size_t _NumArgs ></p> <p>int VSSCANF_S(LPCTSTR strSrc, LPCTSTR ptcFmt, INT_PTR (&arr)[_NumArgs]) {</p> <pre><code>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]);
}

Из:

Arg1 = -52, arg2 = 456, arg3 = @ Нажмите любую клавишу для продолжения . , ,

Ну, я не могу правильно отформатировать, но вы поняли идею.

0 голосов
/ 19 мая 2013

Если вы хотите обернуть 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

0 голосов
/ 09 июля 2010

В связи с тем, что это помечено как C ++, вы рассматривали возможность просто укусить пулю и полностью отойти от линии функций scanf? Идиоматический способ C ++ - использовать std::istringstream. Переписать, чтобы использовать это вместо поиска vsscanf, возможно, было бы проще и более портативно, не говоря уже о гораздо большей безопасности типов.

0 голосов
/ 16 марта 2010

Быстрый поиск обнаружил несколько предложений, включая http://www.flipcode.net/archives/vsscanf_for_Win32.shtml

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...