How do I format a string for OutputDebugString??

I am using:

OutputDebugString(_T("Some text blah blah\r\n"));

Open in new window


in my VS2010 C++ dll project to writ to the output window.

How do I format a string for this so I can output debug  integer values in my program etc
Wanting2LearnManAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

AndyAinscowFreelance programmer / ConsultantCommented:
#include <stdio.h>

int main( void )
{
   char  buffer[200], s[] = "computer", c = 'l';
   int   i = 35, j;
   float fp = 1.7320534f;

   // Format and print various data:
   j  = sprintf( buffer,     "   String:    %s\n", s ); // C4996
   j += sprintf( buffer + j, "   Character: %c\n", c ); // C4996
   j += sprintf( buffer + j, "   Integer:   %d\n", i ); // C4996
   j += sprintf( buffer + j, "   Real:      %f\n", fp );// C4996
   // Note: sprintf is deprecated; consider using sprintf_s instead

   printf( "Output:\n%s\ncharacter count = %d\n", buffer, j );
}

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
AndyAinscowFreelance programmer / ConsultantCommented:
sprintf (and other similar functions) can be found in the help files along with flags they take for providing formatted strings.
Anthony2000Commented:
If you are using MFC, you can also use CString.


CString s;
int myInt = 34;

s.Format(_T("integer: %d\n"), myInt);
OutputDebugString((LPCTSTR)s);

Open in new window

OWASP: Avoiding Hacker Tricks

Learn to build secure applications from the mindset of the hacker and avoid being exploited.

jkrCommented:
I've got my own littly hand-rolled utility for that:
void
LogMessage ( char* pszFormat, ...) {

    static char s_acBuf [ 2048]; // this here is a caveat!

    va_list args;

    va_start ( args, pszFormat);

    vsprintf ( s_acBuf, pszFormat, args);

    OutputDebugString ( s_acBuf);

    va_end ( _args);
}

// example:

LogMessage("Runtime reported exception 0x%lx = %ld, additional info:%d\n", ulCode, ulCode, GetLastError());

Open in new window

AxterCommented:
Consider using a wrapper function like the following:
 
void trace(const char* format, ...)
{
   char buffer[1000];

   va_list argptr;
   va_start(argptr, format);
   wvsprintf(buffer, format, argptr);
   va_end(argptr);

   OutputDebugString(buffer);
}

Open in new window

AxterCommented:
I should have refresh the screen before posting.
jkr beat me to it!
sarabandeCommented:
i once had a project with a solution of your question using c macros and string streams like

#ifdef UNICODE
#define tstring std::wstring
#define tostringstream std::wostringstream
#else
#define tstring std::string                      
#define tostringstream std::ostringstream
#endif

#define FMTDBGSTR(stream)  ((tostringstream&)(tostringstream() << tstring() << stream)).str().c_str() 

Open in new window


that would allow to using dynamic c++ streaming and get a TCHAR* output string, for example like

OutputDebugString(FMTDBGSTR("abc" << 123 << "xyz" << std::endl));

Open in new window


note, i know that c macros is not c++ like. but nevertheless i prefer this before using sprintf.

Sara
AxterCommented:
FYI:
I would recommend changing the input argument to a constant.
void LogMessage (const char* pszFormat, ...)
cupCommented:
Have a look in crtdbg.h.  There are routines called _RPTn _RPTWn, _RPTFn, _RPTFWn where n is 0..5

To print 2 values you could do something like

_RPT2(_CRT_WARN, "1st = %s 2nd = %16.6lf\n", astring, adouble);

The W versions are for wide strings
The F versions print the file and line number.

Not as good as the vsprintf technique but you don't have the 2048 size caveat.
peprCommented:
My +1 to sarabande.  Have a look at Bruce Eckel's "Thinking in C++, 2nd ed Volume 2 (you can download it from http://www.mindview.net/Books/TICPP/ThinkingInCPP2e.html), search for the title "Output stream formatting" and the "An exhaustive example" below, the example identified as "//: C04:Format.cpp".  You can get some inspiration.  The fragment:

...
#define D(A) T << #A << endl; A

int main() {
  ofstream T("format.out");
  assure(T);
  D(int i = 47;)
  D(float f = 2300114.414159;)

  const char* s = "Is there any more?";

  D(T.setf(ios::unitbuf);)
  D(T.setf(ios::showbase);)
  D(T.setf(ios::uppercase | ios::showpos);)
  D(T << i << endl;) // Default is dec
  D(T.setf(ios::hex, ios::basefield);)
  D(T << i << endl;)
...

Open in new window


You can even think about the local redefinition of your OutputDebugString().
peprCommented:
... to add, Bruce Eckel wrote:

This example uses a trick to create a trace file so that you can monitor what’s happening. The macro D(a) uses the preprocessor “stringizing” to turn a into a string to display. Then it reiterates a so the statement is executed. The macro sends all the information to a file called T, which is the trace file. The output is:

int i = 47;
float f = 2300114.414159;
T.setf(ios::unitbuf);
T.setf(ios::showbase);
T.setf(ios::uppercase | ios::showpos);
T << i << endl;
+47
T.setf(ios::hex, ios::basefield);
T << i << endl;
0X2F
...

Open in new window

Wanting2LearnManAuthor Commented:
re: static char s_acBuf [ 2048]; // this here is a caveat!
 //blah
    OutputDebugString ( s_acBuf);

This gives me the error:
argument of type char* is incompatible with parameter of type "LPCWSTR".

How can I solve this??
sarabandeCommented:
you seem to have unicode enabled. then the buf should be wchar_t (or TCHAR) rather than char.

static wchar_t s_acBuf [ 2048];

Sara
peprCommented:
You can define your own overloaded function OutputDebugString() that takes the char* argument (or better const std::string & argument) that makes the output in the desired form (say hex values or a string with escaped control characters, or so).
sarabandeCommented:
OutputDebugStringA would take a char buffer.

Sara
Wanting2LearnManAuthor Commented:
re:  then the buf should be wchar_t (or TCHAR) rather than char

error C2664: 'vsprintf' : cannot convert parameter 1 from 'wchar_t[2048]' to 'char *'      

Same error if I use TCHAR.

Any ideas how to solve this???

many Thanks
sarabandeCommented:
there is function swprintf which takes wide chars.

but i am not sure that you should go the wchar_t way for debugging. use the OutputDebugStringA and it takes single chars.

Sara
Wanting2LearnManAuthor Commented:
re: but i am not sure that you should go the wchar_t way for debugging

Why do you say this???
sarabandeCommented:
the UNICODE/ANSI switch in WINAPI normally is for support of languages. i would assume that for debugging purposes you rarely have to print unicode strings. but when using runtime functions you also would have to take the wide char variant and always have to convert char* to wchar_t* what is annoying.

Sara
sarabandeCommented:
note, the macro solution i posted already has a valid t-switch. so you could use it without bother for wide or narrow char.

Sara
Anthony2000Commented:
try this modified version of jkr's sample code:
void
LogMessage ( const TCHAR * pszFormat, ...) {

    static TCHAR s_acBuf[2048]; // this here is a caveat!
	int nOutputLength;

    va_list _args;
    va_start(_args, pszFormat);

    outputLength = _vsntprintf_s(s_acBuf, 
	                       sizeof(s_acBuf), 					    _TRUNCATE,					              pszFormat, _args);
    
    if(outputLength >= (sizeof(s_acBuf)/sizeof(TCHAR)))
       OutputDebugString(_T("max buffer may have been exceeded!!\n"));
    OutputDebugString(s_acBuf);

    va_end(_args);
}

Open in new window

Anthony2000Commented:
I posted the wrong version, here is what I meant to post:
void
LogMessage ( const TCHAR * pszFormat, ...) {

    static TCHAR s_acBuf[2048]; // this here is a caveat!
	int nOutputLength;

    va_list _args;
    va_start(_args, pszFormat);

    nOutputLength = _vsntprintf(s_acBuf, 
                             sizeof(s_acBuf), 						pszFormat, _args);
    if(nOutputLength < 0)
      OutputDebugString(_T("log messsage buffer was not long enough!\n"));
    OutputDebugString(s_acBuf);

    va_end(_args);
}

example of use:

int a,b,c;

a = 43;
b = 44;
c = 55;

LogMessage(_T("the numbers are %d, %d, %d\n"), a, b , c);

Open in new window

It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.