Creating ifstream variables at run time in C++?

In summary: Where istream& operator>>() takes an input stream as its first parameter, and a pointer to a charList object as its second parameter. This function will iterate through the list of input files, reading each one into a byte array called ch, and then calling the function incrCount() on each entry. This function will then set the pointer to cl to point to the next entry in the list, and return cl.
  • #1
John O' Meara
330
0
How do you make a number of input file streams, one for each input file so that can copy/append the contents of these files to one output file? The number of input files is only known at run time and varies from run to run of the program. The input file names are first stored in a linked list. Would you use RTTI?

Code:
 int main()
...
charList *ptrFile;
charList filesin; 
ptrFile = &filesin;  // is the linked list object
ifstream ifs;

ofstream ofs;

...

for (int i = 0; i <  ptrFile->getCount(); i++) {
  ifs.open(ptr->getValue(), ios::in);
  ...
  copyFile(ifs, ofs); // copy contents of an input file to the output file
  ifs.close():
  ptrFile = ptrFile->getNextEntry();
}
ofs.close();
return 0;
}
where: getCount(), getValue() and getNextEntry() are member functions of charList, a linked list of input file names. Any suggestions would be appreciated.
 
Physics news on Phys.org
  • #2
Hey John O' Meara.

I don't think you need any kind of C++ specific functionality for this exercise.

If you are just opening a bunch of files and appending the contents of all files to an output file in the order that they are given, then a loop similar to what you have written should be more than sufficient.

Whatever interface you use for files whether it be the standard file library (fopen, fclose, etc), the Windows Functionality (OpenFile, etc) or some other wrapper library with that functionality, the only thing you will need to remember for each iteration of the loop is a file handle, and at most some kind of temporary buffer to grab data from one file and then throw it into another.

You may however, have to do multiple reads of the input file if the temporary buffer you are using is too small, but you can create a simple function to do a loop to do that (and there is probably a function to do it for you but it's pretty straight forward).

Is there any other kind of purpose you are thinking of including (are you thinking about adding new functionality or extending the code in some way)?
 
  • #3
Hi chiro, thanks for replying.

As the code I have written stands, it refuses to increment i in the for loop and it only adds the first file entered to the output file; so I was thinking that I needed a separate ifstream object for each input file. and so I thought that the code was wrong. If I add the following piece of code in the proper place to the code I have already given
Code:
 if (!ifs.good()) {
  cout << "A file error occured.\n"; }
g++ gives the above error after appending the first input file to the output file; while a C++ compiler runs without giving this error but still refuses like I said to increment to loop variable i. I don't entend to add any more functionality to this code. As you say I just want to open a bunch of files and append the contents of all files to one output file. I might find this routine handy for future use in something else, though at the moment I have nothing particular in mind. Thanks again.
 
  • #4
Ohh I see what you are getting at.

You need to look at if your linked list object has a standard iterator, and if you are using a template class, then look at if that has an iterator (things like linked list in C++ usually do) and if they do, see what it is and its implementation.
 
  • #5
This is the linked list:
Code:
class charList {
 char value[80];
 charList *nextEntry;
 int count;
public:
  charList() { count = 0; }
  charList(char *v, charList *next) : nextEntry(next), count(0)
  { strcpy(value, v);  }

   char *getValue() { return value; }
   charList *getNextEntry() { return nextEntry; }
   int getCount() { return count; }
   void incrCount() { count++; }
   void addToEndM(char *str);
};

 void charList::addToEndM(char *str)
 {
  if (nextEntry !=NULL)
     nextEntry->addToEndM(str);
   else
      nextEntry = new charList(str, NULL);
 }

 istream& operator>>(istream& is, charList *&cl)
{
   charList *cp = NULL;
   char ch[80];

    cin >> ch;
    while (ch[0] != '!') {
      if (cp != NULL) {
        cp->addToEndM(ch);
       else {
          cp = new charList(ch, cp);
          cp->incrCount();
       }
       cout << "Enter another file to copy: ";
       cin >> ch;
       cp->incrCount();
     }
     cl = cp;
     return is;
  }
As you can see I am not using templates or iterators, just basic C-strings etc.
 
  • #6
I have a recommendation for you: lots of experienced programmers would look at that and go absolutely ape if they say that kind of code, but I'm going to just make a recommendation without getting too anal.

The recommendation I have is that you implement a set of routines for an iterator: basically a routine that signals to start an iteration, and a routine that returns the next object that does an internal increment (which returns a null pointer if nothing is left).

This is the absolute basics of an iterator. It's good design to have the iterator separate from the class, but it would be very straight-forward to just add these routines to your linked list class and add an extra variable that corresponds to the iterator.

You might wonder what the point of this is and the answer is simple: if you want to iterate through things and have the possibility that the list is changed somehow (either by something within the iteration loop itself or through some sub function in call-stack, or through multi-threaded environments) then you want the iterator to act correctly when all this happens.

At the very least, just add a routine that initializes the iterator and then increments a separate iterator variable to go through the list and return the pointer to the next object with doing the right increment.

What you do this setup is that you setup a while loop (so a while loop as opposed to a do). Something like this:

Code:
LinkedListClass* class = whatever; // Assuming whatever is valid
whatever->InitializeIterator();
ObjectType* objectInstance = NULL;

// Method stores the value of the object in the pointer passed and returns 
// a non-zero return if OK and zero if not.
while(whatever->ReturnNextIteratorObject(&objectInstance))
{
   // Do stuff blah blah with objectInstance
};

I'd recommend that if you are going to be using these kinds of container and template classes that you develop a separate iterator object that allows you to have an interface for iteration: this way you can keep the interface and if you need to change what happens behind the scenes due to changing environments, then you can keep the interfaces without having to change all the code that calls these interfaces.

You get some new programmers that think interfaces are over-kill, but one of the reasons why you want to know what the interface is has to do with when you get into development for a long time and then suddenly realize you need to change a core thing and you nearly lose it if you haven't used the right interfaces (it's easy to change what happens what is underlying the interfaces, but it's a pain to create new ones that are significantly different in what functionality they provide especially if they require major changes).
 
  • #7
Thank you for your recommendations and patience. I have an old book on: "Programming with class A C++ Introduction to Computer science" that I only got around to this year looking at, I guess it is out of date, though I must say that I have found it interesting, but it doesn't do iterators and only mentions templates in an appendix; so the given problem implied that it could be solved without containers, templates or iterators, I would think? It is only for myself that I am doing this computer programming, It will ever only be a hobby with me. Thank you again.
 

1. How do I create an ifstream variable at run time in C++?

To create an ifstream variable at run time in C++, you can use the "ifstream" keyword followed by the variable name and an equal sign, and then use the "open()" function to specify the file you want to open. For example: ifstream myFile; myFile.open("filename.txt");

2. Can I use a variable to specify the file name when creating an ifstream variable?

Yes, you can use a variable to specify the file name when creating an ifstream variable. This allows you to open different files based on user input or other conditions.

3. How do I check if an ifstream variable has successfully opened a file?

You can use the "is_open()" function to check if an ifstream variable has successfully opened a file. This function will return a boolean value, where true indicates that the file has been opened successfully and false indicates that there was an error in opening the file.

4. Can I create multiple ifstream variables at run time?

Yes, you can create multiple ifstream variables at run time. Each variable can be used to open a different file, or you can use the same variable to open multiple files by closing the previous file before opening a new one.

5. How do I close an ifstream variable in C++?

To close an ifstream variable in C++, you can use the "close()" function. This will close the file associated with the variable and free up any system resources used by the ifstream object. It is good practice to always close a file after you are done using it.

Similar threads

  • Engineering and Comp Sci Homework Help
Replies
1
Views
3K
  • Engineering and Comp Sci Homework Help
Replies
5
Views
2K
  • Engineering and Comp Sci Homework Help
Replies
4
Views
1K
  • Engineering and Comp Sci Homework Help
Replies
3
Views
2K
  • Programming and Computer Science
Replies
0
Views
511
  • Engineering and Comp Sci Homework Help
Replies
1
Views
2K
  • Engineering and Comp Sci Homework Help
Replies
15
Views
2K
  • Programming and Computer Science
4
Replies
118
Views
6K
  • Programming and Computer Science
3
Replies
70
Views
3K
  • Programming and Computer Science
3
Replies
75
Views
4K
Back
Top