Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
B.Eckel - Thinking in C++, Vol.2, 2nd edition.pdf
Скачиваний:
50
Добавлен:
08.05.2013
Размер:
2.09 Mб
Скачать

Note that the only difference between s1 and s2 is the capital ‘T’ in s2’s “Test.” Comparing s1 and s1 for equality yields true, as expected, while s1 and s2 are not equal because of the capital ‘T’.

To understand the output of the lexicographical_compare( ) tests, you must remember two things: first, the comparison is performed character-by-character, and second that capital letters “precede” lowercase letters. In the first test, s1 is compared to s1. These are exactly equivalent, thus one is not lexicographically less than the other (which is what the comparison is looking for) and thus the result is false. The second test is asking “does s1 precede s2?” When the comparison gets to the ‘t’ in “test”, it discovers that the lowercase ‘t’ in s1 is “greater” than the uppercase ‘T’ in s2, so the answer is again false. However, if we test to see whether s2 precedes s1, the answer is true.

To further examine lexicographical comparison, the next test in the above example compares s1 with s2 again (which returned false before). But this time it repeats the comparison, trimming one character off the end of s1 (which is first copied into s3) each time through the loop until the test evaluates to true. What you’ll see is that, as soon as the uppercase ‘T’ is trimmed off of s3 (the copy of s1), then the characters, which are exactly equal up to that point, no longer count and the fact that s3 is shorter than s2 is what makes it lexicographically precede s2.

The final test uses mismatch( ). In order to capture the return value, you must first create the appropriate pair p, constructing the template using the iterator type from the first range and the iterator type from the second range (in this case, both string::iterators). To print the results, the iterator for the mismatch in the first range is p.first, and for the second range is p.second. In both cases, the range is printed from the mismatch iterator to the end of the range so you can see exactly where the iterator points.

Removing elements

Because of the genericity of the STL, the concept of removal is a bit constrained. Since elements can only be “removed” via iterators, and iterators can point to arrays, vectors, lists, etc., it is not safe or reasonable to actually try to destroy the elements that are being removed, and to change the size of the input range [first, last) (an array, for example, cannot have its size changed). So instead, what the STL “remove” functions do is rearrange the sequence so that the “removed” elements are at the end of the sequence, and the “un-removed” elements are at the beginning of the sequence (in the same order that they were before, minus the removed elements – that is, this is a stable operation). Then the function will return an iterator to the “new last” element of the sequence, which is the end of the sequence without the removed elements and the beginning of the sequence of the removed elements. In other words, if new_last is the iterator that is returned from the “remove” function, then [first, new_last) is the sequence without any of the removed elements, and [new_last, last) is the sequence of removed elements.

If you are simply using your algorithms, you can just use

sequence, including the removed elements, with more STL new_last as the new past-the-end iterator. However, if you’re

Chapter 15: Multiple Inheritance

308

using a resizable container c (not an array) and you actually want to eliminate the removed elements from the container you can use erase( ) to do so, for example:

c.erase(remove(c.begin(), c.end(), value), c.end());

The return value of remove( ) is the new_last iterator, so erase( ) will delete all the removed elements from c.

The iterators in [new_last, last) are dereferenceable but the element values are undefined and should not be used.

ForwardIterator remove(ForwardIterator first, ForwardIterator last, const T& value); ForwardIterator remove_if(ForwardIterator first, ForwardIterator last,

Predicate pred);

OutputIterator remove_copy(InputIterator first, InputIterator last, OutputIterator result, const T& value);

OutputIterator remove_copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate pred);

Each of the “remove” forms moves through the range [first, last), finding values that match a removal criterion and copying the un-removed elements over the removed elements (thus effectively removing them). The original order of the un-removed elements is maintained. The return value is an iterator pointing past the end of the range that contains none of the removed elements. The values that this iterator points to are unspecified.

The “if” versions pass each element to pred( ) to determine whether it should be removed or not (if pred( ) returns true, the element is removed). The “copy” versions do not modify the original sequence, but instead copy the un-removed values into a range beginning at result, and return an iterator indicating the past-the-end value of this new range.

ForwardIterator unique(ForwardIterator first, ForwardIterator last); ForwardIterator unique(ForwardIterator first, ForwardIterator last,

BinaryPredicate binary_pred);

OutputIterator unique_copy(InputIterator first, InputIterator last, OutputIterator result);

OutputIterator unique_copy(InputIterator first, InputIterator last, OutputIterator result, BinaryPredicate binary_pred);

Each of the “unique” functions moves through the range [first, last), finding adjacent values that are equivalent (that is, duplicates) and “removing” the duplicate elements by copying over them. The original order of the un-removed elements is maintained. The return value is an iterator pointing past the end of the range that has the adjacent duplicates removed.

Because only duplicates that are adjacent are removed, it’s likely that you’ll want to call sort( ) before calling a “unique” algorithm, since that will guarantee that all the duplicates are removed.

The versions containing binary_pred call, for each iterator value i in the input range:

binary_pred(*i, *(i-1));

Chapter 15: Multiple Inheritance

309

and if the result is true then *(i-1) is considered a duplicate.

The “copy” versions do not modify the original sequence, but instead copy the un-removed values into a range beginning at result, and return an iterator indicating the past-the-end value of this new range.

Example

This example gives a visual demonstration of the way the “remove” and “unique” functions work.

//: C05:Removing.cpp

// The removing algorithms #include "PrintSequence.h" #include "Generators.h"

#include <vector> #include <algorithm> #include <cctype> using namespace std;

struct IsUpper {

bool operator()(char c) { return isupper(c);

}

};

int main() { vector<char> v(50);

generate(v.begin(), v.end(), CharGen()); print(v, "v", "");

//Create a set of the characters in v: set<char> cs(v.begin(), v.end()); set<char>::iterator it = cs.begin(); vector<char>::iterator cit;

//Step through and remove everything: while(it != cs.end()) {

cit = remove(v.begin(), v.end(), *it); cout << *it << "[" << *cit << "] "; print(v, "", "");

it++;

}

generate(v.begin(), v.end(), CharGen()); print(v, "v", "");

cit = remove_if(v.begin(), v.end(), IsUpper());

Chapter 15: Multiple Inheritance

310

Соседние файлы в предмете Численные методы
  • #
    08.05.20133.99 Mб22A.Menezes, P.van Oorschot,S.Vanstone - HANDBOOK OF APPLIED CRYPTOGRAPHY.djvu
  • #
  • #
    08.05.20135.91 Mб24B.Eckel - Thinking in Java, 3rd edition (beta).pdf
  • #
  • #
    08.05.20136.09 Mб17D.MacKay - Information Theory, Inference, and Learning Algorithms.djvu
  • #
    08.05.20133.85 Mб15DIGITAL Visual Fortran ver.5.0 - Programmers Guide to Fortran.djvu
  • #
    08.05.20131.84 Mб12E.A.Lee, P.Varaiya - Structure and Interpretation of Signals and Systems.djvu