mtownsend

Hi all,

I find myself needing to write a wrapper function for scanf and sscanf.
Normally, I'd go about this with something like:

int scanf_wrapper ( const char* a_Format, ... ) {
int retval= 0;
va_list ap;

va_start(ap,a_Format);
retval= vscanf(a_Format, ap);
va_end(ap);

return retval;
}

However, it seems like MSVC has no vscanf or vsscanf functions.
Can anyone suggest an alternate solution, or am I screwed

Thanks,

-Mike


Re: Visual C++ Language vscanf alternative

Simple Samples

You can write your function using scanf and such. You just need to write a loop that processes each argument. I searched this forum for va_start and got many results, so if you need help, start with the previous answers.




Re: Visual C++ Language vscanf alternative

mtownsend

Thanks for your suggestion, but I understand how va_lists work and searching the forums
hasn't told me anything I didn't already know.
The problem is that I need to pass an unknown number of arguments to scanf.
If I loop through the va_list and call scanf individually for each one, I have to do all the parsing
on the format string myself, practically re-implementing scanf.
If that's the only way, so be it, but I was hoping there would be a more elegant solution.

-Mike




Re: Visual C++ Language vscanf alternative

Brian Kramer

I looked into this and came up with an unsupported "hack" to accomplish this.  The implementation of scanf (and all of its variants) actually passes va_list internally to a helper function, but this functionality is not exposed to the user.

There is a function, internal to the CRT implementation, called _input_l (_winput_l for Unicode) that you can call yourself if you link against the static library version of the CRT (as opposed to the dll version).  For completeness, I give replacements for both the ANSI and Unicode versions of scanf and sscanf.  Note that Microsoft uses macros to resolve between the two flavors of (s)scanf, and I created functions of the same name but prepended with "my_."  Without further ado...

#include <stdio.h>
#include
<stdarg.h>
#include
<stdlib.h>
#include <tchar.h>

#ifdef _DLL
#error "In order to compile this code, /MT(d) instead of /MD(d) must be used.
#endif

#ifdef _UNICODE
#define _tinput_l _winput_l
#else
#define
_tinput_l _input_l
#endif

extern "C"
int __cdecl _tinput_l(FILE*, const TCHAR*, _locale_t, va_list);

int my_stscanf( const TCHAR *string, const TCHAR *format, ... ) // replacement for _stscanf macro
{
   va_list arglist;
   va_start(arglist, format);
   FILE str;
   str._flag = _IOREAD|_IOSTRG|_IOMYBUF;
   str._ptr = str._base = (char *)string;
   str._cnt = INT_MAX;
   return _tinput_l(&str, format, 0, arglist);
}

int my_tscanf( const TCHAR *format, ... ) // replacement for _tscanf macro
{
   va_list arglist;
   va_start(arglist, format);
   return _tinput_l(stdin, format, 0, arglist);
}

int main()
{
   const TCHAR x[] = _T("1 2 3");
   int a,b,c;

   // test replacement for _tsscanf (which is swscanf for _UNICODE, sscanf otherwise)
   my_stscanf( x, _T("%d %d %d"), &a, &b, &c ); 
   printf("%d %d %d\n", a, b, c );

   // test replacement for _tscanf (which is wscanf for _UNICODE, scanf otherwise)
   _tprintf( _T("now enter three numbers of your own: ") );
   my_tscanf( _T("%d %d %d"), &a, &b, &c );
   printf("%d %d %d\n", a, b, c );

   return 0;
}





Re: Visual C++ Language vscanf alternative

mtownsend

Oh, this is great, Brian.
Thanks a lot!

-Mike




Re: Visual C++ Language vscanf alternative

mtownsend

Er...

I'm getting "error C2081: '_locale_t' : name in formal parameter list illegal"
and "error C2081: 'va_list' : name in formal parameter list illegal"
from the extern declaration of _tinput_l.

Thanks,

-Mike




Re: Visual C++ Language vscanf alternative

Brian Kramer

My code might rely on VS 2005. Which version are you using

(To double check, i copy/pasted the code back into a VS 2005 project and it compiles okay.)





Re: Visual C++ Language vscanf alternative

mtownsend

Yeah, I'm running 2003. Unfortunately, my code needs to work with MSVC7.





Re: Visual C++ Language vscanf alternative

Brian Kramer

Okay. The sources for the C-runtime are probably shipped in VS 2003 also. What i did to solve my problem was to step through the sources for scanf and see what sort of backend exists. The strategy is to simply carry over the code needed to call into the internal implementation. input.c and internal.h are two CRT source files that you might also find useful.

Let me know what you find out. Thanks.





Re: Visual C++ Language vscanf alternative

mtownsend

Thanks for the pointer to input.c
Turns out that, in MSVC7, the required function is:

_input ( FILE *stream, const char *format, va_list arglist )

Everything works great now.
I really appreciate your help.

Thanks again,

-Mike




Re: Visual C++ Language vscanf alternative

Brian Kramer

Yay!  Makes perfect sense: _l is for "locale."  Glad you got what you needed!