Trouble in strstr() to get string after sub-string in C

99 Views Asked by At

Currently working on developing parser using C. I wanted to extract portion of lines after a specific character set. For example, from following line "Target" need to be extracted.

"V { <Target> ;"

Now I use strstr() to locate lines contains "V { ", succeeded. but unable to remove "V { " portion to get clean target. usually strstr() supports sizeof() to make pointer beginning of "Target". But my code return nothing while using sizeof(). My code is below, thanks for your time.

while (fgets(line, MAX_LINE_LENGTH, textfile)){
    const char *p1 = strstr(line, "V {  ");        // end of this line may include offset "+5", didn't work 
    const char *p2 = strstr(p1, ";");              // returns nothing using this code.
        if (p1 != NULL){                                                   
           size_t len = p2-p1;
           char *res = (char*)malloc(sizeof(char)*(len+1));
           strncpy(res, p1, len);
           res[len] = '\0';
           printf("%s\n", res);
           }
     }
2

There are 2 best solutions below

1
XbzOverflow On BEST ANSWER

p1 points to the start of the match.
Add an offset to p1 to get rid of what you do not need.

strncpy(res, p1+3, len-3);
res[len-3] = '\0';

(3 can be some other offset, depending on what you want).

1
Oka On

As described in the comments, you may want to define your own function that increments the pointer to the start of the matched substring by the length of the search string, thus giving you the contents of the target string after the search string.

strcspn can be used to find the span (length of bytes) between the initial argument and the first character encountered that can be found in its second argument.

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

const char *str_after(const char *haystack, const char *needle)
{
    const char *start = strstr(haystack, needle);

    return start ? start + strlen(needle) : NULL;
}

int main(void)
{
    const char *val = str_after("hello world;\n", "hello ");

    if (val) {
        size_t len = strcspn(val, ";");
        char *copy = malloc(1 + len);

        if (copy) {
            memcpy(copy, val, len);
            copy[len] = '\0';
            puts(copy);
            free(copy);
        }
    }
}
world

Some things of note from your example:

In

const char *p1 = strstr(line, "V {  ");
const char *p2 = strstr(p1, ";");

if p1 is NULL, then the second call to strsr invokes Undefined Behaviour.

usually strstr() supports sizeof() to make pointer beginning of [sic]

The sizeof operator resolves to the size of an object or type in bytes. It has no inherent relationship with strstr.

It sounds like you have used sizeof on an array object in the past and are confused by the results of using sizeof on a pointer object, which of course will give you the size of the pointer itself, regardless of what it points to.

On that note, sizeof (char) is guaranteed to be 1.

Don't forget you need to free every pointer returned by malloc when you are finished using the memory, or you will be leaking memory constantly.