tags:

views:

679

answers:

5

I have a small unsorted array and I'd like to find the index of a particular value. Does C++ have a built-in sequential search function for this, or do you just write the loop yourself each time it comes up?

I'm specifically using a C-style array like:

std::string arr[5] = { "EVEN", "ODD", "NONE", "MARK", "SPACE" };

and I need the index of a value that the user supplies.

+14  A: 

Use std::find() from the STL-algorithm-library, or the find()-method of your particular container.

Patrick Daryll Glandien
Thanks. I feel silly for asking, but I can write the function faster than I was finding it by searching for "C++ sequential search".
Bill the Lizard
BTW, you can use std::find on containers other than just STL containers. For example, a simple C-style array can be searched using std::find()
John Dibling
But how will it work on a C-style array? I don't get it.
sharptooth
@sharptooth: all STL iterators are designed such that they have the same semantics as pointers. thus a pointer is an iterator, for STL purposes :)
rmeador
I'll post an example.
John Dibling
@sharptooth: std::find(the_array, the_array + num_elements, the_value)
Éric Malenfant
@sharptooth: The linked page has a nice example using each an array and a vector.
Bill the Lizard
Looks like Michael Burr has already posted one. Now it's clear. Though it's not so obvious without an example.
sharptooth
Sorry, I had to unaccept this answer. That function returns a pointer to the array element, and I need the index.
Bill the Lizard
@Bill the Lizard: Subtract `arr` to get the index.
Paul
You can quite easily calculate the index from the pointer ((result - array) / sizeof(*array))
Patrick Daryll Glandien
@sikx: no need to divide by sizeof(*array). result - array will give proper value.
Paul
if you use find, i believe youshould do find(a, a + n, string("haha")); i'm not sure but if it is a dumb implementation and you just pass "haha", it will take it as a char const* . and will construct a temporary std::string each time it compares. not so when you pass in a std::string directly
Johannes Schaub - litb
@litb: no it won't construct every time. find is not a macro.
Mykola Golubyev
+9  A: 

std::find() should work:

#include <stdio.h>
#include <algorithm>
#include <string>

using std::string;

std::string arr[5] = { "EVEN", "ODD", "NONE", "MARK", "SPACE" };


int main() {

    string* pArrEnd = arr + sizeof( arr)/sizeof(arr[0]);

    string* pFound = std::find( arr, pArrEnd, "MARK");

    if (pFound == pArrEnd) {
        printf( "not found\n");
    }
    else {
        printf( "%s was found at index %d\n", pFound->c_str(), pFound - arr);
        printf( "or using STL: %d\n", std::distance( arr, pFound));
    }

    return 0;
}
Michael Burr
Accepted for the working code sample. Thanks.
Bill the Lizard
+3  A: 

In addition to the STL possibility (std::find) already mentioned there is the POSIX function lsearch (with c semantics).

dmckee
+4  A: 

I suppose you need the index and not the iterator.

int main()
{
    // for c++ vector
    typedef int Element;
    typedef std::vector<Element> CppVector;

    CppVector v;
    v.push_back( 2 );
    v.push_back( 4 );
    v.push_back( 8 );
    v.push_back( 6 );

    const Element el = 4;

    CppVector::const_iterator it = std::find( v.begin(), v.end(), el );
    if ( it == v.end() )
    {
        std::cout << "there is no such element" << std::endl;
    }
    else
    {
        const CppVector::size_type index = it - v.begin();
        std::cout << "index = " << index << std::endl;
    }

    // for C array
    typedef Element CVector[4];
    CVector cv;
    cv[0] = 2;
    cv[1] = 4;
    cv[2] = 8;
    cv[3] = 6;

    const std::size_t cvSize = sizeof( cv ) / sizeof( Element );

    std::cout << "c vector size = " << cvSize << std::endl;

    const Element* cit = std::find( cv, cv + cvSize, el );
    const std::size_t index = cit - cv;

    if ( index >= cvSize )
        std::cout << "there is no such element" << std::endl;
    else
        std::cout << "index = " << index << std::endl;
}
Mykola Golubyev
It's better to store the difference of two pointers in ptrdiff_t type, it can be negative (not in your case, but in general).
Paul
then comparison with => cvSize will issue warning.
Mykola Golubyev
+5  A: 

You can use STL algos on containers other than just STL containers. For example, you can std::find() in a C-style array:

// alloc the array
static const size_t numItems = 100000;
int * items = new int[numItems];

// fill the array
for( size_t n = 0; n < numItems; ++n )
 items[n] = n;

// find 42 using std::find()
int* found = std::find(&items[0], &items[numItems], 42);
if( found == &items[numItems] )
{
 // this is one past the end, so 42 was not found
 items[0] = 42;
}
else
{
 // we found the first instance of 42 at this location
 // change it to 43
 *found = 43;
}
John Dibling
warren
John Dibling
David Rodríguez - dribeas
Johannes Schaub - litb
@litb: I think it is undefined behavior only if you try to dereference the pointer.
John Dibling