0

this is somewhat of an odd question.

I wrote a C function. Its 'like' strchr / strrchr. It's supposed to look for a character in a c-string, but going backwards, and return a pointer to it. As c strings are not "null initiated", it also takes a third parameter 'count', indicating the number of chars it should look backwards.

/*
*s: Position from where to start looking for the desired character.
*c: Character to look for.
*count: Amount of tests to be done
*
* Returns NULL if c is not in (s-count,s)
* Returns a pointer to the occurrence of c in s.
*/
char* b_strchr(const char* s,int c,size_t count){

    while (count-->0){

        if (*s==c) return s;
        s--;
     }
     return NULL;
}

I have done some testing on it, but Do you see any flaws in it? Security issues or so? Any enhancements? Could it be improved? And more important: Is this a bad idea?

Some usage.

    char* string = "1234567890";

    printf("c: %c\n",*b_strchr(string+9,'5',10));//prints 5

    printf("c: %c\n",*b_strchr(string+6,'1',7));//prints 1

EDIT: New interface, some changes.

/*
* from:  Pointer to character where to start going back.
* begin: Pointer to characther where search will end.
*
* Returns NULL if c is not between [begin,from]
* Otherwise, returns pointer to c.
*/
char* b_strchr(const char* begin,int c,const char* from){


    while (begin<=from){

        if (*from==c) return from;
        from--;
     }
     return NULL;
}
Michael Myers
  • 188,989
  • 46
  • 291
  • 292
Tom
  • 43,810
  • 29
  • 138
  • 169

4 Answers4

5

It's better with the edit, but the interface is still surprising. I'd put the begin parameter (the haystack being searched) as the first parameter, the c parameter (the needle being searched for) second, and the from parameter (start position of the search) third. That order seems to be idiomatic across a fairly large set of APIs.

Norman Ramsey
  • 198,648
  • 61
  • 360
  • 533
2

The code has an esoteric interface - pass in a pointer to the last character of the string and the length of the string. That will lead to problems using it.

(Alternatively, the code has a bug - you should add count to s before the loop.)

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • @Jonathan Thanks for your insight. What bug do you refer to?. What i was aiming to is that s points to the character from where to start looking back. – Tom Jul 03 '09 at 01:59
  • 1
    @Tom: if the interface is as you intended, then there is no bug. However, most people, most of the time, keep a pointer to the start of the string and sometimes (in this case necessarily) the length of the string. That means people will have to do the addition you show. A more conventional interface would have the first argument point to the start of the string; the function would do the addition. Note, too, the uncomfortable pattern 's+9' and 10, 's+6' and 7. The what is the betting someone will get that wrong? – Jonathan Leffler Jul 03 '09 at 02:12
  • @Jonathan, Thanks again. I see what you mean. Changed function's interface, see my edit, i think its much better now. – Tom Jul 03 '09 at 02:37
1

If begin is from, the current code will always return begin, which is not what you want. The code after the loop can just be return NULL. And instead of begin != from in the loop condition, I would use begin < from otherwise you will pointer arithmetic overflow when someone mixes up the order of the parameters.

Edit: on second thought since you want [begin, from] inclusive it should be begin <= from

user85509
  • 36,612
  • 7
  • 33
  • 26
1

I wrote a C function. Its 'like' strchr / strrchr.

You've attempted to reinvent strrchr(), so it's not like strchr().

Do you see any flaws in it?

Yes. Several. :-(

Since b_strchr() can return NULL, you shouldn't put it directly into the printf() statement. Deferencing NULL usually results in a segfault.

You may be better off with your favourite variation of ...

char *result;

result = b_strchr(string + 9, 'a', 10));
if (result == NULL)
{
    printf("c: NULL\n");
}
else
{
    printf("c: %c\n", *result);
}

Also, when

(count >= length of the input string) and the character is not found

you're going to get unpredicable results because s is no longer pointing to a character in the string — s is pointing to memory before the beginning of the string. As an example, try

result = b_strchr(string + 9, 'a', 11));
if (result == NULL)
{
    printf("c: NULL\n");
}
else
{
    printf("c: %c\n", *result);
}

and see what happens.

Expand your use test cases to include conditions outside of what you know will work successfully. Ask someone else to help you design test cases that will really test your code.

And more important: Is this a bad idea?

As a learning exercise, absolutely not.

However, in this case, for production code you'd be better off sticking to the standard strrchr().

Convict
  • 506
  • 2
  • 4
  • I see what you mean, but strrchr is not what i need. What i need is look for a character in lower addresses that where im standing. As for the printf tests, yes you are right. I did those intentionally on cases that wouldnt return null, but thanks for your input. Please, see that there is an updated version. – Tom Jul 03 '09 at 03:31