?
Solved

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

Posted on 2003-03-25
11
Medium Priority
?
272 Views
Last Modified: 2010-04-01
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
Comment
Question by:antos
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
11 Comments
 
LVL 3

Expert Comment

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

Thanks,
0
 
LVL 31

Expert Comment

by:Zoppo
ID: 8203434
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
 
LVL 12

Expert Comment

by:Salte
ID: 8204064
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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 6

Expert Comment

by:GaryFx
ID: 8204261
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
 

Author Comment

by:antos
ID: 8204367
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
 
LVL 12

Accepted Solution

by:
Salte earned 100 total points
ID: 8204443
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
 
LVL 30

Expert Comment

by:Mayank S
ID: 8208183
>> 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
 
LVL 30

Expert Comment

by:Mayank S
ID: 8208185
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
 
LVL 12

Expert Comment

by:Salte
ID: 8209121
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
 
LVL 30

Expert Comment

by:Mayank S
ID: 8209157
:-)
0
 
LVL 30

Expert Comment

by:Mayank S
ID: 8209375
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

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
  Included as part of the C++ Standard Template Library (STL) is a collection of generic containers. Each of these containers serves a different purpose and has different pros and cons. It is often difficult to decide which container to use and …
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
Suggested Courses

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question