Home C++ C++ Output Iterators tutorial with code examples

C++ Output Iterators tutorial with code examples

In C++, Output Iterators are a type of iterator used to write data to a container or stream, moving in a single direction.

They are primarily used to insert or modify elements in containers or output streams.

Unlike input iterators, which are read-only, output iterators are write-only and do not allow for reading or comparing elements.

Output iterators are especially useful for algorithms that produce or transform data.

Characteristics of Output Iterators

  1. Single-pass traversal: Can only move forward, similar to input iterators.
  2. Write-only: Only supports writing elements, not reading them.
  3. No comparison: Output iterators cannot be compared for equality or inequality.
  4. Dereferenceable: Supports dereferencing for writing data.

Basic Syntax

iterator_type iterator_name = container.begin();

1. Basic Example of Output Iterator with std::vector

In this example, an output iterator is used to add elements to a std::vector.

#include <iostream>
#include <vector>
#include <iterator>
using namespace std;

int main() {
    vector<int> numbers;

    // Output iterator to insert elements into the vector
    back_insert_iterator<vector<int>> output_it(numbers);

    *output_it = 10; // Insert 10
    ++output_it;
    *output_it = 20; // Insert 20
    ++output_it;
    *output_it = 30; // Insert 30

    cout << "Vector elements: ";
    for (int number : numbers) {
        cout << number << " ";
    }

    return 0;
}

Explanation:

  • back_insert_iterator<vector<int>> is used to create an output iterator that inserts elements at the end of numbers.
  • Each *output_it = value operation inserts the value at the current iterator position.

Output:

Vector elements: 10 20 30

2. Using std::ostream_iterator for Stream Output

std::ostream_iterator is an output iterator that writes elements to output streams, like cout.

#include <iostream>
#include <iterator>
#include <vector>
using namespace std;

int main() {
    vector<int> numbers = {1, 2, 3, 4, 5};

    cout << "Vector elements: ";
    ostream_iterator<int> output_it(cout, " ");
    for (int number : numbers) {
        *output_it = number; // Write each element to cout
        ++output_it;
    }

    return 0;
}

Explanation:

  • ostream_iterator<int> output_it(cout, ” “); creates an output iterator that writes integers to cout, separated by a space.
  • Each *output_it = number operation outputs the value to the console.

Output:

Vector elements: 1 2 3 4 5

3. Copying Elements to std::vector Using std::copy and back_inserter

std::copy can be used with back_inserter to copy elements from one container to another.

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

int main() {
    vector<int> numbers = {1, 2, 3, 4, 5};
    vector<int> new_numbers;

    // Use std::copy with back_inserter
    copy(numbers.begin(), numbers.end(), back_inserter(new_numbers));

    cout << "New vector elements: ";
    for (int number : new_numbers) {
        cout << number << " ";
    }

    return 0;
}

Explanation:

  • back_inserter(new_numbers) creates an output iterator that appends elements to new_numbers.
  • std::copy copies elements from numbers to new_numbers using this output iterator.

Output:

New vector elements: 1 2 3 4 5

4. Using std::fill_n with Output Iterators

The std::fill_n algorithm can be used with output iterators to add a fixed number of elements to a container.

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

int main() {
    vector<int> numbers;

    // Fill the vector with five 100s
    fill_n(back_inserter(numbers), 5, 100);

    cout << "Filled vector elements: ";
    for (int number : numbers) {
        cout << number << " ";
    }

    return 0;
}

Explanation:

  • fill_n(back_inserter(numbers), 5, 100); fills numbers with five instances of 100 using a back-insert output iterator.

Output:

Filled vector elements: 100 100 100 100 100

5. Writing to std::ofstream Using std::ostream_iterator

ostream_iterator can also be used with file streams to write elements to a file.

#include <iostream>
#include <fstream>
#include <iterator>
#include <vector>
using namespace std;

int main() {
    ofstream outputFile("output.txt");

    if (!outputFile) {
        cerr << "File could not be opened!" << endl;
        return 1;
    }

    vector<int> numbers = {1, 2, 3, 4, 5};
    ostream_iterator<int> output_it(outputFile, "\n");

    for (int number : numbers) {
        *output_it = number;
        ++output_it;
    }

    outputFile.close();
    cout << "Numbers written to file output.txt" << endl;

    return 0;
}

Explanation:

  • ostream_iterator<int> output_it(outputFile, “\n”); creates an output iterator that writes each integer to a new line in output.txt.
  • Each *output_it = number writes the number to the file.

Output:

Numbers written to file output.txt

Content of output.txt:

1
2
3
4
5

6. Using std::transform with Output Iterators

The std::transform function applies a transformation to elements and stores the result using an output iterator.

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
using namespace std;

int main() {
    vector<int> numbers = {1, 2, 3, 4, 5};
    vector<int> squaredNumbers;

    // Square each element and store in squaredNumbers
    transform(numbers.begin(), numbers.end(), back_inserter(squaredNumbers), [](int n) { return n * n; });

    cout << "Squared elements: ";
    for (int number : squaredNumbers) {
        cout << number << " ";
    }

    return 0;
}

Explanation:

  • transform squares each element in numbers and uses back_inserter to store results in squaredNumbers.

Output:

Squared elements: 1 4 9 16 25

7. Using std::generate_n with Output Iterators

The std::generate_n function generates a sequence of values and stores them in a container using an output iterator.

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

int main() {
    vector<int> numbers;

    // Generate sequence of 5 random numbers
    generate_n(back_inserter(numbers), 5, []() { return rand() % 100; });

    cout << "Generated random numbers: ";
    for (int number : numbers) {
        cout << number << " ";
    }

    return 0;
}

Explanation:

  • generate_n uses back_inserter(numbers) to add five random numbers to numbers.

Output (random values):

Generated random numbers: 37 23 88 19 45

8. Duplicating Elements with std::copy and std::ostream_iterator

You can duplicate elements from one container to another using std::copy and output iterators.

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
using namespace std;

int main() {
    vector<int> numbers = {1, 2, 3};

    cout << "Duplicated elements: ";
    copy(numbers.begin(), numbers.end(), ostream_iterator<int>(cout, " "));
    copy(numbers.begin(), numbers.end(), ostream_iterator<int>(cout, " ")); // Copy again to duplicate

    return 0;
}

Explanation:

  • copy is called twice, each time outputting numbers to cout.

Output:

Duplicated elements: 1 2 3 1 2 3

Summary Table of Output Iterator Usage

Example Description
Basic Vector Output Iterator Inserts elements into a vector
Stream Output Iterator Writes elements to cout using ostream_iterator
Copying with std::copy Copies elements to a new container with back_inserter
Filling with std::fill_n Fills a container with repeated values
File Output with ostream_iterator Writes elements to a file using an output iterator
Transforming with std::transform Transforms and stores results in another container
Generating Sequence Generates values and stores them in a container
Duplicating Elements Duplicates container contents using output iterators

Key Takeaways

  • Output Iterators are used to write or insert data into containers or streams.
  • std::back_inserter and std::ostream_iterator are common types of output iterators used for appending elements and writing to streams.
  • Output iterators work well with algorithms like std::copy, std::fill_n, std::transform, and std::generate_n.
  • Unlike other iterators, output iterators are write-only and are not used for reading or comparing elements, making them suitable for single-pass write operations.

You may also like