#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
int main()
{
std::string from, to;
std::cout << "Please enter name of input file with the extension\n""The file must already exist.\n";
std::cin >> from;
std::ifstream is{ from };
if (!is)
{
std::cout << "Could not open file: " << from << "\nprogram terminating" << '\n';
system("pause");
return 1;
}
std::cout << "\nPlease enter name of output file\n""If the file already exists it will be replaced \n";
// File name should include its extension too
std::cin >> to;
std::ofstream os{ to };
if (!os)
{
std::cout << "Could not open file: " << to << "\nprogram terminating" << '\n';
system("pause");
return 1;
}
std::istream_iterator<std::string> ii{ is };
std::istream_iterator<std::string> eos;
std::ostream_iterator<std::string> oo{ os, "\n" };
// Saving on the working directory of that project
std::cout << "\nAttempting to read from file " << from << '\n';
std::vector<std::string> b{ ii,eos };
std::cout << "Number of words read = " << b.size() << '\n';
std::cout << "Sorting...\n";
sort(b.begin(), b.end());
std::cout << "\nWriting sorted words to output\n";
copy(b.begin(), b.end(), oo);
std::cout << "\nThese are the words after sorting:\n\n";
for (autoconst& b1 : b)
std::cout << b1 << ' ';
std::cout << "\n\n";
system("pause");
return 0;
}
1) On line 37: std::istream_iterator<std::string> ii{ is }; the type input stream iterator ii is initialised by is which is of type "input file stream"! How do these two types match?
2) On line 39: std::ostream_iterator<std::string> oo{ os, "\n" }; the iterator oo is initialised by two things, on and "\n". I'm not confident I undestand it well.
3) On line 44: std::vector<std::string> b{ ii,eos }; the interator ii is the beginning but for the vector to match its end to nullptr to work properly, eos should be nullptr, whilst it's empty here! I don't understand it either!
Constructs an istream iterator that is associated with stream s (the object does not own or copy the stream, only stores a reference).
Constructs an ostream iterator that is associated with stream s (the object does not own or copy the stream, only stores a reference).
If delimiter is specified, and is not a null pointer, it is inserted after every element is inserted in the stream.
3)
1 2
vector (InputIterator first, InputIterator last,
const allocator_type& alloc = allocator_type());
That last iterator is pointing to one beyond the last element in the vector. If it can not be a nullptr, then how can the loops recognize the end of the vector when dealing with its data?
That last iterator is pointing to one beyond the last element in the vector. If it can not be a nullptr, then how can the loops recognize the end of the vector when dealing with its data?
Remember that iterators are similar to pointers, so if the "loop counter" (an iterator) is equal to end() (another iterator) the loop is finished. The loop is comparing "addresses" not values.
Yeah, right, good point.
Yes, I've specifically recently been toying with STL containers within my forgoing threads, myVec, mySet etc.
So in those containers we set begin() to point to the first element and end() to one beyond the last one. Both iterators have their own addresses. Therefore when the loop reaches the address assigned to end(), it stopes and ...
As well as, eos has merely been declared not initialized, hence lacks an address!
As well as, eos has merely been declared not initialized, hence lacks an address!
If the program actually compiled, it would have "address", some random address but an address in any case. But since the program doesn't seem to compile I don't really understand what your problem actually is.
The program compiles perfectly on my VS 2019 (using C++ 17).
The question is, on line 44 a vector is created using two iterators, one pointing to the file stream, ii, to be used as begin() for the vector, and the other some iterator conveying some address, eos, to be used for as end() for the vector!!! These begin() and end() have been applied by sort() on line 49! And then the values are printed by them on line 55! :(
The question is, how using an iterator conveying a random address does the vector pinpoint the end of its range!?
end() should specifically point to the element one past the last one, but here eos points to somewhere. Who knows it's the end of the container? God knows what address it points to!
The program compiles perfectly on my VS 2019 (using C++ 17).
Different systems will include different headers from other headers. Your system is including <iterator> and <string> from one or more of the headers you've included. Other systems may not do that since it is not part of the standard. Since you are using std::istream_iterator, etc., you should explicitly include <iterator>. And since you are using std::string you should explicitly include <string>.
God knows what address [eos] points to!
It's doesn't point to a random address. It doesn't point into the vector at all if that's what you're thinking (the vector iterators and istream iterators are different things). The default istream_iterator constructor is called for eos which initializes the iterator object to whatever it needs to "point" to the end of the stream. What exactly that is depends on how it's implemented. One possibility is that when you pass an istream the iterator stores a pointer to that istream object. When you don't pass an istream (therefore calling the default constructor) it just stores a nullptr instead. Then all the iterator needs to do to implement eof detection at the iterator level is to change the istream pointer in the iterator to nullptr when eof is detected. Then it will equal the end-of-stream iterator.
The vector constructor that takes a begin and end iterator (of whatever kind) presumably does something like:
1 2 3 4 5 6
// pseudocode:
vector(iterator begin, iterator end)
{
for (iterator it = begin; it != end; ++it)
push_back(*it)
}
And the istream iterator might look something like the following. It needs a little more detail than this to be fully generalized type-wise (it should inherit from std::iterator, for instance) but this is pretty close to the real thing.