• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 297
  • Last Modified:

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

#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;
 
}

see previous question (antos) for the problem. Thanks again.

Ant
0
carbutt
Asked:
carbutt
1 Solution
 
GaryFxCommented:
Simple answer:  Either use strings, or else define a copy constructor and assignment operator for Player.  Furthermore, remove the delete []id from the destructor.  It wasn't created with new, therefore it can't be deleted with delete.  (I'm surprised this hasn't blown up on you.)

Long answer:  Since you don't have your own copy constructor or assignment operator, whenever you copy a Player they wind up sharing the same character pointers for name and ranking.  However, if one of those copies gets deleted, then the character pointers get deleted (by your destructor), leaving the other copy with invalid pointers.

This is known as the Big Three in the C++ FAQ.  It means that any time you write a destuctor, you almost certainly need to write a copy constructor and an assignment operator (and likewise if you write one of the others first).

If you use standard strings, then you no longer need your own destructor, and the problem goes away.

Gary
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

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

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