ID:160224
 
I didn't intend to come to this forum with a question more related to C++ than byond, but I'm getting nowhere in the C++ forums I frequent (though admittedly, the forums of that particular website are much better for C#).

A previous experiment, and subsequent failure can be found here:
http://www.c-sharpcorner.com/Forums/ ShowMessages.aspx?ThreadID=49016


verb/Create_Player(var/n as num)
if(call("R_Controller.dll","CreatePlayer")(n))
usr<<"Player [n] created successfully."

verb/List_Players()
var/s = call("R_Controller.dll","ListPlayers")()
usr << s


In the code above, Create_Player works as expected. However,
I haven't been able to get List_Players() to work. In its present form (below) it crashes dream seeker. However, I have had a variation which merely spits out "est " instead of "test" (when passed to string2return), and another, returned a bunch of incoherent symbols (which looked like strange letter 'i').


extern "C" R_CONTROLLER_API char *ListPlayers()
{

static char string2return[500];
*string2return=0;

for( map<int, Player*>::iterator i=listOfPlayers.begin(); i != listOfPlayers.end(); i++)
{
strncat(string2return, (char*)(i->first), __min( 20, 500-strlen(string2return)) );
//params: char array, char array to append, number of chars to append
//__min returns the lesser of 2 numbers
}
return string2return;
}


I'm having no luck with strings or char arrays being passed to byond (I hate char arrays). I also hate C++, but it's the language of choice for what I'm attempting.

Any light that can be brought to this nether region of my brain would be most appreciated.
Rockinawsome wrote:
> extern "C" R_CONTROLLER_API char *ListPlayers()
> {
>
> static char string2return[500];
> *string2return=0;
>
> for( map<int, Player*>::iterator i=listOfPlayers.begin(); i != listOfPlayers.end(); i++)
> {
> strncat(string2return, (char*)(i->first), __min( 20, 500-strlen(string2return)) );
> //params: char array, char array to append, number of chars to append
> //__min returns the lesser of 2 numbers
> }
> return string2return;
> }
>


While I could hunt through that snippet for subtle logic errors that accompany your off-by-one error (string2return should have 501 elements to account for the possibility of that last terminating NUL byte), I'm going to go for another riddle instead.

You should show the definition CreatePlayer(). I'm assuming that the first element in the map is a pointer to a character array (key maybe?), but your DM code seems to make it appear as a simple number, so I don't understand why you're casting it as a char pointer in List_Players(), as (char*)45 doesn't exactly result in "45". Maybe you're looking for the itoa() standard C function.
In response to Kuraudo
So I updated ListPlayers() with _itoa, and I'm getting a number back now, but the problem is the number doesn't make any sense. If no players are created, no number is returned, but if any number of players are created, then "11" is returned.

example of my output:

Player 2 created successfully. //called create player
11 //called list players
Player 1 created successfully.
11

extern "C" R_CONTROLLER_API char *ListPlayers() 
{

static char string2return[501];
*string2return=0;

for( map<int, Player*>::iterator i=listOfPlayers.begin(); i != listOfPlayers.end(); i++)
{
strncat(string2return, _itoa(i->first,string2return,10), __min( strlen(_itoa(i->first,string2return,10)), 500-strlen(string2return)) );
//params: char array, char array to append, number of chars to append
//__min returns the lesser of 2 numbers
}
return string2return;
}
In response to Kuraudo
Well I've improved my code a bit, using ostringstream and converting it effectively spits out the correct text without chopping anything off.



extern "C" R_CONTROLLER_API char *ListPlayers() 
{
ostringstream string2return;
static char buf[500];
*buf=0;
int count = 0;
for( map<int, Player*>::iterator i=listOfPlayers.begin(); i != listOfPlayers.end(); ++i)
{
count++;
string2return << "Player: " << (*i).first << " " << count << endl;

//params: char array, char array to append, number of chars to append
//__min returns the lesser of 2 numbers
}

strcat(buf,string2return.str().c_str()); //concatenate a C style string with a char array

return buf;
}


The iteration bug remains however, and is driving me crazy.
It iterates once and quits.

Player::Player(int playerNumber) //parameter would be 1-4
{
controllerNum = playerNumber - 1; //adjusted for Microsoft's system: 0-3
}


I thought maybe the above code was the culprit, that perhaps iterators didn't play well with 0, or maybe map<> doesn't, but it turns out testing it by creating players 2 and 3 is as problematic as testing with players 1 and 2.

Any thoughts?

extern "C" bool R_CONTROLLER_API CreatePlayer(int num)
{
Player * Player1 = new Player(num);
listOfPlayers[num] = Player1;
return true;
}


*Edit, I've discovered that the problem must be in relation to the map not expanding in size. I tested with listOfplayers.size(). So therein lies my problem.