Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 273
  • Last Modified:

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
0
antos
Asked:
antos
1 Solution
 
CatalepsyCommented:
Could you paste your code into this page?  There seems to be a couple of key ingredients missing.

Thanks,
0
 
ZoppoCommented:
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
0
 
SalteCommented:
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
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
GaryFxCommented:
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
0
 
antosAuthor Commented:
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;
 
}
0
 
SalteCommented:
Yep, the name here is a pointer to a string and when you do a copy you copy the pointer to the string. You then have two objects pointing to the same string.

Later when one of those objects are destroyed it will delete the string and the other object is suddenly left without a name.

step 1. Make a copy constructor that copies the string over to a new copy of the string.

step 2. Make an assignment operator that delete the existing name and then allocate room for a new name and then copy the name over.

Also, you don't have to do:

if (name) delete [] name;

It is ok to simply write:

delete [] name;

is fine. The standard specifies that if name is a null pointer this should do nothing.

Do the same thing for all the other pointers you delete.

Also, I believe you should definitely let the match object use pointers to player objects and not use copies of them. After all it is a specific player that participate in the match and not a copy of him or her.

After you've done this and if you still have problems let us know :-)

Alf
0
 
Mayank SAssociate Director - Product EngineeringCommented:
>> 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.
0
 
Mayank SAssociate Director - Product EngineeringCommented:
Alf, just refer to this:

http://www.experts-exchange.com/Programming/Programming_Languages/Cplusplus/Q_20562641.html

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

Mayank.
0
 
SalteCommented:
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
0
 
Mayank SAssociate Director - Product EngineeringCommented:
:-)
0
 
Mayank SAssociate Director - Product EngineeringCommented:
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.
0

Featured Post

[Webinar On Demand] Database Backup and Recovery

Does your company store data on premises, off site, in the cloud, or a combination of these? If you answered “yes”, you need a data backup recovery plan that fits each and every platform. Watch now as as Percona teaches us how to build agile data backup recovery plan.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now