C++ <algorithm> std::find_end

The std::find_end function in C++ is part of the <algorithm> header and is used to find the last occurrence of a subsequence within a container. It searches for the last occurrence of a sequence defined by a range [first2, last2) within another range [first1, last1), and returns an iterator to the first element of this last occurrence. If the subsequence is not found, it returns last1.


Syntax of std::find_end

</>
Copy
template <class ForwardIterator1, class ForwardIterator2>
ForwardIterator1 find_end(ForwardIterator1 first1, ForwardIterator1 last1,
                          ForwardIterator2 first2, ForwardIterator2 last2);

template <class ForwardIterator1, class ForwardIterator2, class BinaryPredicate>
ForwardIterator1 find_end(ForwardIterator1 first1, ForwardIterator1 last1,
                          ForwardIterator2 first2, ForwardIterator2 last2,
                          BinaryPredicate pred);

Parameters of std::find_end

ParameterDescription
first1, last1Forward iterators to the initial and final positions of the searched sequence. The range used is [first1, last1), which contains all the elements between first1 and last1, including the element pointed by first1 but not the element pointed by last1.
first2, last2Forward iterators to the initial and final positions of the sequence to be searched for. The range used is [first2, last2).
predBinary function that accepts two elements as arguments (one of each of the two sequences, in the same order), and returns a value convertible to bool. The returned value indicates whether the elements are considered to match in the context of this function. The function shall not modify any of its arguments. This can either be a function pointer or a function object.

Return Value of std::find_end

An iterator to the first element of the last occurrence of [first2, last2) in [first1, last1). If the sequence is not found, the function returns last1. If [first2, last2) is an empty range, the result is unspecified.


Examples for find_end

Example 1: Using std::find_end to Find the Last Occurrence of a Subsequence

In this example, we use std::find_end to find the last occurrence of a subsequence within a vector.

Program

</>
Copy
#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> main_sequence = {1, 2, 3, 4, 2, 3, 4, 5};
    std::vector<int> sub_sequence = {2, 3, 4};

    auto it = std::find_end(main_sequence.begin(), main_sequence.end(),
                            sub_sequence.begin(), sub_sequence.end());

    if (it != main_sequence.end()) {
        std::cout << "Last occurrence of subsequence found at position: "
                  << std::distance(main_sequence.begin(), it) << '\n';
    } else {
        std::cout << "Subsequence not found.\n";
    }

    return 0;
}

Output

Last occurrence of subsequence found at position: 4

Explanation

  1. We include the necessary headers: <iostream> for input/output operations, <vector> for the std::vector container, and <algorithm> for the std::find_end function.
  2. We define a vector main_sequence containing the integers {1, 2, 3, 4, 2, 3, 4, 5}.
  3. We define another vector sub_sequence containing the integers {2, 3, 4}.
  4. We use std::find_end to search for the last occurrence of sub_sequence within main_sequence.
  5. If the subsequence is found, it points to the first element of the last occurrence, and we print its position using std::distance. Otherwise, we print that the subsequence was not found.

Example 2: Using std::find_end with a Custom Comparator

This example demonstrates how to use std::find_end with a custom comparator to find the last occurrence of a subsequence within a list, ignoring case sensitivity.

Program

</>
Copy
#include <iostream>
#include <list>
#include <algorithm>
#include <cctype>

bool case_insensitive_compare(char a, char b) {
    return std::tolower(a) == std::tolower(b);
}

int main() {
    std::list<char> main_sequence = {'A', 'b', 'C', 'd', 'B', 'c', 'D', 'e'};
    std::list<char> sub_sequence = {'b', 'C', 'd'};

    auto it = std::find_end(main_sequence.begin(), main_sequence.end(),
                            sub_sequence.begin(), sub_sequence.end(),
                            case_insensitive_compare);

    if (it != main_sequence.end()) {
        std::cout << "Last occurrence of subsequence found at position: "
                  << std::distance(main_sequence.begin(), it) << '\n';
    } else {
        std::cout << "Subsequence not found.\n";
    }

    return 0;
}

Output

Last occurrence of subsequence found at position: 4

Explanation

  1. We include the necessary headers: <iostream> for input/output operations, <list> for the std::list container, <algorithm> for the std::find_end function, and <cctype> for the std::tolower function used in the custom comparator.
  2. We define a custom comparator function case_insensitive_compare that compares two characters in a case-insensitive manner by converting both to lowercase using std::tolower.
  3. We define a list main_sequence containing the characters {‘A’, ‘b’, ‘C’, ‘d’, ‘B’, ‘c’, ‘D’, ‘e’}.
  4. We define another list sub_sequence containing the characters {‘b’, ‘C’, ‘d’}.
  5. We use std::find_end with the custom comparator to search for the last occurrence of sub_sequence within main_sequence, ignoring case sensitivity.
  6. If the subsequence is found, it points to the first element of the last occurrence, and we print its position using std::distance. Otherwise, we print that the subsequence was not found.

Examples for Exceptions Thrown by std::find_end

The std::find_end function can throw exceptions in the following cases:

  • If the comparison operation or predicate function (pred) throws an exception.
  • If an operation on the iterators, such as dereferencing or incrementing, throws an exception.

Example 1: Predicate Throws an Exception

This example demonstrates a case where the predicate function throws an exception during execution.

Program

</>
Copy
#include <iostream>
#include <vector>
#include <algorithm>
#include <stdexcept>

bool faulty_predicate(int a, int b) {
    if (a < 0 || b < 0) {
        throw std::runtime_error("Negative value encountered during comparison.");
    }
    return a == b;
}

int main() {
    std::vector<int> main_sequence = {1, -2, 3, -2, 3, 4};
    std::vector<int> sub_sequence = {-2, 3};

    try {
        auto it = std::find_end(main_sequence.begin(), main_sequence.end(),
                                sub_sequence.begin(), sub_sequence.end(),
                                faulty_predicate);

        if (it != main_sequence.end()) {
            std::cout << "Subsequence found at position: "
                      << std::distance(main_sequence.begin(), it) << std::endl;
        } else {
            std::cout << "Subsequence not found." << std::endl;
        }
    } catch (const std::runtime_error& e) {
        std::cout << "Exception caught: " << e.what() << std::endl;
    }

    return 0;
}

Output

Exception caught: Negative value encountered during comparison.

Explanation

  1. The program defines a predicate function faulty_predicate that throws a std::runtime_error if either of the values being compared is negative.
  2. The vector main_sequence contains both positive and negative integers.
  3. The vector sub_sequence contains integers, including a negative value.
  4. The std::find_end function applies the predicate to search for the last occurrence of sub_sequence in main_sequence. When the predicate encounters a negative value, it throws an exception.
  5. The exception is caught in the try-catch block, and an error message is printed.