Using istream_iterator and reading from standard input or file

I write in Microsoft Visual C ++, and I would like my program to read from standard input or a file using istream_iterator . Googling the internets did not show how simple I think it should be. So, for example, I can write this quite easily and read from standard input:

 #include <iostream> #include <string> #include <iterator> using namespace std; int main() { istream_iterator<string> my_it(cin); for (; my_it != istream_iterator<string>(); my_it++) printf("%s\n", (*my_it).c_str()); } 

Or I can write this and read from a file:

 #include <iostream> #include <string> #include <iterator> #include <fstream> using namespace std; int main(int argc, char** argv) { ifstream file(argv[1]); istream_iterator<string> my_it(file); for (; my_it != istream_iterator<string>(); my_it++) printf("%s\n", (*my_it).c_str()); } 

But how can I combine these two so that a simple check (argc == 2) allows me to initialize my input stream iterator with either a file stream or stdin, and continue my fun way?

+4
source share
4 answers

You can assign to an iterator after creating it:

 int main(int argc, char** argv) { ifstream file; istream_iterator<string> my_it; if(argc == 2) { file.open(argv[1]); my_it = istream_iterator<string>(file); } else { my_it = istream_iterator<string>(cin); } } 
+10
source

This small snippet will give you an istream input , which can be either a file or std :: cin.

 std::ifstream filestream; if ( use_file ) filestream.open( ... ); std::istream &input = use_file ? filestream : std::cin; 

Now you can use input without worrying about what source the input comes from.

+1
source

At first glance, the simplest solution would be to use the ternary operator ?: As follows:

 istream_iterator<string> my_it( (argc == 2) ? ifstream(argv[1]) : cin ); 

However, this will not work because it creates a temporary ifstream object that will be destroyed at the end of the statement. So you need a way to conditionally create an ifstream and conditionally destroy it after the for loop. std::auto_ptr<> matches the count. Thus:

 auto_ptr<ifstream> file((argc == 2) ? new ifstream(argv[1]) : NULL); istream_iterator<string> my_it( (argc == 2) : *file : cin); for (; my_it != istream_iterator<string>(); my_it++) printf("%s\n", (*my_it).c_str()); 

Another, possibly cleaner solution, is to move the iteration into a separate function that accepts istream& .

I saw this problem before it was online, which is covered by one of the great C ++. Unfortunately, I don’t remember exactly where, or by whom! I think it was on DDJ, maybe Sutter or Alexandrescu?

+1
source

You mean something like this: (using pointers)

 #include <iostream> #include <string> #include <iterator> #include <fstream> using namespace std; int main(int argc, char** argv) { istream_iterator<string>* my_it = NULL; if (argc == 2) { ifstream file(argv[1]); my_it = new istream_iterator<string>(file); } else { my_it = new istream_iterator<string>(cin); } ... delete my_it; } 

I have not tested this. This is what you need?

0
source

All Articles