firstlegagain1
firstlegagain1

Reputation: 127

How to search a char in a char array in if condition statement

Is there any function which can help me do the following much more easily?

char ch = '+';
if (( ch == '+') || (ch == '-') || (ch == '*'))
{
    //do something
}

Since have to check this several times in my code, I would prefer if there was any to do it similar to

char arr ={'+','-','*'};
if (ch in arr)
{
    //do something 
}

Upvotes: 1

Views: 965

Answers (6)

Code-Apprentice
Code-Apprentice

Reputation: 83577

For this specific case, you can wrap the boolean expression in your own custom function:

bool isOperator(char ch) {
    return ( ch == '+') || (ch == '-') || (ch == '*');
}

This will reduce the redundancy in the rest of your code since now you can just do

if(isOperator(ch))

Upvotes: 0

Mahmoud Hanora
Mahmoud Hanora

Reputation: 307

try this

#include <algorithm>

int main() {
   char arr[] ={'+','-','*'};
   char ch = '-';
   if(std::find(arr, arr+sizeof(arr)/sizeof(char), ch) - arr < sizeof(arr)/sizeof(char)){
   //do anything 
   }
   return 0;
}

Upvotes: 1

Bartek Banachewicz
Bartek Banachewicz

Reputation: 39390

For me, at first glance, this is a set lookup: is this element any of those is equivalent to does this set of elements contain this one. And, as such:

if ((std::set<char> {'a','b','c'}).count(x) > 0) {
    // ...
}

See it on Coliru

Upvotes: 0

Passer By
Passer By

Reputation: 21160

This makes any a compile time construct if your array is too. I can't really think of a way to make this more optimized if the range is arbitrary.

I've chosen to overload == because it looks nicer than passing the arguments side by side.

#include<iterator>

template<typename Iter>
class any
{
public:
    using value_type = typename std::iterator_traits<Iter>::value_type;

    constexpr any(Iter begin, Iter end) : begin{begin}, end{end} {}
    template<typename T, size_t N>
    constexpr any(T (&arr)[N]) : any{arr, arr + N} {}

    constexpr bool operator==(const value_type& v)
    {
        return compare(v, begin);
    }
private:
    Iter begin, end;
    constexpr bool compare(const value_type& v, Iter it)
    {
        return it != end && (v == *it || compare(v, it + 1));
    }
};

template<typename T, size_t N>
any(T (&)[N]) -> any<T*>;

template<typename T, typename Iter>
constexpr bool operator==(const T& t, any<Iter> a)
{
    return a == t;
}

This results in a nice looking format

static_assert('+' == any("+-*"), "Failure!");

constexpr char ops[] = {'+', '-', '*'};
char c = '/';
if(c == any(ops))
    do_stuff(c);

Explanations

using value_type = typename std::iterator_traits<Iter>::value_type;

is to alias the type Iter dereferences to as value_type.

template<typename T, size_t N>
any(T (&)[N]) -> any<T*>;

is to deduct the type of any without explicit template parameters.

return it != end && (v == *it || compare(v, it + 1));

is to recursively check if the range has been exhausted and if not, check if the value is equal to the current element.

Note that any("+-*") has 4 characters in it, the last one being '\0'.

Upvotes: 0

Vittorio Romeo
Vittorio Romeo

Reputation: 93384

You can write a function that generates code equivalent to

if (( ch == '+') || (ch == '-') || (ch == '*'))

with a better user syntax.


template <typename X>
bool any(const X&) noexcept
{
    return false;
}

template <typename X, typename T, typename... Ts>
bool any(const X& x, const T& curr, const Ts&... rest) noexcept
{
    return x == curr || any(x, rest...);
}

Usage:

if(any(ch, '+', '-', '*')) { /* do something */ }

As shown by this godbolt.org comparison, this is an example of a zero-cost abstraction.

In C++17 you could use a fold expression:

template <typename X, typename... Ts>
bool any(const X& x, const Ts&... rest)
{
    return ((x == rest) || ...);
}

If you want to reuse the same comparison values multiple times without repeating yourself, you can create a "curried" version of any that first binds the arguments to check against and then does the comparison on a subsequent call.

template <typename... Ts>
auto bound_any(const Ts&... xs)
{
    return [xs...](const auto& x)
    {
        return ((x == xs) || ...);
    };
}

Usage:

auto is_op = bound_any('+', '-', '*');
if(is_op(ch)) { /* do something */ }

Here's a godbolt.org comparison.

Upvotes: 3

M.M
M.M

Reputation: 141648

In this case you can use:

if ( std::strchr("+-*", ch) )

The strchr function, from #include <cstring>, returns a null pointer iff the character is not found in the string.

Upvotes: 4

Related Questions