Reputation: 5237
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?
Upvotes: 1
Views: 88
Reputation: 1886
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);
}
Upvotes: 2
Reputation: 33014
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';
Upvotes: 1
Reputation: 16059
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, "<");
}
Upvotes: 1