Reputation: 625
I am working through problems in Accelerated C++ We have a program which stores strings in vectors and outputs them according to certain rules. The original code fragment is as follows.
typedef vector<string> Rule;
typedef vector<Rule> Rule_collection;
typedef map<string, Rule_collection> Grammar;
// read a grammar from a given input stream
Grammar read_grammar(istream& in)
{
Grammar ret;
string line;
// read the input
while (getline(in, line)) {
// `split' the input into words
vector<string> entry = split(line);
if (!entry.empty())
// use the category to store the associated rule
ret[entry[0]].push_back(
Rule(entry.begin() + 1, entry.end()));
}
return ret;
}
We are then asked to use lists instead of vectors.
So all the vectors above will now become lists.
The bit I am stuck on is how to deal with the line beginning ret[entry]].push_back etc. Also what to put in after Rule... I have tried using entry.begin() but that doesn't work.
Any assistance would be appreciated.
Upvotes: 1
Views: 5025
Reputation: 37364
You will need to replace your code with something like this:
ret[*(entry.begin())].push_back(
Rule(++(entry.begin()), entry.end()));
Upvotes: 0
Reputation: 146910
This code is pretty generic- it should just work when you change the typedefs, except a couple of minor niggles like std::list
does not give random-access iterators, and since you don't show the code I can't speak about split
.
Upvotes: 0
Reputation: 31435
with list you can perform most of the operations you can with vector but you cannot use entry[0]
as there is no random-access.
entry.front()
will get that element instead.
Also you cannot add 1 to entry.begin()
because it is bi-directional and does not support +, but you can assign it to a temporary iterator then ++it
.
Upvotes: 2
Reputation: 26060
ret[entry[0]]
calls Grammar::operator[]
passing it a string
: the string contained in entry[0]
, which is the first string put in such vector by split
.
Supposing that split
returns a std::list
, you should just take the first element of the list:
ret[ entry.front() ] ... // where entry is a std::list<string>
Upvotes: 0
Reputation: 5425
begin()
gives you an iterator to the beginning of the list. You could dereference the iterator, which gives you the first value...
ret[*(entry.begin())].push_back(...
Or you could use the front()
function, which returns the element at the front of a list (technically a reference, but should work in this case).
ret[entry.front()].push_back(...
EDIT:
As others have pointed out, this works provided entry
is a std::list<string>
, as you implied.
Upvotes: 0
Reputation: 5211
entry.begin ()
returns an iterator to the start of the list, whereas
entry [0]
for vector returns the first element, so I think you want something like the following
*(entry.begin ())
EDIT:
Hopefully I understood what you are asking... Other than that begin and end should return comparable values for both vector and list
Upvotes: 1