Steblo
Steblo

Reputation: 625

How to access elements in a list in c++

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

Answers (6)

a1ex07
a1ex07

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

Puppy
Puppy

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

CashCow
CashCow

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

peoro
peoro

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

James
James

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

vmpstr
vmpstr

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

Related Questions