How do I determine the first or last item to iterate over a container?

How do you make the following in a more stylish / short way?

for(i=container.begin(); i!=container.end(); ++i) {
    if (i!=container.begin()) {
        cout << ", ";
    }
    cout << *i;
    j=i;
    if (++j==container.end()) {
        cout << "!" << endl; 
    }
}

      

Solutions like foreach are acceptable (actions for the first and last item must be customizable).

PS There are many answers that handle the first item but not the last one. This is what I mean by processing the last element:

for(i=container.begin(); i!=container.end(); ++i) {
    j=i;
    if (i==container.begin()) {
        cout << "[" << *i << "]" << endl;
    } else if (++j==container.end()) {
        cout << ", (" << *i << ")" << "!" << endl; 
    } else {
         cout << ", " << *i;
    }
}

      

Don't you think it's very easy to handle the first element outside of the loop body? The real problem is the last one! I wish I was able to clarify the important question that the question is asking. I think I'll just agree with the final answer.

+2


a source to share


7 replies


Boost has next / before which can sometimes help in situations like this.

for(i=container.begin(); i!=container.end(); ++i) {
    if (boost::next(i) == container.end()) {
         std::cout << "!" << std::endl;
    }
}

      



Although for this particular case, I just printed out the first element, loop from second to last, always outputting ',' and then outputting '!' after the end of the cycle. (as others have already pointed out)

I see no point in moving special cases inside the loop and then checking for them inside the loop ....

+3


a source


My advice here: there is no point in detecting anything in this loop!

Since your special cases are at the beginning and end of your container, it's easy to remove their handling from the loop.



The following function will print the contents of any container class whose elements may have been <<

'ed before std::ostream

:

template < class Container >
void print(Container const & container)
{
    typename Container::const_iterator current = container.begin();
    typename Container::const_iterator const end = container.end();
    if (current != end)
    {
        std::cout << *current;
        for (++current; current != end; ++current)
        { 
            std::cout << ", " << *current;
        }
        std::cout << "!" << std::endl;
    }
}

      

+3


a source


In your code

if (i==container.end()) {
    cout << "!" << endl; 
}

      

will never happen.

My own approach is to use the container size (I think size () is now constant time across all standard library containers). Count in a loop and you are at the end when count == size () - 1 and at the beginning when count == 0, obviously.

+2


a source


Since container

not defined by you, I used the simplest one -vector

template <class T>
string vector_join( const vector<T>& v, const string& token ){
  ostringstream result;
  for (typename vector<T>::const_iterator i = v.begin(); i != v.end(); i++){
    if (i != v.begin()) result << token;
    result << *i;
  }
  return result.str();
}

//usage
cout << vector_join( container, ", " ) << "!";

      

+2


a source


Change a little ++i

:

i = container.begin();
while(i != container.end()) {
    if (i != container.begin()) {
        cout << ", ";
    }
    cout << *i;
    if (++i == container.end()) {
        cout << "!" << endl; 
    }
}

      

+1


a source


template < class TContainerType>
void print(TContainerType const & i_container)
  {
  typename TContainerTypeconst ::const_iterator current = i_container.begin();
  typename TContainerTypeconst ::const_iterator const end = i_container.end();
  if(current != end)
    {
    std::cout << *current++;
    while(current != end)
      std::cout << ", " << *current++;
     }
  std::cout << "!" << std::endl;
  }

      

+1


a source


Take the second part out of the loop.

for(i=container.begin(); i!=container.end(); ++i) {
    if (i != container.begin()) {
        cout << ", ";
    }
    cout << *i;
}
cout << "!" << endl; 

      

0


a source







All Articles