Solved

ifstream array

Posted on 2002-07-25
17
1,092 Views
Last Modified: 2012-06-27
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


0
Comment
Question by:elstcb
  • 10
  • 4
  • 3
17 Comments
 
LVL 3

Expert Comment

by:abusimbel
Comment Utility
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.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
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.
0
 
LVL 2

Author Comment

by:elstcb
Comment Utility
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 <=.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>>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.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>>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.
0
 
LVL 3

Expert Comment

by:abusimbel
Comment Utility
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.
0
 
LVL 30

Accepted Solution

by:
Axter earned 50 total points
Comment Utility
You can use pointers instead.
Example:

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

     for (int d=0; i<6; i++)delete fin[d];
     system("pause");
     return 0;
}

0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
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....
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 30

Expert Comment

by:Axter
Comment Utility
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.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
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;
}

0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
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.
0
 
LVL 3

Expert Comment

by:abusimbel
Comment Utility
Axter, Could you divide the answer in more fragments?

;-)

Bye,
Abusimbel.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>>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....
0
 
LVL 2

Author Comment

by:elstcb
Comment Utility
wow that's a lot of replies...!

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

Thanks,

Steve
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
elstcb,
Did the comment I post fix the problem?
0
 
LVL 2

Author Comment

by:elstcb
Comment Utility
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
0
 
LVL 2

Author Comment

by:elstcb
Comment Utility
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
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

762 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

Need Help in Real-Time?

Connect with top rated Experts

6 Experts available now in Live!

Get 1:1 Help Now