Link to home
Start Free TrialLog in
Avatar of elstcb
elstcb

asked on

ifstream array

Hi all, hopefully a nice easy one.

My program has 6 input files, each of which is loaded a line at a time, the data in each is processed and output to a different file until the end of all the input files is reached.

How and what it does isn't really important, however at the minute I have the following:

  ifstream fin0(m_file_paths[1]);
  .
  .
  ifstream fin5(m_file_paths[6]);

  fin0.getline(line, 500, '\n');
  .
  .
  fin5.getline(line, 500, '\n');


What I'd like to do is something like the following (0 is used seperately):

  ifstream fin[6];
  for (i=1; i<6; i++)
  {
    fin[i] = ifstream(m_file_paths[i]);
  }

and then get data using something like:
  fin[1].getline(line, 500, '\n');

The declarations seem to work ok, however it falls over on the getline (which works when they're not in arrays) with the standard "unable to read memory at" error dialogue...

Any ideas where I'm going wrong?

Thanks in advance,

Steve


Avatar of abusimbel
abusimbel

This is a very common error, you are out of the array by 1:

The loop should go from 0 to 5 and not in 1 to 6 because in the momment you'll try to access    fin[6] you'll have a memory exception and in the momment you'll try to acces fin[0] you'll have a non initilized stream.

Remember:

ifstream fin[6];

Has as members:

fin[0]
fin[1]
fin[2]
fin[3]
fin[4]
fin[5]

Bye,
Abusimbel.
Avatar of Axter
Although some compilers like VC++ 6.0, allows you to use the copy constructor for (ios) type, this is not allowed according to the C++ standard.
If your compiler was working properly, it would have given you a compiler error.
Avatar of elstcb

ASKER

That's _NOT_ my problem - As stated originally I'm only using 1 to 5 in my loop because I use 0 differently to the rest. Hence the i<6 rather than <=.
>>That's _NOT_ my problem - As stated originally I'm only >>using 1 to 5 in my loop because I use 0 differently to
>>the rest. Hence the i<6 rather than <=.

That is also a problem.
>>That's _NOT_ my problem - As stated originally I'm only
>>using 1 to 5 in my loop because I use 0 differently to
>>the rest. Hence the i<6 rather than <=.

That is not the reason you're getting an error.
That paticular problem will only stop you from accessing the first ifstream.  It's not making you reach pass the arrray, because you have (<6) in your for loop.

The real problem that is causeing the error you reported is what I have already posted in my first comment.
Ok if the array is not the problem, then as Axter said you can use instead:

fin[i] = ifstream(m_file_paths[i]);

fin[i].open(m_file_paths[i]);

And you will avoid the copy constructor.

Another posibility is to use pointers instead objects in the array, but the open should work perfectly.

Bye,
Abusimbel.
ASKER CERTIFIED SOLUTION
Avatar of Axter
Axter
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
A more elagant approach would be to create a small class that can do job where the variable gets declared.

Example:

class Myifstream : public ifstream
{
public:
     Myifstream(const char* FileName) : ifstream(FileName){}
};



int main(int argc, char* argv[])
{
     char line[6][501];
     Myifstream fin[6] = {"c:\\test1.cpp", "c:\\test2.cpp", "c:\\test3.cpp", "c:\\test4.cpp", "c:\\test5.cpp", "c:\\test6.cpp"};
     for (int i=0; i<6; i++)
     {
          fin[i].getline(line[i], 500);
     }

     return 0;
}


Continue....
In my above posted example, you don't need to iterate through fin[] to initialize it and open the file.
It's all done in one line:
Myifstream fin[6] = {"c:\\test1.cpp", "c:\\test2.cpp", "c:\\test3.cpp", "c:\\test4.cpp", "c:\\test5.cpp", "c:\\test6.cpp"};


So in one line, you declare the variable, pass the file name, and open the file.
If you need to use m_file_paths member function in order to open the file, you can still do that with the above class.
Example:
int main(int argc, char* argv[])
{
     char line[6][501];
     char m_file_paths[6][32]  = {"c:\\test1.cpp", "c:\\test2.cpp", "c:\\test3.cpp", "c:\\test4.cpp", "c:\\test5.cpp", "c:\\test6.cpp"};
     Myifstream fin[6] = {m_file_paths[0], m_file_paths[1], m_file_paths[2], m_file_paths[3], m_file_paths[4], m_file_paths[5]};
     for (int i=0; i<6; i++)
     {
          fin[i].getline(line[i], 500);
     }

     system("pause");
     return 0;
}

One last point.
In most cases, it's better to use the member function, then to use a global function.
However, getline function is an exception to the rule.
That's because the getline member function does not have an overloaded function that can take a std::string object directly.
However, the global std::getline function does have this method.
So your code could look like this instead.
int main(int argc, char* argv[])
{
     string line[6];
     char m_file_paths[6][32]  = {"c:\\test1.cpp", "c:\\test2.cpp", "c:\\test3.cpp", "c:\\test4.cpp", "c:\\test5.cpp", "c:\\test6.cpp"};
     Myifstream fin[6] = {m_file_paths[0], m_file_paths[1], m_file_paths[2], m_file_paths[3], m_file_paths[4], m_file_paths[5]};
     for (int i=0; i<6; i++)
     {
          getline(fin[i], line[i]);
     }

     system("pause");
     return 0;
}


By using std::string, you don't have to allocate a big block array variable like the following:
char line[6][501];

More then likely, most of the memory will go to waste, because most lines fall between 2-80 charactors.
But if you use std::string, it will only allocate as much memory as required for the paticular line being read.
Axter, Could you divide the answer in more fragments?

;-)

Bye,
Abusimbel.
>>Axter, Could you divide the answer in more fragments?

I was making separate points, and I was affraid I would loose the reader if I put it all in one big chunk.

And my last comment really didn't have to much to do with the original question.  Just FYI....
Avatar of elstcb

ASKER

wow that's a lot of replies...!

I'm not at work any more but I'll give it a go tomorrow.

Thanks,

Steve
elstcb,
Did the comment I post fix the problem?
Avatar of elstcb

ASKER

Sorry I haven't posted back for a few days, I haven't been able to get access to the file I need to try it out. I should have access again later today or tomorrow so I'll get back to you then.

Steve
Avatar of elstcb

ASKER

Thanks it worked a treat. Whilst the other stuff was probably "more elegant" as you put it, it was a bit over my head!

Sorry for the delay in getting back.

Thanks again,

Steve