9

I need to get number of character in array.

const char myarray[5] = {'0', 'a', 'e', 'f', 'c'}; // Create array of char
int number=0; // Create variable
number = getposition(myarray, 'f'); // Now number equals to 3
number = getposition(myarray, 'z'); // -1, because array doesn't have this char

My task is easy because array don't have repeating characters (for example, it can't be smth like this: {'a', '1', 'f', 'a'}). How can I do it?

5
  • You mean 'the indices of a character'? Commented Oct 24, 2011 at 12:29
  • You could return an array of position. Commented Oct 24, 2011 at 12:29
  • Yes. Not indices, but one index: as I've said, there are no repeating characters. Commented Oct 24, 2011 at 12:31
  • memchr is your friend - unless this is homework - in which case - you should think about it.... Commented Oct 24, 2011 at 12:34
  • No, this is an algorhythm of decoding. I can make construction with a hundreds of if or use case, but I think there could be more effective decision. Commented Oct 24, 2011 at 12:53

6 Answers 6

16

A little bit more C++:

#include <algorithm>

int getposition(const char *array, size_t size, char c)
{
     const char* end = array + size;
     const char* match = std::find(array, end, c);
     return (end == match)? -1 : (match-array);
}

A lot more C++:

template <typename T, size_t N>
int getposition(const T (&array)[N], const T c)
{
     const T* match = std::find(array, array+N, c);
     return (array+N==match)? -1 : std::distance(array, match);
}

Bonus C++11/C++11 update

#include <algorithm>
#include <iterator>

template <typename Range, typename T>
size_t index_of(Range const& range, T const& c) {
    using std::begin;
    using std::end;

    auto b = begin(range), e = end(range);
    auto match = std::find(b, e, c);

    return (e==match)? -1 : std::distance(b, match);
}

Bonus C++17 update

Here, the original question gets direct support in std::string_view:

Live On Coliru

#include <string_view>
using namespace std::string_view_literals;

int main() {
    return "hello"sv.find('e');
}
Sign up to request clarification or add additional context in comments.

6 Comments

The first is really the only correct answer in C++. If the question were in C, then the response is memchr (mentioned by another poster). The problem is a classical linear search, and you don't reinvent the wheel (unless that is the target of the exercise).
The first one here is definitely wrong, since it uses strlen instead of the size parameter, and we don't know whether the array is a string (the one in the example isn't) and if so whether the 0 terminator is supposed to be searched or not. But otherwise it's basically the right thing. You could have an "even more C++" version using std::begin(array), std::end(array), although then it also wouldn't need to advertise the template deduction trick for capturing N, because it could just take a single template argument Range.
@SteveJessop: Hehe. Can you tell I copied that from the OP... That's what I deserve for copy-pasting without reading it well :( Fixed. About the Range-based version, I considered adding it (but I was already at 2 options, and it turns out speed matters at SO)
In the second code block, end is not defined. However, in the first code block, it is defined. Did I miss something here?
@JamesLittle Wow. How did that go unnoticed for all these years. I took the opportunity to add c++11, c++14 and c++17 versions that are informative and more elegant, respectively! Cheers
|
8
#include <algorithm>

template <typename T, size_t size>
int getposition(T const (&array)[size], T const & c)
{
    T const * found = std::find(&array[0], &array[size], c);
    return found == &array[size] ? -1 : found - array;
}

7 Comments

Very nice but quite cryptic ;)
I really want to +1 this, if only found - array were replaced by std::distance(array,found).
@xtofl: I don't really see any point in that - this function specifically deals with an array, not a generic iterator range.
@MikeSeymour: I edited the post : the type T was missing in the second parameter. Hope it is okay with you.
@Nawaz: no it wasn't; I've rolled back to remove the duplicated T.
|
5

You need to tell the getposition() method how many elements to search within the array and as the array is initialised at compile time you can use the sizeof directive:

int number = getposition(myarray, sizeof(myarray), 'f');

...

int getposition(const char *array, size_t size, char c)
{
    for (size_t i = 0; i < size; i++)
    {
        if (array[i] == c)
            return (int)i;
    }
    return -1;
}

14 Comments

Using more than one return in a function doesn't help maintenance and legibility.
@m0skit0: That's a matter of preference. IMO saving the value in an extra var and exiting the loop when you know that you can return immediately doesn't help either.
@m0skit0: adding extra variables and break statements wouldn't help either.
@m0skit0: You'd need to add a break (or a more complicated termination condition), and a variable to store the return value, in order to follow your advice and avoid an early return. Or do you have a suggestion that avoids an early return and somehow manages to be more legible than this?
I happen to agree with the single return concept, but not in trivial functions like this where maintenance is not a consideration, given the size of the function. I don't think @m0skit0 has really provided the 'proof' that a single return is king - his answer is way more complicated than it needs to be and maintenance would be a real concern.
|
2
int getposition(const char* a, int arr_size, char to_find)
{
    int pos = -1;

    for(int i = 0; i < arr_size; ++i)
    {
        if(a[i] == to_find)
        {
            pos = i;
            break;
        }
    }

    return pos;
}

3 Comments

Won't even compile... And that's no function. Please make sure of your answers before posting ;)
Updated with something that compiles and works. My first answer was, frankly, rubbish. The other answers are also much cleverer than mine :-)
@m0skit0: your answer won't compile either; do you know the saying 'people in glass houses...'?
1

If this really is a pure decoding exercise - why not re-organize your array... then lookup is constant time - e.g..

int lt[128]; // ignoring negative values..

memset(lt, -1, 128); // initialize all to -1

// set the ones you want mappings for..
lt['0'] = 0;
lt['a'] = 1;
lt['e'] = 2;
lt['f'] = 3;
lt['c'] = 4;

so now your look up function is:

int indexOf(char v) { return lt[v]; }

You'd be hard-pressed to beat that for performance...

Comments

-2

You need to pass the array size as well to the function.

int getposition(const char* array, size_t array_size, char value)
{
    int ret = -1;

    int i = 0;
    bool found = false;
    while (i < array_size && !found)
    {
        found = (array[i++] == value);
    }

    if (found)
    {
        ret = i - 1;
    }

    return ret;
}

8 Comments

:) seems we both overcomplated things: the first occurence will do.
I'm returning on the first occurence mate ;) The while() loop end on first occurence. Don't downvote without actually understanding the code ;) And I didn't downvote you btw because your answer was a valid one. I simply critized the form :P
Sorry - I read over the !found condition. Adding an explicit return would have prevented that :). But I downvoted because you wrote the function instead of using the standard library.
Curiously enough, trojanfoe didn't get any downvote from you. And I don't want to add an extra return, that's the point ;)
@m0skit0: You have some errors in your answer: the input array should be const char *. You shouldn't initialise an unsigned type (ret) with -1 and boolean isn't a valid C++ keyword. This question was about the size of an array, not how to program dogmatically.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.