0

From this discussion, I have the following code to check if an element exists in an array:

#include <iostream>
#include <vector>

template <typename T, std::size_t N>
bool IsIn(T value, const T(&values)[N])
{
    for (const T& array_value : values)
    {
        if (value == array_value) return true;
    }
    return false;
}

int main() {

    int arr1[] = { 10, 20, 30 };
    bool ee1 = IsIn(10, arr1);
    std::cout << "ee1 = " << (ee1?"true":"false") << "\n";

    return 0;
}

I believe this code is good for array of fixed size (at compile time) only. If the array is dynamically created (the number of elements is not known at compile time), is there any way I can modify the code to accommodate it?

PS: I am aware of vector. However, I am just curious if there is any way to avoid it.

CaTx
  • 1,421
  • 4
  • 21
  • 42

3 Answers3

2

Don't use C-style arrays unless you absolutely need to. Use std::array instead. For dynamic arrays, use std::vector.

You can then use iterators to make your function generic. However, this function already exists, it's called std::find. You can try to implement your own, for learning purposes, or look up an example implementation here: cppreference | find

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

int main(){
    std::array<int, 3> static_array{1, 2, 3};
    std::vector<int> dynamic_array{3, 4, 5}; 
    std::string str = "Hello World";

    std::array<int, 3>::iterator stat_found;
    if( (stat_found = std::find(static_array.begin(), static_array.end(), 3)) != static_array.end() ){
        std::cout << "Found 3 in static_array at pos: " << stat_found - static_array.begin() << "\n";
    }

    std::vector<int>::iterator dyn_found;
    if( (dyn_found = std::find(dynamic_array.begin(), dynamic_array.end(), 3)) != dynamic_array.end() ){
        std::cout << "Found 3 in dynamic_array at pos: " << dyn_found - dynamic_array.begin() << "\n";
    }

    std::string::iterator str_found;
    if( (str_found = std::find(str.begin(), str.end(), 'W')) != str.end() ){
        std::cout << "Found W in string at pos: " << str_found - str.begin() << "\n";
    }
}
infinitezero
  • 1,610
  • 3
  • 14
  • 29
  • If the array is created from an input string, the size of the array is not known at compile time. How do you deal with it? Btw, your method seems to rely on knowing the array size at compile time. Am I right? – CaTx Jul 17 '22 at 09:08
  • @CaTx No, this is completly oblivious to the size of the array. I have updated the post to include a string example. – infinitezero Jul 17 '22 at 10:10
  • thank you so much! Looks like it's best to use `std::vector`. – CaTx Jul 17 '22 at 11:16
1

Without changing the body of your method, you can accommodate practically any collection type by abstracting over the collection type as well, i.e.

template <typename T, typename Collection>
bool IsIn(T value, const Collection &values)
{
  /* ... */
}

However, as inifnitezero noted, the standard way of doing this is actually with iterators, and many implementations already exist in the standard library for this.

mitch_
  • 1,048
  • 5
  • 14
0

For a dynamic array you have to pass in the size in some form or another.

template <typename T>
bool IsIn(T value, const T *arr, std::size_t size) { ... }

You already know about std::vector, which knows it's own size, so I will skip that. That is the way to handle dynamic arrays. But not the only way to pass them to a function.

You can use std::span, which can be used for fixed sized arrays, std::array, std::vector and any container with random access iterator (sequential iterator? not sure). It's probably the most flexible thing to use.

You can also use begin and end const iterators. But that involves a lot of typing unless you already have 2 iterators when you want to call it.

Personally I think std::span covers all the bases. You can even make a span from iterators.

Goswin von Brederlow
  • 11,875
  • 2
  • 24
  • 42