Link to home
Start Free TrialLog in
Avatar of antos
antos

asked on

Passing an array to funciton, part of the array object is lost ?

I have a match struct as:

class Match{

     public:

     Player player1;
     Player player2;
     int matchNumber;

}; // end of Matches class

//1 fucntion as

Player* newPlayerArray;
newPlayerArray = new Player [partNumber];
newPlayerArray = general.createMatches1(playerArray, partNumber);


this function works fine and returns newPlayerArray correctly - players having names, ids and rankings. But when i try the function setmatches1, taking in the same array as before:

class General {
     
     public:

     General(){
     }

     ~General(){
     }

     Player* createMatches1(Player *playerArray, int number);
     Match* setMatches1(Match* matchArray, Player* playerArray);
         
}; // end of general class

//The METHOD

Match* General::setMatches1(Match* matchArray, Player* playerArray){

     int y=0;

     for (int x=0; x<partNumber; x+=2){
          matchArray[y].player1 = playerArray[x];
          matchArray[y].player2 = playerArray[x+1];
          matchArray[y].matchNumber = y+1;
          y++;
     }

     return matchArray;
}
called in main as:

     matchArray = new Match [partNumber/2];
     matchArray = general.setMatches1(matchArray, newPlayerArray);


The matchArray now has match objects with players with ids and rankings FINE , but for some reason the names of the players DO NOT EXIST. they existed in the playerarray. I cannot se how just the names can be lost from the player element?

I would be very grateful if someone knows how to solve this problem.

Thanks

Ant
Avatar of Catalepsy
Catalepsy

Could you paste your code into this page?  There seems to be a couple of key ingredients missing.

Thanks,
Avatar of Zoppo
At least this code is problematic:

>Player* newPlayerArray;
>newPlayerArray = new Player [partNumber];
>newPlayerArray = general.createMatches1(playerArray, partNumber);

the new created 'newPlayerArray' is replaced by the returned
pointer from 'createMatches1' which is different from newPlayerArray so this will lead to memory-leaks.

anyway I can't see the sense of returning the passed pointer
back to the calling function ... why not simply implement it
like i.e.:

void General::setMatches1(Match* matchArray, Player* playerArray)
{
 int y=0;

 for (int x=0; x<partNumber; x+=2){
   matchArray[y].player1 = playerArray[x];
   matchArray[y].player2 = playerArray[x+1];
   matchArray[y].matchNumber = y+1;
   y++;
 }
}
...
 matchArray = new Match [partNumber/2];
 general.setMatches1(matchArray, newPlayerArray);
...


ZOPPO
There are several problems here.

For one thing the match contain actual player objects instead of pointers or references to them. This means that the match object is supposed to have a copy of each player object participating in that match. If you modify the player data in the match it will not show up in the plain array of players and if you modify data in the player array it will not show up in the match data.

Another problem is that you have removed lots of the code, some of the functions appear with only body and with the parameters and function names removed. This is typically very important information and so we are unable to tell what is going on.

Another problem is that you indicate specifically that one of hte problems is that one of the elements of the player object which is having problems (the name element) but you do not give the source code for the player class anywhere. Instead you give us lots of other code which without the definitions and declarations of the player class won't really have any informational value.

Please post your code and question again.

Alf
Salte is correct that you really need to post the Player code.  But if I might hazard a guess, I'm guessing that the assignment operator for Player isn't handling the names correctly.  Most probably, you're using the default assignment operator, and you have a field that doesn't copy correctly this way.

Gary
Avatar of antos

ASKER

Here is all the code . Thanks for the help guys

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fstream.h>
#include <iostream.h>
#include <iomanip.h>

int partNumber;
double noRounds;       

class Player {

public:
  char id[3];
  char* name;
  char* ranking;
  int intRanking;

  Player() {
   
    name = 0;
    ranking = 0;
    intRanking =0;
  }

  ~Player() {
    if (id) delete [] id;
    if (name) delete [] name;
    if (ranking) delete [] ranking;
  }
 
  void setDetails (char *array);
  void setIds(char *ids, int startPos);  
  void convertRanking(char* ranking);
  void resetName(Player player, Player* playerArray);

}; //end of player class

//////////////////////////////Player functions////////////////////////////////////////////

 void Player::setDetails (char *array) {
   
    //set the name of the player
    char tmpNameArray[13];
    int n=3;
    int y =0;
   
    while(array[n] != ' '){
      tmpNameArray[y] = array[n];
      y++;      
      n++;
    } // end of the do while loop
   
    tmpNameArray[y] = '\0';
   
    name = new char[strlen(tmpNameArray)];
   
    //set the players ranking
    char tmpRankingArray[5];
   
    int z=0;
   
      for (n; n<strlen(array); n++){      
        if (array[n] != ' '){
          tmpRankingArray [z]= array[n];
          z++;
        }
      }
      
      tmpRankingArray[z] = '\0';
      
      ranking = new char [strlen(tmpRankingArray)];

      strcpy(name, tmpNameArray);
      strcpy(ranking, tmpRankingArray);

  }//end of set details
 
 void Player::setIds(char *ids, int startPos){
    id[0] = ids[startPos];
      id[1] = ids[startPos+1];
      id[2] = '\0';

}// end of setIds

void Player::convertRanking(char* ranking){
   
      for (int x=0; x < partNumber; x++){
            char * ch;
            intRanking = int(strtod (ranking, &ch));
      }

} // end of convert ranking

void Player::resetName(Player player, Player *playerArray){
      
      cout << player.name;
      cout << playerArray[1].name;

}

//////////////////////////Matches class/////////////////////////////////////////
class Match{

      public:

      Player player1;
      Player player2;
      int matchNumber;

}; // end of Matches class

///////////////////////////////Match Functions////////////////////////////////////////////////////////



////////////////////////////////////////////////////////General class//////////////////////////////////////
class General {
      
      public:

      General(){
      }

      ~General(){
      }

      void participantsCount(int &count);
      char* removeSpaces(char *text);
      void sortRank(Player *playerArray);
      Player* createMatches1(Player *playerArray, int number);
      Match* setMatches1(Match* matchArray, Player* playerArray);
      void createTheTree(Player* playerArray, Match* matchArray);
      
}; // end of general class

////////////////////////////////////////////General Class Functions////////////////////////////////////////////////////

//Count the number of participants function
void General::participantsCount(int &count) {
 
  ifstream partStream ("participants.dat");
 
  while (!partStream.eof()){
    //remove first line
    partStream.ignore(50, '\n');
    //remove the second line
    partStream.ignore(50, '\n');
    while (!partStream.eof()){
      char ch;
      partStream.get(ch);
      if (ch == ' '){
      count++;
      }
    }
   
  }
 
} // end of participants count

//remove the first 2 spaces from each line
char* General::removeSpaces(char *text){
    int x;
   
    do {
      for (x = 0; x < strlen(text); x++){
      text[x] = text[x+1];
        }
     
      text[strlen(text)] = '\0';
    }while (text[0] == ' ');
   
    return text;
}

void General::sortRank (Player *playerArray){
      
      int a,b;
      Player temp;

      for ( b = 0; b < partNumber - 1; b++){
         for  (a = 0; a < partNumber - 1; a++){
               if (playerArray[a].intRanking < playerArray[a+1].intRanking){
                   temp = playerArray[a];
                   playerArray[a] = playerArray[a+1];
                   playerArray[a+1] = temp;

                     }
             }
      }
} // end of sort Players by rank

Player* General::createMatches1(Player *playerArray, int number) {


Player odds[number/2], evens[number/2];
      Player * temp1;
      Player * temp2;

      if (number == 2) {
            return playerArray;
      } else {
            for (int n = 0; n < number-1; n+=2) {
                  evens[n/2] = playerArray[n];
            } // end for

            for (int n = 1; n <= number-1; n+=2) {
                  odds[n/2] = playerArray[n];
            } // end for

            temp1 = createMatches1(evens, number/2);
            temp2 = createMatches1(odds, number/2);
      }

      for (int n = 0; n < number/2; n++){
            playerArray[n] = temp1[n];      
      }

      for (int n = number/2; n < number; n++) {
            playerArray[n] = temp2[n-(number/2)];
      }

      return playerArray;

} // end function create matches 1

Match* General::setMatches1(Match* matchArray, Player* playerArray){

      int y=0;

      for (int x=0; x<partNumber; x+=2){
            matchArray[y].player1 = playerArray[x];
            matchArray[y].player2 = playerArray[x+1];
            matchArray[y].matchNumber = y+1;
            y++;
      }

      return matchArray;
}// end of setMatches

void General::createTheTree(Player* playerArray, Match* matchArray){

      double numberR = noRounds;
      int numberM = partNumber/2;

      ofstream treeDat("tree.dat");
      ofstream treeHtml("tree.html");

      treeDat << "Matches for round 1" << endl;
      treeDat << endl;

      treeHtml << endl;
      treeHtml << endl;
      
      for (int x=0; x <numberR; x++){
            treeHtml << "<table border = 1>" << "<caption align = top><font color=red>" <<"Round "  << x << "</font>" << endl;
            for (int x=0; x <numberM; x++){
                  treeDat << "Match" << setw(3) << matchArray[x].matchNumber <<":  " <<"Player:  " <<  setw(3) << matchArray[x].player1.id << "  will play" << setw(3) << matchArray[x].player2.id << endl;
                  treeHtml << "<tr>" "<td>"<< "<font color=blue>" << "Match " << "</font>" << matchArray[x].matchNumber << ":  " << "</font>" << "Player:  " << matchArray[x].player1.id << "  will play" << setw(3) << matchArray[x].player2.id << "</td></tr>" << endl
                                    << "</table>";
            }// end of outputting matches
      } // end of outputting rounds
      

} // end of create the tree

////////////////////////////////////////////////////MAIN/////////////////////////////////////////

int main(){
      
      General general;
  int count = 0;
  general.participantsCount(count);
  partNumber = count -2;
  noRounds = sqrt(partNumber);

  Player player;      //player
  Player *playerArray;
 
  Match match; //match
  Match *matchArray;

  //////////EXTRACT PARTICIPANTS////////////
  int arrayLength = (partNumber * 3) +1;
  char *firstCharArray;
  char *participantsArray; //IDs of partcipants
      
  ifstream partStream ("participants.dat");

  playerArray = new Player [partNumber];

  while (!partStream.eof()){
    //remove first line
    partStream.ignore(100, '\n');
    //remove the second line
    partStream.ignore(100, '\n');
    // extract the the third line
    firstCharArray = new char[arrayLength];
    partStream.getline(firstCharArray, 100, '\n');
    participantsArray = firstCharArray;
    delete [] firstCharArray;
    break;
    //ignore the fourth line
    partStream.ignore(100, '\n');
  }
      
  partStream.close(); // close the file

  //remove spaces from participants
  char IDs [(partNumber*2) + 1];
 
  IDs[0] = *(participantsArray);
  IDs[1] = *(participantsArray +1);
 
  //int z=2;
  int y=2;
 
  for (int x =2; x < arrayLength; x++){
   
    if (*(participantsArray + x) == ' '){
    }else{      
      IDs[y] = *(participantsArray + x);
      y++;
    }
  }

  delete [] participantsArray;
 
  IDs[(partNumber*2)] = '\0';
 
   // create player struct variable IDS.
  int x=0;

  for (int n = 0; n < strlen(IDs); n+=2) {
    player.setIds(IDs, n);
    playerArray[x] = player;
    x++;
  }
 
  ///////////////////////EXTRACT players.dat/////////
 
  ifstream playerStream ("players.dat");
 
  char lineArray[30];
  char *secondCharArray;
  secondCharArray = lineArray;
        
  int currentPlayer=0;
 
  while (!playerStream.eof()){
   
    playerStream.getline(secondCharArray, 100, '\n');
    if (secondCharArray[0] != '/' && secondCharArray[1] != '/'){
      general.removeSpaces(secondCharArray);
      if (secondCharArray[0] == playerArray[currentPlayer].id[0] && secondCharArray[1] == playerArray[currentPlayer].id[1]){
            playerArray[currentPlayer].setDetails(secondCharArray);      
            currentPlayer++;
      }
    }
   
  } // end of reading in the file
  playerStream.close();

  //set all the rankings to integers
  for (int x=0; x <partNumber; x++){
      playerArray[x].convertRanking(playerArray[x].ranking);
  }
 
  //sort players in descending order
  general.sortRank(playerArray);
      
  //produce round 1
      Player* newPlayerArray;
      newPlayerArray = new Player [partNumber];
      newPlayerArray = general.createMatches1(playerArray, partNumber);

       for (int x=0; x <partNumber; x++){
            //cout << newPlayerArray[x].name;
       }
      
 
  //set the matches
      
      matchArray = new Match [partNumber/2];
      matchArray = general.setMatches1(matchArray, newPlayerArray);

      for(int x=0; x < partNumber/2; x++){
            cout << matchArray[x].player1.id;
      }

      general.createTheTree(newPlayerArray, matchArray);

      return 0;
 
}
ASKER CERTIFIED SOLUTION
Avatar of Salte
Salte

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
>> if (id) delete [] id;

Don't do it.... id[] has been defined as an array, not as a pointer. Its not been allocated memory using new, so the delete[] is not needed.

Man, your code is too long to debug but all that I would like to say is that whenever you're using pointer data-members in a class, with a destructor having 'delete' statements, then you should be a little careful while passing objects as arguments. You should never pass them by value, as then, a new object is instantiated (the formal argument in the called function), the values of the data-members are copied (including the pointer data-members), so the pointer data-member of the formal argument in the callED function points to the same location as the actual argument in the callING function, and when this called function finishes execution, the destructor is called for the formal argument which deallocates the memory because of the 'delete' statements, and thus, the actual argument's pointer data-member (in the callING function) is now also pointing to garbage.

Hope that you got that, and its of help to you!

Mayank.
Alf, just refer to this:

https://www.experts-exchange.com/questions/20562641/Passing-an-array-to-funciton-part-of-the-array-object-is-lost.html

The code's exactly the same, though the questioner is different..

Mayank.
Mayank,

Hmmm... dare we say the h word?

Seeing that the code is so similar I'd guess that the majority of the code is from the teacher and so they really get it handed for free.

Man, they need to shape up :-)

Alf
Or maybe from a friend who is good at C++ and distributes his code to friends, but is not good enough to always give them the correct code.

Mayank.