Lostsoul
Lostsoul

Reputation: 26037

Is there an indexOf equivalent for arrays in C?

I'm brand new to C and hope there's something built in that I can use. Say I have a list and I want to find the location of a list(all items in the lists are unique). Like so: char *name[] = {"monkey", "pig", "goat", "dog", "cat"}; I tried:

   char *name[] =  {"monkey", "pig", "goat", "dog", "cat"};
   int *found = strstr (*name,"dog");
   printf("Found at %i \n", found); //expect 3(or 4, if it doesn't use 0s) result

but it keeps giving me the result of 2(even if I put names that don't exist). I swapped strstr with strcspn with no luck either.

I am asking because I wasn't sure and I created my own function to do this but its pretty crappy and not very flexible(I hardcode the list name in it), I figured if there's something within C then it'll be better for me. Here's the function I made(cover your eyes if you don't want to lose brain cells reading it, joking :-):

int indexOf(char nameToFind) {
    //returns the location of an item in a list
    int pos = -1;
    int i;
    for (i = 0; i < sizeof(name) / sizeof(name[0]) && pos == -1; i++)
    {
        // Assuming there is a char[] field called name in Stdinfo
        if (*name[i] == nameToFind) {
            pos = i;
        }
    }
    return pos;
}

Does something like this exist in C that would be faster & more flexible than my version?

Upvotes: 4

Views: 16384

Answers (2)

Joshua Green
Joshua Green

Reputation: 1575

The code your wrote is wrong on a few levels. Your line

char *name[] = {"monkey", "pig", "goat", "dog", "cat"};

creates an array of char pointers, each pointing to a NULL-terminated string. So far, so good. However, your line

int *found = strstr (*name,"dog");

sets found to a pointer to the first occurrence of "dog" in *name = name[0] = "monkey". Besides not looking through the array name as you intend, you're also assigning the char * returned by strstr to an int *. Not good. Your next line

printf("Found at %i \n", found);

tries to print found, but the specifier requires an int and you're passing it found, an int *. These are all things to avoid, and I think a lot of this is undefined behavior.

What you want is a loop that uses strcmp, for example:

char *name[] = {"monkey", "pig", "goat", "dog", "cat"};
unsigned int numElements = sizeof(name)/sizeof(name[0]);
unsigned int i;
for(i = 0; i < numElements; ++i) {
    if (strcmp(name[i], "dog") == 0) {
        printf("Found at %u\n", i);
        break;
    }
}
if (i >= numElements) {
    printf("Not found\n");
}

Computing numElements in this way won't work if you pass the array into a function, so you'll have to explicitly pass the number of elements in that case.

Upvotes: 6

templatetypedef
templatetypedef

Reputation: 373042

For character arrays, there is the strchr function, which searches an array for a character. If it finds it, it returns a pointer to that character. If not, it will return a NULL pointer. You can then use pointer subtraction to determine the index.

For general arrays, there is the library bsearch function if the array is sorted. Most compilers provide an lsearch nonstandard function that just does a linear search over the array to find a given value.

If you are using C++, then you have access to the find, lower_bound, and upper_bound STL algorithms, which perform similar tasks.

Hope this helps!

Upvotes: 1

Related Questions