1

I saw this question but none of the answers were quite what I was looking for. I've tried strstr but it returns a pointer instead of an integer index.

I need to find if string a contains string b and if so, where it's located, kind of like the index returned by strcmp. Is there a function or easy way to do this in C?

For example, if a is "foobar" and b is "bar", then this function/method would return 3 because "bar" is at index 3 of "foobar".

Any help is appreciated!

2
  • strstr does just that - if it doesn't work as you expect it to, you should post your code here and explain the problem you have with the behavior of strstr in it. Commented Nov 4, 2016 at 20:48
  • 3
    "bar" is at index 3 in "foobar", not 2. Commented Nov 4, 2016 at 20:49

3 Answers 3

4

You can use strstr for this, along with some pointer arithmetic.

char *result = strstr(a, b);
if (result != NULL) {
    printf("index = %tu\n", result - a);
}

Here, result points a particular number of bytes ahead of a. So if you subtract the two, that's your index.

Sign up to request clarification or add additional context in comments.

1 Comment

Correct. Note that Microsoft's C library and some others might not support the %lu conversion specifier. On such systems, use printf("index = %llu\n", (unsigned long long)result - a);
1

You can easily convert the returned pointer into an index by subtracting the pointer to the beginning of the string, a:

char *p = strstr(a, b);
int i = p ? p - a : -1;

(Also, strcmp doesn't return an index.)

17 Comments

@MD XF - no it does not. strcmp() can only detect the nature of the difference (is one lexicographically less than, equal to, or greater than the other). It returns no information about where the difference is.
@melpomene - i would be better with type ptrdiff_t. That is the result of subtracting pointers - and the result is not necessarily able to be stored in an int. Otherwise, your approach is okay - if strstr(a,b), if not NULL, cannot give a result less than a, so the subtraction p-a will not give a negative value.
@melpomene /tmp/test foobar Foobar - result: The difference between foobar and Foobar is 32. Here's another The difference between foobar and bar is 4. The statement: printf("The difference between %s and %s is %d\n", argv[1], argv[2], strcmp(argv[1], argv[2]));. So what's wrong? Care to explain? When in doubt, test the code.
@alvits: The tutorial from programiz.com is misleading: the value 32 could be any int value greater than 0. Nothing can be assumed about the return value of strcmp(a,b); beyond the fact that it can 0 if the strings are the same, negative if a is lexicographically less than b and positive otherwise.
The Comment in MSVC source code is rather clear: Compare strings pointed by pSrt1, pSrt2. Return 0 if same, < 0 if pStr1 is less then pStr2, > 0 otherwise. Explaining the OP how a particular library computes the different values returned is counterproductive: many casual readers will believe that you are describing what it must do instead of what it happens to do. Such misconceptions are difficult to dislodge.
|
0

Here you go:

#include <stdio.h>
#include <string.h>

int main()
{
    char str1[]="foobar";
    char str2[]="bar";
    char *ptr;
    if((ptr = strstr(str1, str2)) != NULL) {
        printf("Start offset: %td\n", ptr - str1);
    }

    return 0;
}

3 Comments

Testing will not save you from UB.
My understanding is ptrdiff_t is a signed int which is what %d in printf expects. Is that true?
No: ptrdiff_t is a signed type that can be int or larger. On linux 64-bit, it is long, on Windows 64-bit, it is long long. Either use printf("Start offset: %td\n", ptr - str1); or printf("Start offset: %lld\n", (long long)(ptr - str1));

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.