<!--
    Licensed to the Apache Software  Foundation (ASF) under one or more
    contributor  license agreements.  See  the NOTICE  file distributed
    with  this  work  for  additional information  regarding  copyright
    ownership.   The ASF  licenses this  file to  you under  the Apache
    License, Version  2.0 (the  License); you may  not use  this file
    except in  compliance with the License.   You may obtain  a copy of
    the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the  License is distributed on an  "AS IS" BASIS,
    WITHOUT  WARRANTIES OR CONDITIONS  OF ANY  KIND, either  express or
    implied.   See  the License  for  the  specific language  governing
    permissions and limitations under the License.

    Copyright 1999-2007 Rogue Wave Software, Inc.
-->

<HTML>
<HEAD>
<TITLE>mismatch()</TITLE>
<LINK REL=StyleSheet HREF="../rw.css" TYPE="text/css" TITLE="Apache stdcxx Stylesheet"></HEAD>
<BODY BGCOLOR=#FFFFFF>
<A HREF="minus.html"><IMG SRC="images/bprev.gif" WIDTH=20 HEIGHT=21 ALT="Previous file" BORDER=O></A><A HREF="noframes.html"><IMG SRC="images/btop.gif" WIDTH=56 HEIGHT=21 ALT="Top of Document" BORDER=O></A><A HREF="booktoc.html"><IMG SRC="images/btoc.gif" WIDTH=56 HEIGHT=21 ALT="Contents" BORDER=O></A><A HREF="tindex.html"><IMG SRC="images/bindex.gif" WIDTH=56 HEIGHT=21 ALT="Index page" BORDER=O></A><A HREF="modulus.html"><IMG SRC="images/bnext.gif" WIDTH=25 HEIGHT=21 ALT="Next file" BORDER=O></A><DIV CLASS="DOCUMENTNAME"><B>Apache C++ Standard Library Reference Guide</B></DIV>
<H2>mismatch()</H2>
<P><B>Library:</B>&nbsp;&nbsp;<A HREF="2-9.html">Algorithms</A></P>

<PRE><HR><B><I>Function</I></B><HR></PRE>

<UL>
<LI><A HREF="#sec1">Local Index</A></LI>
<LI><A HREF="#sec2">Summary</A></LI>
<LI><A HREF="#sec3">Synopsis</A></LI>
<LI><A HREF="#sec4">Description</A></LI>
<LI><A HREF="#sec5">Complexity</A></LI>
<LI><A HREF="#sec6">Example</A></LI>
<LI><A HREF="#sec7">Standards Conformance</A></LI>
</UL>
<A NAME="sec1"><H3>Local Index</H3></A>
No Entries
<A NAME="sec2"><H3>Summary</H3></A>
<P>Algorithm that compares elements from two sequences and returns a pair of iterators pointing to the first two elements that don't match each other</P>
<A NAME="sec3"><H3>Synopsis</H3></A>

<PRE>#include &lt;algorithm&gt;

namespace std {
  template &lt;class InputIterator1, class InputIterator2&gt;
  pair&lt;InputIterator1,InputIterator2&gt;
  mismatch(InputIterator1 start1, InputIterator1 finish1,
           InputIterator2 start2);

  template &lt;class InputIterator1, class InputIterator2,
            class BinaryPredicate&gt;
  pair&lt;InputIterator1, Inputiterator2&gt;
  mismatch(InputIterator1 start1, InputIterator1 finish1,
           InputIterator2 start2,
           BinaryPredicate binary_pred);
}
</PRE>
<A NAME="sec4"><H3>Description</H3></A>
<P>The <SAMP>mismatch()</SAMP> algorithm compares members of two sequences and returns two iterators (<SAMP>i</SAMP> and <SAMP>j</SAMP>) that point to the first location in each sequence where the sequences differ from each other. <SAMP>mismatch()</SAMP> assumes that the second sequence has at least as many members as the first sequence. If the two sequences are identical, <SAMP>mismatch()</SAMP> returns a pair of iterators that point to the end of the first sequence and the corresponding location at which the comparison stopped in the second sequence.</P>
<P>The first version of <SAMP>mismatch()</SAMP> checks members of a sequence for equality, while the second version lets you specify a comparison function object. The comparison function object must be a binary predicate.</P>
<P>The iterators <SAMP>i</SAMP> and <SAMP>j</SAMP> returned by <SAMP>mismatch()</SAMP> are defined as follows:</P>

<UL><PRE>j  == start2  +  (i  -  start1)
</PRE></UL>
<P>and <SAMP>i</SAMP> is the first iterator in the range <SAMP>[start1, finish1)</SAMP> for which the appropriate one of the following conditions hold: </P>

<UL><PRE>!(*i  ==  *(start2  +  (i  -  start1)))
</PRE></UL>
<P>or</P>

<UL><PRE>binary_pred(*i, *(start2 + (i - start1))) == false
</PRE></UL>
<P>If all of the members in the two sequences match, <SAMP>mismatch()</SAMP> returns a pair of <SAMP>finish1</SAMP> and <SAMP>start2 + (finish1 - start1)</SAMP>. </P>
<A NAME="sec5"><H3>Complexity</H3></A>
<P>At most <SAMP>finish1 - start1</SAMP> applications of the corresponding predicate are done.</P>
<A NAME="sec6"><H3>Example</H3></A>

<UL><PRE>//
//  mismatch.cpp
//

#include &lt;algorithm&gt;    // mismatch
#include &lt;functional&gt;   // less_equal
#include &lt;iostream&gt;     // cout, endl
#include &lt;utility&gt;      // pair
#include &lt;vector&gt;       // vector



int main ()
{
    typedef std::vector&lt;int, std::allocator&lt;int&gt; &gt; Vector;
    typedef Vector::const_iterator                 Iter;

    const Vector::value_type d1[] = { 1, 2, 3, 4 };
    const Vector::value_type d2[] = { 1, 3, 2, 4 };

    // Set up two vectors.
    const Vector vi1 (d1 + 0, d1 + sizeof d1 / sizeof *d1);
    const Vector vi2 (d2 + 0, d2 + sizeof d2 / sizeof *d2);

    // p1 will contain two iterators that point to 
    // the first pair of elements that are different 
    // between the two vectors.
    std::pair&lt;Iter, Iter&gt; p1 =
        std::mismatch (vi1.begin (), vi1.end (), vi2.begin ());  

    // Find the first two elements such that an element in 
    // the first vector is greater than the element in
    // the second vector.
    std::pair&lt;Iter, Iter&gt; p2 =
        std::mismatch (vi1.begin (), vi1.end (),
                       vi2.begin (), std::less_equal&lt;int&gt;());

    // Output results.
    std::cout &lt;&lt; *p1.first &lt;&lt; ", " &lt;&lt; *p1.second &lt;&lt; std::endl;
    std::cout &lt;&lt; *p2.first &lt;&lt; ", " &lt;&lt; *p2.second &lt;&lt; std::endl;

    return 0;
}


Program Output:
</PRE></UL>
<UL><PRE>2, 3
3, 2
</PRE></UL>
<A NAME="sec7"><H3>Standards Conformance</H3></A>
<P><I>ISO/IEC 14882:1998 -- International Standard for Information Systems -- Programming Language C++, Section 25.1.7</I></P>

<BR>
<HR>
<A HREF="minus.html"><IMG SRC="images/bprev.gif" WIDTH=20 HEIGHT=21 ALT="Previous file" BORDER=O></A><A HREF="noframes.html"><IMG SRC="images/btop.gif" WIDTH=56 HEIGHT=21 ALT="Top of Document" BORDER=O></A><A HREF="booktoc.html"><IMG SRC="images/btoc.gif" WIDTH=56 HEIGHT=21 ALT="Contents" BORDER=O></A><A HREF="tindex.html"><IMG SRC="images/bindex.gif" WIDTH=56 HEIGHT=21 ALT="Index page" BORDER=O></A><A HREF="modulus.html"><IMG SRC="images/bnext.gif" WIDTH=20 HEIGHT=21 ALT="Next file" BORDER=O></A>

<!-- Google Analytics tracking code -->
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
    _uacct = "UA-1775151-1";
    urchinTracker();
</script>
<!-- end of Google Analytics tracking code -->

</BODY>
</HTML>
