• Advertisement
Sign in to follow this  

printing some stuff on screen?

This topic is 3953 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

hello guys i am having some problems writing some stuff on screen using a function that helps me draw text on the screen. The problem occurs when i want to write a string to the screen, for example the players name. //in main game loop strcpy_s(str, ""); wsprintfA(str, "\nPlayer Name: %s", hscore[0].name); //Draw string DXUDrawText(&impactFont, str); //<-- function that draws test on screen //somewhere hScore[0].name="RYU"; hscore[0].score=1233412; Now the problem is this wsprintfA(str, "\nPlayer Name: %s", hscore[0].name); Doesn't print ryu name, i am getting confused how to use it, if i did wsprintfA(str, "\nPlayer Score: %d", hscore[0].score); this works showing the integer value for player score?

Share this post


Link to post
Share on other sites
Advertisement
Please post the definitions of the str variable and the hscore variable (and the structure/class).

Also, I note that you have some inconsistent case - you access "hscore" most of the time, but assign the name string into "hScore". Is that just a typo in your post, or is that actually what's in your code?


You shouldn't use strcpy_s, wsprintfA, and so on; they can possibly write into areas of memory that they shouldn't, which can crash your program, corrupt your data, or worse. (Look up "buffer overflow" for more information on how that works.) Instead, use strncpy, snprintf, and so on; those functions accept a "length" parameter which tells them how much memory they can write into, which helps prevent overflows.

If you're writing in C++, you shouldn't use raw string functions at all, but instead use std::string.

Share this post


Link to post
Share on other sites


struct HiScoreTable
{
string name;
int score;
};

HiScoreTable hscore[10];
//will be in vector once it starts working
//vector<hiScoreTable> scoreTable;

DXUFONT impactFont; // the font we will use to write to screen
TCHAR str[MAX_PATH]; // a string variable to write to screen
RECT rcImpact = {20, 20, 1024, 768}; // the rectangular area we will write on screen


Share this post


Link to post
Share on other sites
basically hscore is just a struct which i will input data from the player later on i.e

//when player dies
hscore[0].name=player->getName();
hscore[0].score=player->getScore();

Share this post


Link to post
Share on other sites
hi i did this ->

strcpy_s(str, "");
hscore[0].name="AMIR";
sprintf(str, "\nPlayer Name: %s", hscore[0].name);

but the output is Player Name: (null) ???? whats going on here?

Share this post


Link to post
Share on other sites
The problem is that you are mixing std::string and C-style strings. wsprintfA expects that the string you pass it is a C-style string, but you're passing it a std::string from the hscore struct.

You could fix the problem by converting the std::string to a C-string with the c_str() function; that is, pass hscore[0].name.c_str() to wsprintfA. However, that's not really a good fix.

What you should do is use std::string consistently, and not use C-strings at all if you can possibly help it.

// Include this at the top of the file:
#include <sstream>

// Replace the string formatting/output code with this:
std::ostringstream output;
output << "\nPlayer Name: " << hscore[0].name;

DXUDrawText(&impactFont, output.str());

Share this post


Link to post
Share on other sites
Yes, that is technically a valid option. It is, however, an extremely bad idea. As I said in my first post, C-strings are dangerous and error-prone, and can lead to many bad things happening in your program. Even programmers with a lot of experience can screw up C-strings pretty easily.

For more detailed explanation, see section 34.1, here.

I would really strongly recommend that you get out of the habit of using C-strings (this means, in case you're not familiar with the term, anything like char*, char[], TCHAR*, LPTSTR, etc. etc.) and use C++'s string feature properly.

Share this post


Link to post
Share on other sites
ok sorry mate i seem to get this error

error C2664: 'DXUDrawText' : cannot convert parameter 2 from 'std::basic_string<_Elem,_Traits,_Ax>' to 'LPSTR'

pointing to -> DXUDrawText(&impactFont, output.str());

Share this post


Link to post
Share on other sites
Eek. I looked up the DXU code that you're using, and frankly it's a bit crap. I know it's a big change, but if you can, you might be better off getting rid of it and using DirectX directly. (Alternatively, depending on what you're working on, you might find other libraries like SDL more appropriate.)

That's a bit more major than switching to consistent std::string usage, so I totally understand if you'd rather not do that [smile]

Here's what I'd recommend; just change your DXUDrawText calls to this DrawText function:

void DrawText(LPDXUFONT font, const std::string& text)
{
size_t buffersize = text.length() + 1;
char* buffer = new char[buffersize];
std::copy(text.c_str(), text.c_str() + buffersize, buffer);

// Pray that DXU doesn't throw exceptions.
// If it does, see version 2 below.
DXUDrawText(font, buffer);

delete [] buffer;
}

// You should only need to use this version if you KNOW that the
// DXU library throws C++ exceptions. I don't think it does, so
// the above version should be OK.
void DrawText(LPDXUFONT font, const std::string& text)
{
size_t buffersize = text.length() + 1;
char* buffer = new char[buffersize];
std::copy(text.c_str(), text.c_str() + buffersize, buffer);

try
{
DXUDrawText(font, buffer);
}
catch(...)
{
delete [] buffer;
throw;
}

delete [] buffer;
}





The basic problem is that the DXU font drawing code is asking for a C-string buffer that it can modify. I don't know for sure if it actually will modify the string, but I doubt it; in any case, better safe than sorry.

The trouble is, when we have a std::string and want to get a C-string from it, we get a C-string which isn't safe to modify. This is denoted by the fact that the value returned by c_str() is a const.

So we have a string we can't modify, but we have to give it to a function that demands permission to modify it. We're stuck.

(For the record, this is part of why I say the DXU code is garbage; the functions should take const strings at the very least, which would be denoted by the shortcut LPCTSTR rather than LPSTR. The DXU code is riddled with such inconsistencies and poor practices.)

The solution is to create a temporary copy of the string, in a special buffer that we have complete control over. That way, it's OK if the DXU code changes the string. Then, once the DXU code is done doing its thing, we clean up that temporary copy, and move on.

Share this post


Link to post
Share on other sites
i find the dxu library really easy to use compared to other direct x wrappers but yeah it isn't very well done with some things :), thanks again mate, your really helpfull :)

Share this post


Link to post
Share on other sites
Quote:

// You should only need to use this version if you KNOW that the
// DXU library throws C++ exceptions. I don't think it does, so
// the above version should be OK.
void DrawText(LPDXUFONT font, const std::string& text)
{
size_t buffersize = text.length() + 1;
char* buffer = new char[buffersize];
std::copy(text.c_str(), text.c_str() + buffersize, buffer);

try
{
DXUDrawText(font, buffer);
}
catch(...)
{
delete [] buffer;
throw;
}

delete [] buffer;
}


Ugh. Instead:


void DrawText(LPDXUFONT font, const std::string& text)
{
std::vector<char> buffer(text.c_str(), text.c_str() + text.length() + 1);

DXUDrawText(font, &buffer[0]);
}

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement