I am importing object files and making tables from the for a project due tommorow night. The function works fine when I use it the first time i.e. input pro1.txt, but when I call the function again and input pro2.txt as the file name my program crashes. All of the text files are in the same folder as the code. Any help to where I screwed up would be greatly appreciated! My code is:

void readFile(Object pObject[], int &p){

    double distance[100];
    double height[100];
    string name[7];

    ifstream file;
    string s;
    int t=0;


    cout << "Please enter the file name: ";
    cin >> s;
    cout<<endl;

    file.clear();
    file.open(s.c_str());

    if (file.fail()){
        cout << "ERROR: file does not exist or corrupted file!" <<endl;

    }
    else if (!file.fail()){
    while(!file.eof()){
        file >> name[p] >>distance[p] >>height[p];
        if(!file.eof()){
            t++;
            p++;

        }
    }

    file.close();

        cout << "        Object" << endl;
        cout << "Distance     " << "Height" << endl<<endl;
        for (int q=0; q<p;q++) cout << setw(8) <<name[q] << setw(8) <<distance[q] <<setw(11)<< height[q] <<endl;

        cout << endl;
        cout << t <<" objects read"<<endl;
        cout << p << " objects in database"<<endl<<endl;
}
}

Edited 3 Years Ago by Nick Evan: Fixed formatting

try calling file.clear() after the file is read and before you close it. It's easy to do. It might work. It might not.

don't use the return result of eof() to determine whether the body of the loop will be entered.

I tried the file.clear() and it didn't work. I also need the eof() to make it read every line of the txt files. A text file looks like:

Object1 0.500 1.500
maybe2 1.500 6.000
Ob3 3.000 1.000
thing4 3.200 2.300

if that helps.

The problem is paramter "p" to the function. Since it's passed by reference, and if you don't reset it (as I assume you don't want to), it comes back into the function at a value greater than 0. Actually, it will be 4 with the data you show. When you call the function again, you're using that to read into the string array name[] (of size 7), so you end up going off the end of that array after reading through the second file set.

Here's the relevant portion of your code, fixed up some. I've removed the excess eof( ) tests, and a couple other things. The file.clear( ) not needed, especially before opening the file.

file.open(s.c_str());

   if (file.fail())
   {
      cout << "ERROR: file does not exist or corrupted file!" <<endl;
   }
   else //if it didn't fail, it succeeded, no test needed
   {
      while(file >> name[t] >>distance[t] >>height[t])//use t here, till you pass in the actual
                                                                                 //data array
      {
         t++;
         p++;
      }
   }

   file.close();

   cout << " Object" << endl;
   cout << "Distance " << "Height" << endl<<endl;
   for (int q=0; q<t;q++) //use t - it's the local count read in
      cout << setw(8) <<name[q] << setw(8) <<distance[q] <<setw(11)<< height[q] <<endl;

cout << " Object" << endl;
cout << "Distance " << "Height" << endl<<endl;
for (int q=0; q<t;q++) //use t - it's the local count read in
cout << setw(8) <<name[q] << setw(8) <<distance[q] <<setw(11)<< height[q] <<endl;

On this part I would like to print out the data from the whole database, so I try to use p instead of t and it doesn't work. When there is q<t, it only prints out the info from that file.

Edited 3 Years Ago by Reverend Jim: Fixed formatting

don't use the return result of eof() to determine whether the body of the loop will be entered.

Why is it people just say something without explanation? Why should they listen if there doesn't seem to be a reason?

Lerner is correct, and here's why. feof() is the same as .eof()

thanks for the explanation. Do you know how to solve my other problem?

On this part I would like to print out the data from the whole database, so I try to use p instead of t and it doesn't work. When there is q<t, it only prints out the info from that file.

If you were in fact storing to the database ( pObject array) then index p would work. In the code you provided, you are storing to a small local array allocated in the function, so your bounds on that must be distinct from the supposed position in the database array.

You need to make one of two changes to your code

A. use the database array elements as the target for the read operations.
or
B. read to the local variables as you do, then copy them to the database array.

I tried to make the changes but it won't work.

My Object class is defined here:

Object pObject[100];

Object::Object(){
    distance = 0;
    height  = 0;
}

Object::Object(string n, double d, double h){
    n = name;
    d = distance;
    h = height;
}

void Object::setName(string name2){name=name2;}

string Object::getName(){return name;}

void Object::setDistance(double d1){distance=d1;}

void Object::setHeight(double h1){height=h1;}

double Object::getHeight(){return height;}

double Object::getDistance(){return distance;}

My new code for the readfile is:

void readFile(Object pObject[], int &p){

    double distance[100];
    double height[100];
    string name[7];

    ifstream file;
    string s;
    int t=0;


    cout << "Please enter the file name: ";
    cin >> s;
    cout<<endl;

    file.clear();

      file.open(s.c_str());

      if (file.fail())

      {

      cout << "ERROR: file does not exist or corrupted file!" <<endl;

      }

      else //if it didn't fail, it succeeded, no test needed

      {

      while(file >> name[t] >>distance[t] >>height[t])//use t here, till you pass in the actual

      //data array

      {

      t++;

      p++;

      }

      }



      file.close();
      pObject[p].setName(name[t]);
      pObject[p].setDistance(distance[t]);
      pObject[p].setHeight(height[t]);



      cout << "                    Object" << endl;

      cout << "Name        "<<"Distance     " << "Height" << endl<<endl;

      for (int q=0; q<p;q++) //use t - it's the local count read in

      cout <<fill(pObject[q].getName(),7) << setw(13) <<pObject[q].getDistance() <<setw(11)<< pObject[q].getHeight() <<endl;

        cout << endl;
        cout << t <<" objects read"<<endl;
        cout << p << " objects in database"<<endl<<endl;

}

Now my table is blank. I am trying to fill the pObject array and print out the name, distance, and height of all of my objects from multiple input files.

Edited 3 Years Ago by Nick Evan: Fixed formatting

in the loop - read data into single string, distance, height variables.

If you need to validate them, do so.

Then assign them to the data members of pObject[p], within the loop.

What you've just posted will read through the file, storing again to the local arrays. The assignment to pObject you do after the loop is going to store local_array[t] values, which hold nothing, as t has been incremented.

Walk through the process by hand, follow where values get modified and what value they have at the points you use them.

thanks, I got them to work when I put in the first set of opjects, but now when I read the 2nd txt file my program crashes agian. I am new to readfiles and strings so I am a little slow with this stuff. Here is my file now:

void readFile(Object pObject[], int &p){

    double distance[100];
    double height[100];
    string name[7];

    ifstream file;
    string s;
    int t=0;


    cout << "Please enter the file name: ";
    cin >> s;
    cout<<endl;

    file.clear();

      file.open(s.c_str());

      if (file.fail())

      {

      cout << "ERROR: file does not exist or corrupted file!" <<endl;

      }

      else{
      while(file >> name[t] >>distance[t] >>height[t]){
      pObject[p].setName(name[p]);
      pObject[p].setDistance(distance[p]);
      pObject[p].setHeight(height[p]);

      t++;
      p++;

      }
      }
      file.close();

      cout << "                    Object" << endl;

      cout << "Name        "<<"Distance     " << "Height" << endl<<endl;

      for (int q=0; q<p;q++)

      cout <<fill(pObject[q].getName(),7) << setw(13) <<pObject[q].getDistance() <<setw(11)<< pObject[q].getHeight() <<endl;

        cout << endl;
        cout << t <<" objects read"<<endl;
        cout << p << " objects in database"<<endl<<endl;

}

Edited 3 Years Ago by Nick Evan: Fixed formatting

Thanks. Now when I input the 1st text file everything works, but when I input a 2nd text file my program crashes. I am new to this so I am a little slow as you can see. Here is what my function looks like now:

void readFile(Object pObject[], int &p){

    double distance[100];
    double height[100];
    string name[7];

    ifstream file;
    string s;
    int t=0;


    cout << "Please enter the file name: ";
    cin >> s;
    cout<<endl;

    file.clear();

      file.open(s.c_str());

      if (file.fail())

      {

      cout << "ERROR: file does not exist or corrupted file!" <<endl;

      }

      else{
      while(file >> name[t] >>distance[t] >>height[t]){
      pObject[p].setName(name[p]);
      pObject[p].setDistance(distance[p]);
      pObject[p].setHeight(height[p]);

      t++;
      p++;

      }
      }
      file.close();

      cout << "                    Object" << endl;

      cout << "Name        "<<"Distance     " << "Height" << endl<<endl;

      for (int q=0; q<p;q++)

      cout <<fill(pObject[q].getName(),7) << setw(13) <<pObject[q].getDistance() <<setw(11)<< pObject[q].getHeight() <<endl;

        cout << endl;
        cout << t <<" objects read"<<endl;
        cout << p << " objects in database"<<endl<<endl;

}

If I understand your project correctly you have declared a user defined type called Object. Each object has three member variables. In main() you want to declare an array of Objects to act as a data base. You want to fill the database with information from two, or more, different files.

If that is a reasonable summary of the project then you don't the variable t in the readFile() function at all. If p is assigned the value 0 before the first call to readFile() then readFile() could look something like this:

void readFile(Object pObject[], int &p)
{
  double distance;
  double height;
  string name;
  ifstream file;
  string s;

  cout << "Please enter the file name: ";
  cin >> s;
  cout<<endl;

  file.open(s.c_str());

  if (file.fail())
  {
    cout << "ERROR: file does not exist or corrupted file!" <<endl;
  }
  else
  {
    while(file >> name >>distance >>height)
    {
       pObject[p].setName(name);
       pObject[p].setDistance(distance);
       pObject[p].setHeight(height);
       p++;
    }
  }
  file.close();
}

Note that there is no way to tell whether you are overfilling the database or not with this code. It will need to be modified in order to prevent that from happening. To do that, check that p is less than or equal to the largest valid index the database can use. How you get that information to the function is up to you. Often it is passed as a separate parameter to the function. But there are other ways as well.

And you're mixing up your p's and t's again!

while(file >> name[t] >>distance[t] >>height[t])
{
   pObject[p].setName(name[p]); // use name[[b]t[/b]]
   pObject[p].setDistance(distance[p]); // use distance[[b]t[/b]]
   pObject[p].setHeight(height[p]);  // use heignt[[b]t[/b]]
   t++;
   p++
}
This question has already been answered. Start a new discussion instead.