Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why does std::search need forward iters

my issue is identical to the thread below, I'm struggling to understand the answers given, or rather my code shouldn't work as it only uses input iterators ..but my func appears to work and behave identically to std::search ..so I'm at a loss and loathe to move on without understanding properly ...maybe if someone can suggest an input that will break my function but not the std::

From Why do I need a Forward Iterator to implement my customized std::search :

I am studying the book "Accelerated C++" from Koenig & Moo.

Exercise 8-2 ask me to implement on my own some templatized functions from <algorithm> and <numeric>, and to specify what kind of iterator does my implementation require.

When trying to implement std::search, I determined that I need only "input" iterators.

However, looking at the implementation of std::search installed with my compiler, I can see that they use "forward" iterators, but I cannot understand why, because there is no need to write, only to read, and input iterators meet the requirement.

Can anybody here help me to understand this, please? Why would I need to use "forward" iterators to implement std::search?

Thanks in advance.

myfunction:

template <class In> 
In search(  In begin, In end, In begin2, In end2 )
{
    In found ;                      // iter: 1st element in pattern match(in content)
    In pattern_begin = begin2 ;     // iter: 1st element in search pattern.
    int flag = 0 ;                  // flag: partial match found?

    // search content for pattern 
    while (  begin < end  ) {

        // if pattern-match fails ..reset vars
        // & continue searching remaining content/elements
        if ( *begin != *begin2 ) {

            In ret ;                     
            begin2 = pattern_begin ;
            flag = 0 ;
            begin++ ;


        } else {
            // compare next element in pattern with next element in content.
            // if: 1st element of 'pattern' is found, store iter to it's pos
            // ..then if entire pattern is found, we can ret an iter to where it starts
            if ( flag == 0 ) { 
                found = begin ;
                flag = 1 ;
            }
            // inc iters to compare next elements in partial match
            begin++ ;
            begin2++ ;
        }

        // if: iter is 1-past end of search pattern
        // then entire pattern has been found 
        // return the iter to where it starts
        if( begin2 == end2 ) {  return found ;  }

    }

    // end of content reached, no complete pattern found
    // begin should? equal an iter 1-past the end of content
    return begin ;
}

driver:

///* // Driver: custom::search(  b, e, b2, e2  ) 
#include <string>
#include <vector>
#include <iostream>
//#include <algorithm>
#include "library_algorithms.h"

int main() {

    // init string test
    std::string content = "fo The fox  foxu jumped  foxe foxy " ;
    std::string search_pattern = "foxy" ;

    // func test on string
    std::string::iterator ret_iter = 
    custom::search(  content.begin(), content.end(), search_pattern.begin(), search_pattern.end()  ) ;
    //std::search(  content.begin(), content.end(), search_pattern.begin(), search_pattern.end()  ) ;

    // output
    if (  ret_iter != content.end()  ) {

        std::cout << std::endl << std::endl << search_pattern << ": found at position: " << int(  ret_iter - content.begin()  ) << std::endl;

    } else { 

        std::cout << std::endl << std::endl << search_pattern << ": ...not found" << std::endl;
    }




    // Init vec test:
    // create content values in range:  10 20 30 <......> 9970 9980 9990
    std::vector<int> myvector;
    for (int i=1; i<1000; i++) myvector.push_back(i*10);

    // create pattern values to search for
    std::vector<int> pattern ;
    pattern.push_back( 3730 ) ;
    pattern.push_back( 3740 ) ;
    pattern.push_back( 3750 ) ;
    pattern.push_back( 3760 ) ;

    // test: func on vector<int>
    std::vector<int>::iterator it;
    it = custom::search (  myvector.begin(), myvector.end(), pattern.begin(), pattern.end() );

    // output
    if (it!=myvector.end())
    std::cout << std::endl << std::endl << "pattern found at position " << int(it-myvector.begin()) << std::endl;
    else
    std::cout << std::endl << std::endl << "pattern not found" << std::endl;





    return 0 ;

}
like image 582
tuk Avatar asked Mar 20 '11 12:03

tuk


People also ask

How do I move the iterator forward?

Forward iterator use only increments operator (++) to move through all the elements of a container. Therefore, we can say that the forward iterator can only move forward.

What is Forwarditerator?

A Forward Iterator is an iterator that corresponds to the usual intuitive notion of a linear sequence of values. It is possible to use Forward Iterators (unlike Input Iterators and Output Iterators) in multipass algorithms.

Which function is used to get a move iterator from a container?

Generally, like this: struct vec{ iterator begin() ; const_iterator begin() const; };

What is an iterator C++?

An iterator is an object that can iterate over elements in a C++ Standard Library container and provide access to individual elements.


1 Answers

You've misunderstood what an input iterator can do.

You can't "save" or copy an input iterator. It allows you to traverse the sequence exactly once. In other words, this line, among others, will break: begin2 = pattern_begin.

An input iterator may represents something that you can't readily "rewind", like, say, the stream of data received from a network adapter. An iterator pointing to "6 elements ago" is no longer meaningful, because that data may no longer be available in memory. You only have the current position in the stream.

It should be obvious that in order to implement search correctly, you need to be able to traverse parts of the sequence more than once.

like image 80
jalf Avatar answered Oct 13 '22 09:10

jalf