Newbie std::string problem, printing wrong info:S

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
Zervox
Posts: 6
Joined: Sat Apr 03, 2010 4:30 pm

Newbie std::string problem, printing wrong info:S

Post by Zervox »

:oops: basically I am trying to print to different numbers together, where numUnits is having my current amount of object/units, and unitLimit is the max

std::string u = itoa(numUnits, num, 10) + std::string(" | ") + itoa(unitLimit, num, 10);

Problem is that, it gets the current amount correct and the seperator, but not the unitLimit

in my case unitLimit is set to 15 but if I have 0 objects, 1 object or any number of units it displays like
0 | 0, 1 | 1, 2 | 2

basically it should show 0 | 15 ?
Brkopac
Posts: 88
Joined: Fri Sep 19, 2008 2:36 am

Post by Brkopac »

I'd recommend using string streams for things like this.

Code: Select all

#include <sstream>

int numUnits = 0;
int unitLimit = 15;

std::stringstream ss;
ss << numUnits;
ss << " | ";
ss << numLimit;

std::cout << ss.str() << std::endl;
edit: made the example more clear, I would not recommend Mel's example, take advantage of string streams they are very useful

Brkopac
Last edited by Brkopac on Sun Apr 04, 2010 12:50 am, edited 1 time in total.
Image - The glory days.
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Post by Mel »

No, it looks more like that there are 2 variables called "numUnits" and "unitLimit" and wants to write them in this fashion to a std::string. "numUnits|unitLimit"

First, you don't need "itoa" function when using C++ to output numbers, in fact, not even in C, when the numbers are represented in the basic types. (int, float...)

You can use sprintf, perhaps.

Code: Select all

const char* charArray; // long enough to contain the string.

sprintf(charArray,"%d|%d",numUnits,unitLimit);
And initialize the string with it. Or many other ways.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
Zervox
Posts: 6
Joined: Sat Apr 03, 2010 4:30 pm

Post by Zervox »

I am not so experienced in programming but the unitLimit is defined as
unitLimit = 15;
and the numUnits is updated for every single unit on my map.
added the rest of code affecting looks.

Code: Select all

char num[10];
itoa((int)(money * 10), num, 10);
RECT rc[] = {{80, 2, 0, 0}, {162, 2, 0, 0}};
fontMoney->DrawText(NULL, num, -1, &rc[0], DT_LEFT| DT_TOP | DT_NOCLIP, 0xff000000);

std::string u = itoa(numUnits, num, 10) + std::string(" | ") + itoa(unitLimit, num, 10);
fontMoney->DrawText(NULL, u.c_str(), -1, &rc[1], DT_LEFT| DT_TOP | DT_NOCLIP, 0xff000000);



the code

Code: Select all

const char* charArray; // long enough to contain the string. 

sprintf(charArray,"%d|%d",numUnits,unitLimit);

Code: Select all

error C2664: 'sprintf' : cannot convert parameter 1 from 'const char *' to 'char *'

Brkopac

I am getting cout undeclared identifier
\player.cpp(672) : error C2039: 'cout' : is not a member of 'std'
\player.cpp(672) : error C2065: 'cout' : undeclared identifier

Using Visual Studio 2008 Express
Nalin
Posts: 194
Joined: Thu Mar 30, 2006 12:34 am
Location: Lacey, WA, USA
Contact:

Post by Nalin »

Zervox wrote:the code

Code: Select all

const char* charArray; // long enough to contain the string. 

sprintf(charArray,"%d|%d",numUnits,unitLimit);

Code: Select all

error C2664: 'sprintf' : cannot convert parameter 1 from 'const char *' to 'char *'
Look at the error message. The first parameter to sprintf needs to be a char*. You are passing a const char*.

Code: Select all

char* charArray;
Zervox wrote: Brkopac

I am getting cout undeclared identifier
\player.cpp(672) : error C2039: 'cout' : is not a member of 'std'
\player.cpp(672) : error C2065: 'cout' : undeclared identifier

Using Visual Studio 2008 Express
cout hasn't been included.

Code: Select all

#include <iostream>
Zervox
Posts: 6
Joined: Sat Apr 03, 2010 4:30 pm

Post by Zervox »

yeah, fixed iostream straight after I posted now it doesnt complain but it doesnt show anything either
randomMesh
Posts: 1186
Joined: Fri Dec 29, 2006 12:04 am

Post by randomMesh »

You could try boost::lexical_cast. It rocks conversion-wise.
This is a header-only library, so no need to compile boost or something.

I do all my conversion stuff with this, it never fails.
"Whoops..."
Zervox
Posts: 6
Joined: Sat Apr 03, 2010 4:30 pm

Post by Zervox »

Brkopac wrote:I'd recommend using string streams for things like this.

Code: Select all

#include <sstream>

int numUnits = 0;
int unitLimit = 15;

std::stringstream ss;
ss << numUnits;
ss << " | ";
ss << numLimit;

std::cout << ss.str() << std::endl;
edit: made the example more clear, I would not recommend Mel's example, take advantage of string streams they are very useful

Brkopac

Code: Select all

	std::stringstream ss; 
    ss << numUnits; 
    ss << " | "; 
    ss << unitLimit;
	fontMoney->DrawText(NULL, ss.str(), -1, &rc[1], DT_LEFT| DT_TOP | DT_NOCLIP, 0xff000000);

Code: Select all

error C2664: 'ID3DXFont::DrawTextA' : cannot convert parameter 2 from 'std::basic_string<_Elem,_Traits,_Ax>' to 'LPCSTR'
1>        with
1>        [
1>            _Elem=char,
1>            _Traits=std::char_traits<char>,
1>            _Ax=std::allocator<char>
1>        ]
1>        No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
randomMesh

think I will be having problems on how to do the proper conversion at the moment, this is mostly for learning purposes as you might have guessed ^^
Zervox
Posts: 6
Joined: Sat Apr 03, 2010 4:30 pm

Post by Zervox »

Ok, so I partially solved my old way with a workaround

Code: Select all

std::string units = itoa(numUnits, num, 10) + std::string(" | "); 
// + itoa(unitLimit, num, 10);
fontMoney->DrawText(NULL, units.c_str(), -1, &rc[1], DT_LEFT| DT_TOP | DT_NOCLIP, 0xff000000);

std::string unitsmax = itoa(unitLimit, num, 10);
fontMoney->DrawTextA(NULL, unitsmax.c_str(), -1, &rc[2], DT_LEFT| DT_TOP | DT_NOCLIP, 0xff000000);
now, the max unitLimit is rendered on its own, the error I believe si that the part after (" | ") wouldnt solve and then automaticly parsed the numUnits back into the unitLimit again. Wonder why :?:
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

The error with your original code has to do with how you call itoa(). You pass the same buffer parameter to both calls.

The sequence of statements you wrote...

Code: Select all

std::string u = itoa(numUnits, num, 10) + std::string(" | ") + itoa(unitLimit, num, 10);
I can't remember the rules of sequence points off of the top of my head, but what is happening is that both itoa() calls are completed before the operator+() calls are started. The following is roughly equivalent and should illustrate the problem...

Code: Select all

// stores the string representation of numUnits in the buffer `num'
const char* strNumUnits = itoa(numUnits, num, 10);
printf ("numUnits = %s\n", strNumUnits);

// stores the string representation of unitLimit in the buffer `num'
// overwriting what was previously stored in `num'
const char* strUnitLimit = itoa(unitLimit, num, 10);
printf ("numUnits = %s\n", strNumUnits);
printf ("unitLimit = %s\n", strUnitLimit);

std::string u = strNumUnits + std::string(" | ") + strUnitLimit;
The easy way to handle this is to either use a different buffer for each itoa() call, or to break up the expression so that the buffer is read before it is overwritten.

Code: Select all

std::string u
u += itoa(numUnits, num, 10);
u += " | "
u += itoa(unitLimit, num, 10);
Another simple option is to use one of the sprintf family of functions...

Code: Select all

#include <stdio.h>
#include <string>

int main ()
{
  int numUnits = 1;
  int unitLimit = 12;

  char buf [64];
  sprintf (buf, "%d | %d", numUnits, unitLimit);

  std::string u (buf);
  std::cout << u << std::endl;

  return 0;
}
You could also use this...

Code: Select all

#include <sstream>
#include <string>

int main ()
{
  int numUnits = 1;
  int unitLimit = 12;

  std::ostringstream os;
  os << numUnits << " | " << unitLimit;

  std::string u (os.str());
  std::cout << u << std::endl;

  return 0;
}
Or you could even use Irrlicht's string class...

Code: Select all

#include <irrlicht.h>
using namespace irr;

int main ()
{
  int numUnits = 1;
  int unitLimit = 12;

  core::string u;
  u += numUnits;
  u += " | ";
  u += unitLimit;

  std::string u (u.c_str());
  std::cout << u << std::endl;

  return 0;
}
Travis
Post Reply