1

I have a string which is of the format Contact:

<[email protected]:5060;gr=xyz123>;+g134,<more_text> 

I need to extract the content between the opening < and closing > There can be multiple instances of < and > , but I have to take the content from the pair in which the parameter gr= is present (only one occurrence of this).

To solve this what I did was:

ptr = strstr(str,"gr="); if(ptr) { temp1= ptr; while(*temp1 && *temp1!='<') { temp1--; } strncpy(newstring,temp1,ptr-temp1); //will copy upto start of gr temp2 = strstr(ptr,">") if(temp2) strncat(newstring,ptr,temp2-ptr); // copy remaining string till it finds closing '>' } 

It works fine, but I would like to know if there is anyway to avoid the while loop and going backwards?

1
  • Yes, there are other ways to do it but why do you assume that they would be better? One thing you could do is build newstring all in one go (from temp1 to temp2). Commented May 23, 2014 at 14:05

3 Answers 3

2

You could search for the first occurrence of '<' and '>' and see if 'gr=' falls between them.

lt = strchr(ptr,'<'); gt = strchr(ptr,'>'); gr = strstr(ptr,"gr="); if ( gr > lt && gr < gt) { strncat(newstring,lt,gt-lt); } 
Sign up to request clarification or add additional context in comments.

7 Comments

Since the search for lt & gt is just one char, you could use strchr which is slightly faster than strstr. Anyway, your solution seems more efficient and simpler than mine. Well done.
@FabioCeconello, thanks, even the blind squirrel catches a nut sometimes.
Certainly you want strstr(ptr,"<"); or strchr(ptr,'<'); and not strstr(ptr,'<');
@chux What would happen if I wrote strstr(ptr,'<') instead of strstr(ptr,"<") ?
@CDahn Did you want this in a loop? Because otherwise if gr parameter is not in the first pair of < > this wont work !
|
1

You can use strcspn to get the offset to the next marker. Your code doesn't have the loop to look for the next instances, but this code does. I assume your loop is outside that, maybe you'll need to adapt a bit.

size_t offset = 0, length; offset = strcspn(str, "<"); while (str[offset] != '\0') { ++offset; length = strcspn(str + offset, ">"); ptr = strstr(str + offset, "gr="); if (ptr != NULL && ptr - str < offset + length) { strncpy(newstring, ptr + offset, length); /* do what you need with newstring here */ } offset = strcspn(str + offset + length + 1, "<"); } 

1 Comment

Thanks! But I think @CDahn solution is really simple :)
1

You can do this by parsing the string exactly once and not more (unlike other answers here). The code below can handle any substring you give provided the substring doesn't have any repeated characters.

The idea is to copy anything in between any < and >; while copying look for the substring, if it's not found, then continue until it's found.

char *str = "<[email protected]:5060;gr=xyz123>;+g134,<more_text>"; char result[MAX_LENGTH]; size_t i = 0, j = 0; char copying = 0, found = 0; const char *subs = "gr="; const int subs_len = 3; while ((char ch = *str)) { if (ch == '<') copying = 1; else if (ch == '>') { if (found) break; else { copying = 0; i = j = 0; } } else if (copying) { result[i++] = ch; if (!found) { if (ch == subs[j]) { ++j; if (j == subs_len) found = 1; } else { j = (ch == subs[0]) ? 1 : 0; } } } ++str; } result[i] = '\0'; 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.