Page 1 of 1

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

Posted: Sat Apr 03, 2010 4:37 pm
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 ?

Posted: Sat Apr 03, 2010 5:17 pm
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

Posted: Sat Apr 03, 2010 10:20 pm
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.

Posted: Sun Apr 04, 2010 5:38 am
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

Posted: Sun Apr 04, 2010 6:13 am
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>

Posted: Sun Apr 04, 2010 6:25 am
by Zervox
yeah, fixed iostream straight after I posted now it doesnt complain but it doesnt show anything either

Posted: Sun Apr 04, 2010 7:46 am
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.

Posted: Sun Apr 04, 2010 10:06 am
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 ^^

Posted: Sun Apr 04, 2010 10:33 am
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 :?:

Posted: Sun Apr 04, 2010 6:09 pm
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