47

How can I check if my array has an element I'm looking for?

In Java, I would do something like this:

Foo someObject = new Foo(someParameter);
Foo foo;
//search through Foo[] arr
for(int i = 0; i < arr.length; i++){
  if arr[i].equals(someObject)
    foo = arr[i];
}
if (foo == null)
  System.out.println("Not found!");
else
  System.out.println("Found!");

But in C++ I don't think I'm allowed to search if an Object is null so what would be the C++ solution?

Omar Darwish
  • 1,536
  • 2
  • 15
  • 23
  • To clarify: "objects" in c++ can't be null because null specifically because NULL (or nullptr) refers to a null pointer - it's not an object that's an instance of any class. So if instead of manipulating objects directly, if you were working with pointers to objects, it would make perfect second to compare one to null. On some level ostensibly the same is true in Java (you can see this when you try to reference a null value and get a null pointer exception) except Java doesn't let you directly manipulate pointers to reference types. – Moodragonx Feb 06 '23 at 22:52

9 Answers9

100

In C++ you would use std::find, and check if the resultant pointer points to the end of the range, like this:

Foo array[10];
... // Init the array here
Foo *foo = std::find(std::begin(array), std::end(array), someObject);
// When the element is not found, std::find returns the end of the range
if (foo != std::end(array)) {
    cerr << "Found at position " << std::distance(array, foo) << endl;
} else {
    cerr << "Not found" << endl;
}
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
13

You would just do the same thing, looping through the array to search for the term you want. Of course if it's a sorted array this would be much faster, so something similar to prehaps:

for(int i = 0; i < arraySize; i++){
     if(array[i] == itemToFind){
         break;
     }
}
Rivasa
  • 6,510
  • 3
  • 35
  • 64
  • 1
    For microcontrollers like Arduino you would usually have to do something like this because the std library is not advisable due to memory constraints. – Methodician Jan 03 '22 at 21:10
12

There are many ways...one is to use the std::find() algorithm, e.g.

#include <algorithm>

int myArray[] = { 3, 2, 1, 0, 1, 2, 3 };
size_t myArraySize = sizeof(myArray) / sizeof(int);
int *end = myArray + myArraySize;
// find the value 0:
int *result = std::find(myArray, end, 0);
if (result != end) {
  // found value at "result" pointer location...
}
Kevin Grant
  • 5,363
  • 1
  • 21
  • 24
11

Here is a simple generic C++11 function contains which works for both arrays and containers:

using namespace std;

template<class C, typename T>
bool contains(C&& c, T e) { return find(begin(c), end(c), e) != end(c); };

Simple usage contains(arr, el) is somewhat similar to in keyword semantics in Python.

Here is a complete demo:

#include <algorithm>
#include <array>
#include <string>
#include <vector>
#include <iostream>

template<typename C, typename T>
bool contains(C&& c, T e) { 
    return std::find(std::begin(c), std::end(c), e) != std::end(c);
};

template<typename C, typename T>
void check(C&& c, T e) {
    std::cout << e << (contains(c,e) ? "" : " not") <<  " found\n";
}

int main() {
    int a[] = { 10, 15, 20 };
    std::array<int, 3> b { 10, 10, 10 };
    std::vector<int> v { 10, 20, 30 };
    std::string s { "Hello, Stack Overflow" };
    
    check(a, 10);
    check(b, 15);
    check(v, 20);
    check(s, 'Z');

    return 0;
}

Output:

10 found
15 not found
20 found
Z not found
Andriy Makukha
  • 7,580
  • 1
  • 38
  • 49
3

If you were originally looking for the answer to this question (int value in sorted (Ascending) int array), then you can use the following code that performs a binary search (fastest result):

static inline bool exists(int ints[], int size, int k) // array, array's size, searched value
{
    if (size <= 0)      // check that array size is not null or negative
         return false;
    // sort(ints, ints + size); // uncomment this line if array wasn't previously sorted
    return (std::binary_search(ints, ints + size, k));
}

edit: Also works for unsorted int array if uncommenting sort.

Antonin GAVREL
  • 9,682
  • 8
  • 54
  • 81
3

One wants this to be done tersely. Nothing makes code more unreadable then spending 10 lines to achieve something elementary. In C++ (and other languages) we have all and any which help us to achieve terseness in this case. I want to check whether a function parameter is valid, meaning equal to one of a number of values. Naively and wrongly, I would first write

if (!any_of({ DNS_TYPE_A, DNS_TYPE_MX }, wtype) return false;

a second attempt could be

if (!any_of({ DNS_TYPE_A, DNS_TYPE_MX }, [&wtype](const int elem) { return elem == wtype; })) return false;

Less incorrect, but looses some terseness. However, this is still not correct because C++ insists in this case (and many others) that I specify both start and end iterators and cannot use the whole container as a default for both. So, in the end:

const vector validvalues{ DNS_TYPE_A, DNS_TYPE_MX };
if (!any_of(validvalues.cbegin(),  validvalues.cend(), [&wtype](const int elem) { return elem == wtype; })) return false;

which sort of defeats the terseness, but I don't know a better alternative... Thank you for not pointing out that in the case of 2 values I could just have just if ( || ). The best approach here (if possible) is to use a case structure with a default where not only the values are checked, but also the appropriate actions are done. The default case can be used for signalling an invalid value.

Jan
  • 447
  • 6
  • 8
  • 1
    I really like this approach, but it needs some clarification. Firstly, a warning that `std::any_of` is only introduced in C++ 11. Secondly, if you want to pass an array to the function you will instead want `boost::algorithm::any_of_equal` as the standard implementation doesn't directly support being passed an array. – Derme302 Aug 03 '20 at 00:56
2

You can use old C-style programming to do the job. This will require little knowledge about C++. Good for beginners.

For modern C++ language you usually accomplish this through lambda, function objects, ... or algorithm: find, find_if, any_of, for_each, or the new for (auto& v : container) { } syntax. find class algorithm takes more lines of code. You may also write you own template find function for your particular need.

Here is my sample code

#include <iostream>
#include <functional>
#include <algorithm>
#include <vector>

using namespace std;

/**
 * This is old C-like style.  It is mostly gong from 
 * modern C++ programming.  You can still use this
 * since you need to know very little about C++.
 * @param storeSize you have to know the size of store
 *    How many elements are in the array.
 * @return the index of the element in the array,
 *   if not found return -1
 */
int in_array(const int store[], const int storeSize, const int query) {
   for (size_t i=0; i<storeSize; ++i) {
      if (store[i] == query) {
         return i;
      }
   }
   return -1;
}

void testfind() {
   int iarr[] = { 3, 6, 8, 33, 77, 63, 7, 11 };

   // for beginners, it is good to practice a looping method
   int query = 7;
   if (in_array(iarr, 8, query) != -1) {
      cout << query << " is in the array\n";
   }

   // using vector or list, ... any container in C++
   vector<int> vecint{ 3, 6, 8, 33, 77, 63, 7, 11 };
   auto it=find(vecint.begin(), vecint.end(), query);
   cout << "using find()\n";
   if (it != vecint.end()) {
      cout << "found " << query << " in the container\n";
   }
   else {
      cout << "your query: " << query << " is not inside the container\n";
   }

   using namespace std::placeholders;
   // here the query variable is bound to the `equal_to` function 
   // object (defined in std)
   cout << "using any_of\n";
   if (any_of(vecint.begin(), vecint.end(), bind(equal_to<int>(), _1, query))) {
      cout << "found " << query << " in the container\n";
   }
   else {
      cout << "your query: " << query << " is not inside the container\n";
   }

   // using lambda, here I am capturing the query variable
   // into the lambda function
   cout << "using any_of with lambda:\n";
   if (any_of(vecint.begin(), vecint.end(),
            [query](int val)->bool{ return val==query; })) {
      cout << "found " << query << " in the container\n";
   }
   else {
      cout << "your query: " << query << " is not inside the container\n";
   }
}

int main(int argc, char* argv[]) {
   testfind();

   return 0;
}

Say this file is named 'testalgorithm.cpp' you need to compile it with

g++ -std=c++11 -o testalgorithm testalgorithm.cpp

Hope this will help. Please update or add if I have made any mistake.

Bludzee
  • 2,733
  • 5
  • 38
  • 46
Kemin Zhou
  • 6,264
  • 2
  • 48
  • 56
-2

You can do it in a beginners style by using control statements and loops..

#include <iostream>
using namespace std;
int main(){
    int arr[] = {10,20,30,40,50}, toFind= 10, notFound = -1;
    for(int i = 0; i<=sizeof(arr); i++){
        if(arr[i] == toFind){   
            cout<< "Element is found at " <<i <<" index" <<endl;
            return 0;
        }   
    }
    cout<<notFound<<endl;
}
-6

C++ has NULL as well, often the same as 0 (pointer to address 0x00000000).

Do you use NULL or 0 (zero) for pointers in C++?

So in C++ that null check would be:

 if (!foo)
    cout << "not found";
Community
  • 1
  • 1
canhazbits
  • 1,664
  • 1
  • 14
  • 19