I'm working on a soccer management program
I had some other members of my group to compile data on 400 real life players into a text file.
I planned on reading the text file using a program ,converting individual players into objects and then writing them to another file (in binary mode) to be used by my program..
The reading and writing seems to have gone well, but when I try to open the new file containing the player objects, the program seems to be able to read only 20 players for some reason..

#include <fstream>

#include <iostream>

using namespace std;


int main()

{
  class plr
    {
    public:
      int id;
      int shirt_no;
      int age;
      int goals;
      int pos;//0-GK,1-DEF,2-MID,3-ATT
      char LName[51];
      char FName[51];
      int team;
      int skill;
      int goaltime;
      int cards;
      void transfer(int t_id)
      {
        team = t_id;
      }
    }plrs[401],plrs2[401];



  fstream reader("players.txt", ios::in);
  fstream binary("players2.dat", ios::out);

  //READ FROM TEXT FILE into objects  :
int j;
  for (int i=1;i<=401;i++)
    {
      reader>>j;
      plrs[j].id = j;
      reader>>plrs[j].LName>>plrs[j].FName>>plrs[j].team>>plrs[j].shirt_no>>plrs[j].age>>plrs[j].pos>>plrs[j].skill>>plrs[j].goaltime>>plrs[j].cards;


      cout << "\n\n";
    }
  reader.close();

//Display all players
for(int j=1;j<=400;j++)
{cout<<"\n\n"<<plrs[j].LName<<"\n"<<plrs[j].FName<<"\n"<<plrs[j].team<<"\n"<<plrs[j].shirt_no<<"\n"<<plrs[j].age<<"\n"<<plrs[j].pos<<"\n"<<plrs[j].skill<<"\n"<<plrs[j].goaltime<<"\n"<<plrs[j].cards;
}

//Write objects to file
for (int j=1;j<=400;j++){
binary.write((char*)&plrs[j], sizeof(plrs[j]));
}
  binary.close();


//Read objects from that file through another filestream into a different array of objects
  fstream plrreader("players2.dat", ios::in);
  for (int j=1;j<=400;j++)
    {
      if (plrreader.read((char*)&plrs2[j], sizeof(plrs2[j])))
        {
          cout<<j<<" succesful\n";
        }


    }

  cout<<"Read successful";


//Display objects -- some error here, only 20 players seem to be readable :
  for (int j=1; j<400; j++)
    {
      cout<<"\n"<<plrs2[j].id<<"\nName :"<<plrs2[j].FName<<" "<<plrs2[j].LName<<"\nTeam :"<<plrs2[j].team<<"\n No.:"<<plrs2[j].shirt_no<<"\n Age:"<<plrs2[j].age<<"\n Pos :"<<plrs2[j].pos<<"\n Skill:"<<plrs2[j].skill<<"\n Max goals scored in"<<plrs2[j].goaltime<<"\n Cards"<<plrs2[j].cards;

    }
  plrreader.close();

  return 0;


}

I'm reading from players.txt, storing players in an array of 'plr' objects (plrs).
This seems to be working as expected (all 400 players are displayed correctly)

Then I'm writing these objects using write() to players2.dat. This too, seems to be working (I opened the dat file in notepad, and it has all 400 players)

But when I open the newly created dat file and read the objects into another array of player objects (plrs2), only the first 20 players are read correctly.. The rest are displayed as zeroes..

I've also tried putting the part which reads the objects (line 65 onwards) into another .cpp file, but I get the same result.

I've attached the players.txt file, if anyone needs to run the code..

Please help..

Recommended Answers

All 6 Replies

arrays are always, always indexed beginning from 0, never 1. So line 38 should be for (int i=0;i<401;i++) .

The index values on lines 41 and 42 should be using the loop counter i, not the value of j that was read from the file. What would your program do with a value when j == 500? (Hint: crash!) The value of j should the used as the player's ID, not the index value into the array. You should assume the player's ID has no relationship to the index value used in the array.

arrays are always, always indexed beginning from 0, never 1
...

The index values on lines 41 and 42 should be using the loop counter i, not the value of j that was read from the file.

I made the changes:

#include <fstream>

#include <iostream>

using namespace std;


int main()

{
  class plr
    {
    public:
      int id;
      int shirt_no;
      int age;
      int goals;
      int pos;//0-GK,1-DEF,2-MID,3-ATT
      char LName[51];
      char FName[51];
      int team;
      int skill;
      int goaltime;
      int cards;
      void transfer(int t_id)
      {
        team = t_id;
      }
    }plrs[400],plrs2[400];;



  fstream reader("players.txt", ios::in);
  fstream binary("players2.dat", ios::out);

  //READ FROM TEXT FILE into objects  :
int j;
  for (int i=0;i<400;i++)
    {
      reader>>j;
      plrs[i].id = j;
      reader>>plrs[i].LName>>plrs[i].FName>>plrs[i].team>>plrs[i].shirt_no>>plrs[i].age>>plrs[i].pos>>plrs[i].skill>>plrs[i].goaltime>>plrs[i].cards;


      cout << "\n\n";
    }
  reader.close();

//Display all players
for(int j=0;j<400;j++)
{cout<<"\n\n"<<plrs[j].LName<<"\n"<<plrs[j].FName<<"\n"<<plrs[j].team<<"\n"<<plrs[j].shirt_no<<"\n"<<plrs[j].age<<"\n"<<plrs[j].pos<<"\n"<<plrs[j].skill<<"\n"<<plrs[j].goaltime<<"\n"<<plrs[j].cards;
}

//Write objects to file
for (int j=0;j<400;j++){
binary.write((char*)&plrs[j], sizeof(plrs[j]));
}
  binary.close();


//Read objects from that file through another filestream into a different array of objects
  fstream plrreader("players2.dat", ios::in);
  for (int j=0;j<400;j++)
    {
      if (plrreader.read((char*)&plrs2[j], sizeof(plrs2[j])))
        {
          cout<<j<<" succesful\n";
        }


    }

  cout<<"Read successful";


//Display objects -- some error here, only 20 players seem to be readable :
  for (int j=0; j<400; j++)
    {
      cout<<"\n"<<plrs2[j].id<<"\nName :"<<plrs2[j].FName<<" "<<plrs2[j].LName<<"\nTeam :"<<plrs2[j].team<<"\n No.:"<<plrs2[j].shirt_no<<"\n Age:"<<plrs2[j].age<<"\n Pos :"<<plrs2[j].pos<<"\n Skill:"<<plrs2[j].skill<<"\n Max goals scored in"<<plrs2[j].goaltime<<"\n Cards"<<plrs2[j].cards;

    }
  plrreader.close();

  return 0;


}

But still can't figure out what is really creating the problem

A few problems:

1. There are more than 400 items in players.txt, so you need to increase the size of those two arrays

2. Add the ios::biary flag to the two binary files

3. When reading/writing binary arrays the arrays can be read/written all in one shot -- it is not necessary to write or read them one array element at a time. But sometimes it is more useful to read them one at a time if you don't know how many were written.

4. Move the class plr up above main() so that you can write other functins that use the same class. Almost no programmer will put the class definition within a function because it limits its scop to that one function. Not a very useful thing to do.

5. Instead of that array it would actually be better to use either std::vector or std::list so that you don't have to know how many items are in the files. Buth vector and list grow as you add items to them.

#include <fstream>

#include <iostream>

using namespace std;

  class plr
    {
    public:
      int id;
      int shirt_no;
      int age;
      int goals;
      int pos;//0-GK,1-DEF,2-MID,3-ATT
      char LName[51];
      char FName[51];
      int team;
      int skill;
      int goaltime;
      int cards;
      void transfer(int t_id)
      {
        team = t_id;
      }
      plr() 
      {
          id = shirt_no = age = goals = pos = 
              team = skill = goaltime = cards = 0;
          LName[0] = 0;
          FName[0] = 0;
      }
  };

int main()

{
    plr plrs[402];
    plr plrs2[402];



    ifstream reader("players.txt", ios::in);
    ofstream binary("players2.dat", ios::out | ios::binary);

    //READ FROM TEXT FILE into objects  :
    int i = 0, j = 0;
    while( reader >> j )
    {
      plrs[i].id;
      reader>>plrs[i].LName>>plrs[i].FName>>plrs[i].team>>plrs[i].shirt_no>>plrs[i].age>>plrs[i].pos>>plrs[i].skill>>plrs[i].goaltime>>plrs[i].cards;
      ++i;

    }
    cout << "i = " << i << '\n';
    reader.close();

    //Display all players
    for(int j=0;j<i;j++)
    {
        cout<<"\n\n"<<plrs[j].LName<<"\n"<<plrs[j].FName<<"\n"<<plrs[j].team<<"\n"<<plrs[j].shirt_no<<"\n"<<plrs[j].age<<"\n"<<plrs[j].pos<<"\n"<<plrs[j].skill<<"\n"<<plrs[j].goaltime<<"\n"<<plrs[j].cards;
    }

  binary.write((char *)plrs, sizeof(plrs));
  binary.close();


//Read objects from that file through another filestream into a different array of objects
  ifstream plrreader("players2.dat", ios::in | ios::binary);
  plrreader.read((char*)&plrs2, sizeof(plrs2));
  plrreader.close();
  int nRows = (int)plrreader.gcount() / sizeof(plr);
//Display objects -- some error here, only 20 players seem to be readable :
  for (int j = 0; j < nRows; j++)
   {
      cout<<"j: " << j << ": " <<plrs2[j].id<<"Name :"<<plrs2[j].FName<<" "<<plrs2[j].LName
          <<" Team :"<<plrs2[j].team<<" No.:"<<plrs2[j].shirt_no<<" Age:"<<plrs2[j].age<<" Pos :"
          <<plrs2[j].pos<<" Skill: "<<plrs2[j].skill<<" Max goals scored in "
          <<plrs2[j].goaltime<<" Cards "<<plrs2[j].cards << '\n';
    }

  return 0;


}
commented: thanks +1

Thanks, the program works now.

Yes, there seem to be 401 players in players.txt .. Will check the file later

I tried the code, but all player ids are '0' (as initialized before)
In the first loop

while( reader >> j )
{
plrs[i].id;
..

shouldn't it be reader>>plrs[i].id ?
I tried reader>>plrs[i].id , but it fails to read any player..
Am I missing something?

(As a quick fix I've changed it to plrs[i].id=i+1; )

should have been plrs.id = j;

>>As a quick fix I've changed it to plrs.id=i+1;
Well you changed it wrong. Your original code snippet in your first post was correct for that line.

Thanks.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.