?
Solved

How do I format a string for OutputDebugString??

Posted on 2011-10-04
22
Medium Priority
?
16,084 Views
Last Modified: 2012-05-12
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
0
Comment
Question by:Wanting2LearnMan
  • 6
  • 3
  • 3
  • +5
22 Comments
 
LVL 45

Accepted Solution

by:
AndyAinscow earned 156 total points
ID: 36911844
#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 );
}
0
 
LVL 45

Expert Comment

by:AndyAinscow
ID: 36911848
sprintf (and other similar functions) can be found in the help files along with flags they take for providing formatted strings.
0
 
LVL 8

Assisted Solution

by:Anthony2000
Anthony2000 earned 308 total points
ID: 36911928
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

0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 86

Assisted Solution

by:jkr
jkr earned 156 total points
ID: 36911974
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

0
 
LVL 30

Assisted Solution

by:Axter
Axter earned 464 total points
ID: 36912021
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

0
 
LVL 30

Assisted Solution

by:Axter
Axter earned 464 total points
ID: 36912035
I should have refresh the screen before posting.
jkr beat me to it!
0
 
LVL 35

Assisted Solution

by:sarabande
sarabande earned 308 total points
ID: 36912036
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
0
 
LVL 30

Assisted Solution

by:Axter
Axter earned 464 total points
ID: 36912052
FYI:
I would recommend changing the input argument to a constant.
void LogMessage (const char* pszFormat, ...)
0
 
LVL 11

Assisted Solution

by:cup
cup earned 152 total points
ID: 36913293
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.
0
 
LVL 29

Assisted Solution

by:pepr
pepr earned 456 total points
ID: 36913530
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().
0
 
LVL 29

Assisted Solution

by:pepr
pepr earned 456 total points
ID: 36913551
... 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

0
 

Author Comment

by:Wanting2LearnMan
ID: 36915213
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??
0
 
LVL 35

Assisted Solution

by:sarabande
sarabande earned 308 total points
ID: 36915244
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
0
 
LVL 29

Assisted Solution

by:pepr
pepr earned 456 total points
ID: 36915347
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).
0
 
LVL 35

Expert Comment

by:sarabande
ID: 36915633
OutputDebugStringA would take a char buffer.

Sara
0
 

Author Comment

by:Wanting2LearnMan
ID: 36915647
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
0
 
LVL 35

Expert Comment

by:sarabande
ID: 36915670
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
0
 

Author Comment

by:Wanting2LearnMan
ID: 36915686
re: but i am not sure that you should go the wchar_t way for debugging

Why do you say this???
0
 
LVL 35

Expert Comment

by:sarabande
ID: 36915727
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
0
 
LVL 35

Expert Comment

by:sarabande
ID: 36915731
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
0
 
LVL 8

Assisted Solution

by:Anthony2000
Anthony2000 earned 308 total points
ID: 36917494
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

0
 
LVL 8

Expert Comment

by:Anthony2000
ID: 36917800
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

0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.
Suggested Courses

862 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question