wsprintf and swprintf functions and floating point numbers

Apparently these wide character versions of sprintf don't format floating point numbers. This is a problem when using Visual C++ 2010 Express as downloaded since all the ASCII Text functions have been redefined as wide-character functions. My first thought was to remove the redefinitions. I assume they are somewhere in the header files for Windows but I haven't found them with more than a cursory look. Can someone tell me where to find them so I can undo them? (I know that Unicode is de regueur these days but my code will never be translated in languages needing the wider formats.)

I have ended up writing a little routine to convert ASCII strings to wide-character strings just so I can use sprintf to format floating point numbers. Surely there is a neater solution to the problem. Any solutions will be greatly appreciated.
This is a problem when using Visual C++ 2010 Express as downloaded since all the ASCII Text functions have been redefined as wide-character functions.


Umm... that is extremely unlikely. What makes you think that?


EDIT: Also... they would format floating points just fine. Nothing about this makes sense. Either something is very, very wrong with your installation or you are not using these functions properly.

Can you post some code showing what you're trying to do along with any error messages or unexpected behavior you're seeing?
Last edited on
I agree, Disch, none of this makes sense from a business point of view. Why would Microsoft do this? I rationalize it by thinking they want to indoctrinate young programmers with Unicode early. Sort of like IBM many years ago supplied high schools with Selectric type writers at little or no cost. Made new secretaries demand Selectrics. Who knows?

Still, I'm convident I'm right on the redefinition.

If I let the cursor linger momentarily over ASCII text functions while working on the source file, they all display messages like this.

#define MessageBox MessageBoxW

Here is some sample code with sprintf, wsprintf, swprintf


double xBeg,xEnd.yBeg,yEnd;
static char mixed[1024];
static WCHAR handler[1024];


sprintf(mixed,"X Limits %.5g to %.5g\nY Limits %.5g to %.5g",xBeg,xEnd,yBeg,yEnd);

compiles and displays as
"X Limits .123 to .345
Y Limits .678 to .901"

wsprintf(handler,L"X Limits %.5g to %.5g\nY Limits %.5g to %.5g",xBeg,xEnd,yBeg,yEnd);

compiles and displays as
"X Limits g to g
Y Limits g to .g"


swprintf(handler,1023,L"X Limits %.5g to %.5g\nY Limits %.5g to %.5g",xBeg,xEnd,yBeg,yEnd);

Will not compile. Displays a message something like.
"Doesn't match any of the overload options for this function"

When I try swprintf with intergers, it compiles and displays the appropriate values .

I've been out of programming for some time except for this bit of work. Still, I sort of remember that Petzold mentioned the problem with real numbers with the wsprintf function in his 5th edition.


Still, I'm convident I'm right on the redefinition.


I wouldn't be. I'm still very skeptical.

If I let the cursor linger momentarily over ASCII text functions while working on the source file, they all display messages like this.


WinAPI functions such as MessageBox are defined as macros. This is due to the TCHAR issue.

MessageBoxA = takes char's
MessageBoxW = takes wchar_t's
MessageBox = takes TCHAR's

This is defined in the formal documentation on MSDN.

What's more, TCHAR is simply a typedef (or possibly a #define) of either char or wchar_t depending on whether or not the UNICODE macro is defined.

So instead of having an actual 3rd function, the TCHAR version of these functions are merely #defined over to the A or W versions, dependon on what TCHAR itself is defined as.

So this is not a matter of them redefining the behavior of existing functions. All the above work exactly as advertised -- exactly how the documentation says they should.



However... your problem is neither with a WinAPI function... nor is it with a function that takes TCHARs. So none of that applies.



I will test out the code you posted and revisit this momentarily....


EDIT:

Okay here is what I figured out.

1) wsprintf() is a WinAPI function that takes TCHARs
(ref: http://msdn.microsoft.com/en-us/library/windows/desktop/ms647550%28v=vs.85%29.aspx ). Notice the parameter list says LPCTSTR. That T means TCHAR. It does not take wide characters (at least not all the time).

So yeah, wsprintf() is going to be defined as either wsprintfA or wsprintfW depending on whether or not UNICODE is defined. If you are not using TCHARs, you should not be using that function.

2) You are correct in that wsprintf does not seem to support floating point numbers. It appears to be a "mini" version of the actual sprintf. It also does not support the '*' qualifier, and truncates the string at 1024 TCHARs. So it's basically a steaming load and you shouldn't use it at all. Plus it's WinAPI so it's not portable.


3) swprintf works fine as you posted it for me. I don't know why you're having trouble but I can only assume that the code you are running is slightly different from what you pasted (you had some other issues with your code that I had to fix before running it -- such as a dot instead of a comma, and uninitialized variables).

If you don't give me and actual copy/paste of code that repos your problem, I can't verify it.


4) swprintf is a standard function (portable) whereas wsprintf is not (available on Windows only). Apart from that, swprintf actually works whereas wsprintf is crippled as previously described. So I cannot imaging any reason why anyone would ever choose wsprintf over swprintf.
Last edited on
Well, Disch, I see you have had almost 9000 posts to this site,. I’m sure you have helped a lot of people with this effort. Still you are flatly wrong about my assertion that functions like
DrawText and MessageBox are automatically replaced with DrawTextW and MessageBoxW by Visual C++ 2010 Express. You would have seen this if you had actually checked this out on VisualBasic C++ 2010 Express. The editor clearly indicates that MessageBox is being replaced with MessageBoxW.

#define MessageBox MessageBoxW

This is nothing more than instructions to the preprocessor to make the conversion at compile time.

It works just like

#define ID_OK 1 ,

the instruction to the preprocessor to substitute 1 for the ID_OK at compile time It is working like as a word processor, not via some elaborate programming construct.

With Visual Basic C++ 2010 Express
MessageBox(hWnd,L”This is a test”,L“Testing”,MB_OKCANCEL)
will only compile if the strings are designated as Unicode with the L character.

I’m sure you know that Mircosoft only promises that the free Express edition will be adequate for student and amateur programmers in most instances and is not a substitute for the full commercial edition. They have disabled certain features to be sure to preserve the market. For example .h files and .rc files cannot be generated and editing of them is not permitted except in some narrowly defined cases. The graphical assist for constructing menus, dialog boxes, etc. is not provided in the Express edition. I suspect that there are many more examples.

On the other matter, you are completely right that swprintf does format floating point numbers nicely and generates a Unicode string suitable for MessageBox (redefined as MessageBoxW). I jumped to the conclusion that swprintf has all the limitations of wsprintf when my code didn’t compile easily. I probably did not mark the string with the ubiquitous L.

I was only using the wide-character functions because I was forced to do so by the substitutions,

I look forward to using swprintf in the future.


Have a good day.
Well, Disch, I see you have had almost 9000 posts to this site,. I’m sure you have helped a lot of people with this effort. Still you are flatly wrong about my assertion that functions like
DrawText and MessageBox are automatically replaced with DrawTextW and MessageBoxW by Visual C++ 2010 Express.


I'm not wrong. You just misinterpreted what I said. Here's what I said:

I wrote:
So instead of having an actual 3rd function, the TCHAR version of these functions are merely #defined over to the A or W versions, dependon on what TCHAR itself is defined as.

So this is not a matter of them redefining the behavior of existing functions. All the above work exactly as advertised -- exactly how the documentation says they should.


You are right in that MessageBox sometimes is a #define of MessageBoxW (I say as much in the above blurb). But that's not the right way to think about it.

The right way to think about it is that MessageBox takes TCHARs. Not chars, and not wide strings. TCHARs are a 3rd type that varies depending on your compiler setting.

Therefore, whether MessageBox is #defined as either MessageBoxW (wide version) or MessageBoxA (char version) also depends on your compiler setting (or really, the UNICODE macro).

MessageBox(hWnd,L”This is a test”,L“Testing”,MB_OKCANCEL)
will only compile if the strings are designated as Unicode with the L character.


This is BAD CODE.

You are passing wide strings to a function that does not take wide strings. To clarify... MessageBox does not take wide strings. It takes TCHAR strings. The MessageBox documentation states as much:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms645505%28v=vs.85%29.aspx

Notice that the parameters are "LPCTSTR". The T is for TCHAR. If it were wide, it would say "LPCWSTR"

If you are using wide strings, you should use the wide version of the function, MessageBoxW.

1
2
3
4
5
MessageBoxA(hWnd,"works.  char strings with char version of function","ok",MB_OK);

MessageBoxW(hWnd,L"works.  wide strings with wide version of function",L"ok",MB_OK);

MessageBox(hWnd,TEXT("works.  TCHAR strings with TCHAR version of function"),TEXT("ok"),MB_OK);



I was only using the wide-character functions because I was forced to do so by the substitutions,


You are never forced to. If you do not want to use the wide versions of the functions... don't. I'm pretty sure all WinAPI functions have narrow (char) counterparts.

So instead of using MessageBox... you should probably be using MessageBoxA.
Last edited on
If that post was too long... here's the jist of it:


Regardless of what proof you think you have to the contrary, VS is not redefining functions like MessageBox to take a different form of string.

The problem is you are using the wrong function.

If you are using char strings, you want to use the 'A' version of WinAPI functions.

So use MessageBoxA, DrawTextA, etc instead of MessageBox, DrawText. Then your problems will go away.
Topic archived. No new replies allowed.