[Home] [Downloads] [Search] [Help/forum]


Register forum user name Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to "verify" your details, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.
 Entire forum ➜ Programming ➜ STL ➜ Example - using vectors

Example - using vectors

It is now over 60 days since the last post. This thread is closed.     Refresh page


Posted by Nick Gammon   Australia  (23,046 posts)  Bio   Forum Administrator
Date Fri 04 Jul 2003 06:07 AM (UTC)

Amended on Wed 30 Aug 2006 02:56 AM (UTC) by Nick Gammon

Message
Vectors are handy things for simple lists where you want random access (eg. for sorting, shuffling and so on).

The example below illustrates various things you can do with vectors. I have used vectors of strings so I can also play with case-independent sorts, sort descending, appending to each item, and so on.

Notice the difference the case-independent sort makes on the words "the" and "The". For case-independence they are together, otherwise they are at opposite ends of the sentence.




// disable warnings about long names
#ifdef WIN32
  #pragma warning( disable : 4786)
#endif

#include <string>
#include <vector>
#include <iostream>
#include <functional>
#include <iterator>
#include <algorithm>

using namespace std;

// case-independent (ci) string less_than
// returns true if s1 < s2
struct ci_less : binary_function<string, string, bool>
  {

  // case-independent (ci) compare_less binary function
  struct nocase_compare : public binary_function<unsigned char,unsigned char,bool> 
    {
    bool operator() (const unsigned char& c1, const unsigned char& c2) const 
      { return tolower (c1) < tolower (c2); }
    };

  bool operator() (const string & s1, const string & s2) const
    {
  
    return lexicographical_compare 
          (s1.begin (), s1.end (),   // source range
           s2.begin (), s2.end (),   // dest range
                nocase_compare ());  // comparison
    }
  }; // end of ci_less

void showv (const string s, const vector<string> & v)
  {
  cout << s << endl;
  copy(v.begin(), v.end(), ostream_iterator<string>(cout, " "));
  cout << endl << endl;
  } // end of showv

int main (void)
  {
  // vector of strings
  vector<string> v;

  // make a back insert iterator to safely add to the back of the vector
  back_insert_iterator<vector<string> > i(v);
  
// Insert items into the vector. 
// Strictly speaking, the "++" is not needed, as the
// assignment to the iterator is what advances it.

  *i++ = "The";
  *i++ = "quick";
  *i++ = "brown";
  *i++ = "fox";
  *i++ = "jumped";
  *i++ = "over";
  *i++ = "the";
  *i++ = "lazy";
  *i++ = "dog";

  showv ("initial vector...", v);

  // sort ascending
  sort (v.begin (), v.end ());
  showv ("after sort (ascending)...", v);

  // sort descending by using greater function to compare less
  sort (v.begin (), v.end (), greater<string> ());
  showv ("after sort (descending)...", v);

  // sort case-independent by using our own compare-less
  sort (v.begin (), v.end (), ci_less ());
  showv ("after case-independent sort (ascending)...", v);

  // reverse that by doing a "not" on the result
  sort (v.begin (), v.end (), not2 (ci_less ()));
  showv ("after case-independent sort (descending)...", v);
 
  // shuffle the words
  random_shuffle (v.begin (), v.end ());
  showv ("after shuffle...", v);

  // rotate them
  rotate (v.begin (), v.begin () + 1, v.end ());
  showv ("after rotate 1 to the left...", v);

  // reverse their order
  reverse (v.begin (), v.end ());
  showv ("after reverse...", v);

  // add "(" to the beginning of each one
  transform (v.begin (), v.end (),
             v.begin (),
             bind1st (plus<string> (), "("));

  // add ")" to the end of each one
  transform (v.begin (), v.end (),
             v.begin (),
             bind2nd (plus<string> (), ")"));
  showv ("after transforms...", v);

  return 0;
  } // end of main


Output

initial vector...
The quick brown fox jumped over the lazy dog

after sort (ascending)...
The brown dog fox jumped lazy over quick the

after sort (descending)...
the quick over lazy jumped fox dog brown The

after case-independent sort (ascending)...
brown dog fox jumped lazy over quick the The

after case-independent sort (descending)...
The the quick over lazy jumped fox dog brown

after shuffle...
the dog quick over jumped fox The lazy brown

after rotate 1 to the left...
dog quick over jumped fox The lazy brown the

after reverse...
the brown lazy The fox jumped over quick dog

after transforms...
(the) (brown) (lazy) (The) (fox) (jumped) (over) (quick) (dog)






The example also demonstrates "back insertion". One of the nice things about vectors is they can grow as large as you like without having to decide in advance how large that will be, however if you are doing that you need to tell it to insert (and grow) the vector. That is what the back insertion does. Another way would have been:


  vector<string> v (9);

  v [0] = "The";   
  v [1] = "quick"; 
  v [2] = "brown"; 
  v [3] = "fox";   
  v [4] = "jumped";
  v [5] = "over";  
  v [6] = "the";   
  v [7] = "lazy";  
  v [8] = "dog";   


In this case the constructor for the vector is passed the number of items, so that the vector is initialised to the correct size in advance. Once that is done, you can just put the elements into their respective places.

Personally I think that is a bit tedious.

Another approach would be to forget the back inserter and just do a push_back, like this:


  vector<string> v;

  v.push_back ("The");   
  v.push_back ("quick"); 
  v.push_back ("brown"); 
  v.push_back ("fox");   
  v.push_back ("jumped");
  v.push_back ("over");  
  v.push_back ("the");   
  v.push_back ("lazy");  
  v.push_back ("dog");   



I still think that is more coding than the original.

Another approach again is to use a C array, and copy into the STL one. This probably looks the neatest ...


  // vector of strings
  vector<string> v;

  // initial values
  char * s []  = { "The", "quick", "brown", "fox", "jumped", "over", 
                   "the", "lazy", "dog" };

  // copy into vector
  copy (s, &s [ sizeof s / sizeof s [0] ], back_inserter (v));


These examples just show there is more than one way of achieving a result. :)



The back_insert_iterator, back_inserter and push_back, are all variants of the same thing. At the end of the day back_inserter calls push_back, and the back_insert_iterator implements an operator* which also calls push_back. It just depends on which you think is the easiest to code and debug.

In fact, if you look at the way the back_insert_iterator is implemented, the ++ is a no-op, so this would have worked:


  back_insert_iterator<vector<string> > i(v);
  
  *i = "The";
  *i = "quick";
  *i = "brown";
  *i = "fox";
  *i = "jumped";
  *i = "over";
  *i = "the";
  *i = "lazy";
  *i = "dog";


However this is probably not good coding style, as it isn't very obvious from looking at it that the iterator is really progressing to different elements.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,046 posts)  Bio   Forum Administrator
Date Reply #1 on Fri 04 Jul 2003 07:50 AM (UTC)

Amended on Fri 04 Jul 2003 07:51 AM (UTC) by Nick Gammon

Message
Another impressive thing about STL is the error messages it can generate. For example, if you take the above working example, and compile it under gcc, after changing a single character, you get the following error message:




test.cpp: In instantiation of `std::unary_negate<ci_less>':
test.cpp:77: instantiated from here
test.cpp:77: no type named `argument_type' in `struct ci_less'
/usr/include/c++/3.2.2/bits/stl_function.h:278: no type named `argument_type'
in `struct ci_less'
/usr/include/c++/3.2.2/bits/stl_algo.h: In function `void
std::partial_sort(_RandomAccessIter, _RandomAccessIter, _RandomAccessIter,
_Compare) [with _RandomAccessIter =
__gnu_cxx::__normal_iterator<std::string*, std::vector<std::string,
std::allocator<std::string> > >, _Compare = std::unary_negate<ci_less>]':
/usr/include/c++/3.2.2/bits/stl_algo.h:2138: instantiated from `void std::__introsort_loop(_RandomAccessIter, _RandomAccessIter, _Size, _Compare) [with _RandomAccessIter = __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, _Size = int, _Compare = std::unary_negate<ci_less>]'
/usr/include/c++/3.2.2/bits/stl_algo.h:2209: instantiated from `void std::sort(_RandomAccessIter, _RandomAccessIter, _Compare) [with _RandomAccessIter = __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, _Compare = std::unary_negate<ci_less>]'
test.cpp:77: instantiated from here
/usr/include/c++/3.2.2/bits/stl_algo.h:2557: no match for call to `(
std::unary_negate<ci_less>) (std::basic_string<char, std::char_traits<char>,
std::allocator<char> >&, std::basic_string<char, std::char_traits<char>,
std::allocator<char> >&)'
/usr/include/c++/3.2.2/bits/stl_algo.h: In function `const _Tp&
std::__median(const _Tp&, const _Tp&, const _Tp&, _Compare) [with _Tp =
std::basic_string<char, std::char_traits<char>, std::allocator<char> >,
_Compare = std::unary_negate<ci_less>]':
/usr/include/c++/3.2.2/bits/stl_algo.h:2147: instantiated from `void std::__introsort_loop(_RandomAccessIter, _RandomAccessIter, _Size, _Compare) [with _RandomAccessIter = __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, _Size = int, _Compare = std::unary_negate<ci_less>]'
/usr/include/c++/3.2.2/bits/stl_algo.h:2209: instantiated from `void std::sort(_RandomAccessIter, _RandomAccessIter, _Compare) [with _RandomAccessIter = __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, _Compare = std::unary_negate<ci_less>]'
test.cpp:77: instantiated from here
/usr/include/c++/3.2.2/bits/stl_algo.h:124: no match for call to `(
std::unary_negate<ci_less>) (const std::basic_string<char,
std::char_traits<char>, std::allocator<char> >&, const
std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)'
/usr/include/c++/3.2.2/bits/stl_algo.h:125: no match for call to `(
std::unary_negate<ci_less>) (const std::basic_string<char,
std::char_traits<char>, std::allocator<char> >&, const
std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)'
/usr/include/c++/3.2.2/bits/stl_algo.h:127: no match for call to `(
std::unary_negate<ci_less>) (const std::basic_string<char,
std::char_traits<char>, std::allocator<char> >&, const
std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)'
/usr/include/c++/3.2.2/bits/stl_algo.h:131: no match for call to `(
std::unary_negate<ci_less>) (const std::basic_string<char,
std::char_traits<char>, std::allocator<char> >&, const
std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)'
/usr/include/c++/3.2.2/bits/stl_algo.h:133: no match for call to `(
std::unary_negate<ci_less>) (const std::basic_string<char,
std::char_traits<char>, std::allocator<char> >&, const
std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)'
/usr/include/c++/3.2.2/bits/stl_algo.h: In function `_RandomAccessIter
std::__unguarded_partition(_RandomAccessIter, _RandomAccessIter, _Tp,
_Compare) [with _RandomAccessIter =
__gnu_cxx::__normal_iterator<std::string*, std::vector<std::string,
std::allocator<std::string> > >, _Tp = std::basic_string<char,
std::char_traits<char>, std::allocator<char> >, _Compare =
std::unary_negate<ci_less>]':
/usr/include/c++/3.2.2/bits/stl_algo.h:2147: instantiated from `void std::__introsort_loop(_RandomAccessIter, _RandomAccessIter, _Size, _Compare) [with _RandomAccessIter = __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, _Size = int, _Compare = std::unary_negate<ci_less>]'
/usr/include/c++/3.2.2/bits/stl_algo.h:2209: instantiated from `void std::sort(_RandomAccessIter, _RandomAccessIter, _Compare) [with _RandomAccessIter = __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, _Compare = std::unary_negate<ci_less>]'
test.cpp:77: instantiated from here
/usr/include/c++/3.2.2/bits/stl_algo.h:1910: no match for call to `(
std::unary_negate<ci_less>) (std::basic_string<char, std::char_traits<char>,
std::allocator<char> >&, std::basic_string<char, std::char_traits<char>,
std::allocator<char> >&)'
/usr/include/c++/3.2.2/bits/stl_algo.h:2147: instantiated from `void std::__introsort_loop(_RandomAccessIter, _RandomAccessIter, _Size, _Compare) [with _RandomAccessIter = __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, _Size = int, _Compare = std::unary_negate<ci_less>]'
/usr/include/c++/3.2.2/bits/stl_algo.h:2209: instantiated from `void std::sort(_RandomAccessIter, _RandomAccessIter, _Compare) [with _RandomAccessIter = __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, _Compare = std::unary_negate<ci_less>]'
test.cpp:77: instantiated from here
/usr/include/c++/3.2.2/bits/stl_algo.h:1913: no match for call to `(
std::unary_negate<ci_less>) (std::basic_string<char, std::char_traits<char>,
std::allocator<char> >&, std::basic_string<char, std::char_traits<char>,
std::allocator<char> >&)'
/usr/include/c++/3.2.2/bits/stl_algo.h: In function `void
std::__insertion_sort(_RandomAccessIter, _RandomAccessIter, _Compare) [with
_RandomAccessIter = __gnu_cxx::__normal_iterator<std::string*,
std::vector<std::string, std::allocator<std::string> > >, _Compare =
std::unary_negate<ci_less>]':
/usr/include/c++/3.2.2/bits/stl_algo.h:2075: instantiated from `void std::__final_insertion_sort(_RandomAccessIter, _RandomAccessIter, _Compare) [with _RandomAccessIter = __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, _Compare = std::unary_negate<ci_less>]'
/usr/include/c++/3.2.2/bits/stl_algo.h:2210: instantiated from `void std::sort(_RandomAccessIter, _RandomAccessIter, _Compare) [with _RandomAccessIter = __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, _Compare = std::unary_negate<ci_less>]'
test.cpp:77: instantiated from here
/usr/include/c++/3.2.2/bits/stl_algo.h:2007: no match for call to `(
std::unary_negate<ci_less>) (std::string&, std::basic_string<char,
std::char_traits<char>, std::allocator<char> >&)'
/usr/include/c++/3.2.2/bits/stl_algo.h: In function `void
std::__unguarded_linear_insert(_RandomAccessIter, _Tp, _Compare) [with
_RandomAccessIter = __gnu_cxx::__normal_iterator<std::string*,
std::vector<std::string, std::allocator<std::string> > >, _Tp =
std::basic_string<char, std::char_traits<char>, std::allocator<char> >,
_Compare = std::unary_negate<ci_less>]':
/usr/include/c++/3.2.2/bits/stl_algo.h:2012: instantiated from `void std::__insertion_sort(_RandomAccessIter, _RandomAccessIter, _Compare) [with _RandomAccessIter = __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, _Compare = std::unary_negate<ci_less>]'
/usr/include/c++/3.2.2/bits/stl_algo.h:2075: instantiated from `void std::__final_insertion_sort(_RandomAccessIter, _RandomAccessIter, _Compare) [with _RandomAccessIter = __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, _Compare = std::unary_negate<ci_less>]'
/usr/include/c++/3.2.2/bits/stl_algo.h:2210: instantiated from `void std::sort(_RandomAccessIter, _RandomAccessIter, _Compare) [with _RandomAccessIter = __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, _Compare = std::unary_negate<ci_less>]'
test.cpp:77: instantiated from here
/usr/include/c++/3.2.2/bits/stl_algo.h:1961: no match for call to `(
std::unary_negate<ci_less>) (std::basic_string<char, std::char_traits<char>,
std::allocator<char> >&, std::basic_string<char, std::char_traits<char>,
std::allocator<char> >&)'
/usr/include/c++/3.2.2/bits/stl_heap.h: In function `void
std::__adjust_heap(_RandomAccessIterator, _Distance, _Distance, _Tp,
_Compare) [with _RandomAccessIterator =
__gnu_cxx::__normal_iterator<std::string*, std::vector<std::string,
std::allocator<std::string> > >, _Distance = int, _Tp =
std::basic_string<char, std::char_traits<char>, std::allocator<char> >,
_Compare = std::unary_negate<ci_less>]':
/usr/include/c++/3.2.2/bits/stl_heap.h:268: instantiated from `void std::make_heap(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, _Compare = std::unary_negate<ci_less>]'
/usr/include/c++/3.2.2/bits/stl_algo.h:2555: instantiated from `void std::partial_sort(_RandomAccessIter, _RandomAccessIter, _RandomAccessIter, _Compare) [with _RandomAccessIter = __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, _Compare = std::unary_negate<ci_less>]'
/usr/include/c++/3.2.2/bits/stl_algo.h:2138: instantiated from `void std::__introsort_loop(_RandomAccessIter, _RandomAccessIter, _Size, _Compare) [with _RandomAccessIter = __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, _Size = int, _Compare = std::unary_negate<ci_less>]'
/usr/include/c++/3.2.2/bits/stl_algo.h:2209: instantiated from `void std::sort(_RandomAccessIter, _RandomAccessIter, _Compare) [with _RandomAccessIter = __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, _Compare = std::unary_negate<ci_less>]'
test.cpp:77: instantiated from here
/usr/include/c++/3.2.2/bits/stl_heap.h:187: no match for call to `(
std::unary_negate<ci_less>) (std::basic_string<char, std::char_traits<char>,
std::allocator<char> >&, std::basic_string<char, std::char_traits<char>,
std::allocator<char> >&)'
/usr/include/c++/3.2.2/bits/stl_heap.h: In function `void
std::__push_heap(_RandomAccessIterator, _Distance, _Distance, _Tp, _Compare)
[with _RandomAccessIterator = __gnu_cxx::__normal_iterator<std::string*,
std::vector<std::string, std::allocator<std::string> > >, _Distance = int,
_Tp = std::basic_string<char, std::char_traits<char>, std::allocator<char>
>, _Compare = std::unary_negate<ci_less>]':
/usr/include/c++/3.2.2/bits/stl_heap.h:197: instantiated from `void std::__adjust_heap(_RandomAccessIterator, _Distance, _Distance, _Tp, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, _Distance = int, _Tp = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _Compare = std::unary_negate<ci_less>]'
/usr/include/c++/3.2.2/bits/stl_heap.h:268: instantiated from `void std::make_heap(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, _Compare = std::unary_negate<ci_less>]'
/usr/include/c++/3.2.2/bits/stl_algo.h:2555: instantiated from `void std::partial_sort(_RandomAccessIter, _RandomAccessIter, _RandomAccessIter, _Compare) [with _RandomAccessIter = __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, _Compare = std::unary_negate<ci_less>]'
/usr/include/c++/3.2.2/bits/stl_algo.h:2138: instantiated from `void std::__introsort_loop(_RandomAccessIter, _RandomAccessIter, _Size, _Compare) [with _RandomAccessIter = __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, _Size = int, _Compare = std::unary_negate<ci_less>]'
/usr/include/c++/3.2.2/bits/stl_algo.h:2209: instantiated from `void std::sort(_RandomAccessIter, _RandomAccessIter, _Compare) [with _RandomAccessIter = __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, _Compare = std::unary_negate<ci_less>]'
test.cpp:77: instantiated from here
/usr/include/c++/3.2.2/bits/stl_heap.h:107: no match for call to `(
std::unary_negate<ci_less>) (std::basic_string<char, std::char_traits<char>,
std::allocator<char> >&, std::basic_string<char, std::char_traits<char>,
std::allocator<char> >&)'
make: *** [test.o] Error 1




How's that? Not bad eh?


To generate that I changed the line:


sort (v.begin (), v.end (), not2 (ci_less ()));


to


sort (v.begin (), v.end (), not1 (ci_less ()));


Notice, the change of "not2" to "not1".

It shows, that even if you get a really lengthy error message, to stay calm - maybe there is only a minor coding bug. ;)

However the gratifying thing is that the line number reported in the error message (77) was in fact the line with the error on it.


- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,046 posts)  Bio   Forum Administrator
Date Reply #2 on Fri 04 Jul 2003 10:44 PM (UTC)
Message
Removing things from vectors

Removing things from the middle of a vector is not as simple as it might seem, because two things need to happen:


  1. Everything after the thing(s) being removed need to be shuffled along
  2. The end needs to be adjusted to reflect its new size


This is because vectors are stored linearly, so you can randomly access their contents. If you use the remove_if algorithm, without adjusting the vector length, then you will get the same length vector, and with some of the original things duplicated, like this:




// disable warnings about long names
#ifdef WIN32
  #pragma warning( disable : 4786)
#endif

#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <functional>

using namespace std;

#define NUMITEMS(x) (sizeof(x) / sizeof(x[0]))

int main (void)
  {

  // vector of strings
  vector<string> v;

  char * cs [] = { "the", "dog", "and", "the", "cat", "went",
    "to", "the", "shop" };

  // set up vector
  copy (cs, & cs [ NUMITEMS (cs) ], back_inserter (v));

  // remove the word "the"
  remove_if (v.begin (), v.end (), bind2nd (equal_to<string> (), "the"));

  // display results
  copy (v.begin(), v.end(), ostream_iterator<string> (cout, " "));
  cout << endl;

  return 0;
  } // end of main


Output

dog and cat went to shop to the shop





What we need to do is retain the result from the remove_if, which will be the end of the new sequence, which we can then pass to the vector's erase function, like this ...




// disable warnings about long names
#ifdef WIN32
  #pragma warning( disable : 4786)
#endif

#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <functional>

using namespace std;

#define NUMITEMS(x) (sizeof(x) / sizeof(x[0]))

int main (void)
  {

  // vector of strings
  vector<string> v;

  char * cs [] = { "the", "dog", "and", "the", "cat", "went",
    "to", "the", "shop" };

  // set up vector
  copy (cs, & cs [ NUMITEMS (cs) ], back_inserter (v));

  // iterator to hold the new end
  vector<string>::iterator i;

  // remove the word "the"
  i = remove_if (v.begin (), v.end (), bind2nd (equal_to<string> (), "the"));

  // adjust vector size
  v.erase (i, v.end ());

  // display results
  copy (v.begin(), v.end(), ostream_iterator<string> (cout, " "));
  cout << endl;

  return 0;
  } // end of main


Output

dog and cat went to shop





A little more elegantly, we can combine the remove and erase into a single line, to save defining a temporary iterator, like this:




// disable warnings about long names
#ifdef WIN32
  #pragma warning( disable : 4786)
#endif

#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <functional>

using namespace std;

#define NUMITEMS(x) (sizeof(x) / sizeof(x[0]))

int main (void)
  {

  // vector of strings
  vector<string> v;

  char * cs [] = { "the", "dog", "and", "the", "cat", "went",
    "to", "the", "shop" };

  // set up vector
  copy (cs, & cs [ NUMITEMS (cs) ], back_inserter (v));

  // remove the word "the" and adjust the length as well
  v.erase (remove_if (v.begin (), v.end (), bind2nd (equal_to<string> (), "the")),
         v.end ());

  // display results
  copy (v.begin(), v.end(), ostream_iterator<string> (cout, " "));
  cout << endl;

  return 0;
  } // end of main


Output

dog and cat went to shop



- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


15,204 views.

It is now over 60 days since the last post. This thread is closed.     Refresh page

Go to topic:           Search the forum


[Go to top] top

Quick links: MUSHclient. MUSHclient help. Forum shortcuts. Posting templates. Lua modules. Lua documentation.

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.

[Home]