c++ Insert into Char* str

Hi

I have a char pointer (char * notmystuff) to html content. It has start html and end html tags and bunch of html code in between,.

i have another char * mystuff which has a anchor html tag like

<a href = "some website"> some text </a>

I want to  insert mystuff  into the original notmystuff  so that correct html is displayed..

i guess that means ..detecting the last </body> </html> tags...abd inserting " mystuff" just before body?


Any ideas on the best way to do this?
VlearnsAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

VlearnsAuthor Commented:
i also have lengths of both "notmystuff" and "mystuff"
0
evilrixSenior Software Engineer (Avast)Commented:
>> Any ideas on the best way to do this?
Use a proper HTML parser (something like el kabong). Trying to parse HTML yourself from scratch is going to be a right pain unless you have absolute control of the HTML. A proper parser will take care of all the hard work for you leaving you to focus on your business logic.

http://sourceforge.net/projects/ekhtml/
0
phoffricCommented:
You can use strstr() to find a string within a string:
const char * strstr ( const char * str1, const char * str2 );
         char * strstr (         char * str1, const char * str2 );
strstr returns a" pointer to the first occurrence in str1 of any of the entire sequence of characters specified in str2, or a null pointer if the sequence is not present in str1."
    http://www.cplusplus.com/reference/clibrary/cstring/strstr/

Here is sample code that illustrates how to use it.
/* strstr example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char str[] ="This is a simple string";
  char * pch;
  pch = strstr (str,"simple");
  strncpy (pch,"sample",6);
  puts (str);
  return 0;
}

Open in new window

0
Introducing Cloud Class® training courses

Tech changes fast. You can learn faster. That’s why we’re bringing professional training courses to Experts Exchange. With a subscription, you can access all the Cloud Class® courses to expand your education, prep for certifications, and get top-notch instructions.

phoffricCommented:
Since there may be nested tags, it is up to you to identify the matching end tags with their originating tag.
0
evilrixSenior Software Engineer (Avast)Commented:
>> Since there may be nested tags, it is up to you to identify the matching end tags with their originating tag.
And as this can get very complex (I've written enough parsers to know what a pain this can be) I strongly recommend against trying to roll your own HTML parser -- there are just too many edge cases to consider and unless you have strict control of the HTML you will be forever added code to deal with another "special case" (unfortunately HTML is a very flexible protocol and parsers have to be very forgiving since HTML can be malformed and most browsers will still parse it). For this reason, unless this is an exercise that specifically requires you to parse HTML yourself, really - don't bother. Using a Sax style parser is just way simpler and el kabong (that I recommended earlier) is very light weight, simple to use and fast (very fast).
0
VlearnsAuthor Commented:
can there be two </html> or </body> tags in a valid html document?
0
evilrixSenior Software Engineer (Avast)Commented:
No, but that doesn't mean there won't be and even if there is the html is still generally going to be ok in terms of being rendered. The thing with html is that unlike xml, which has strict rules that compliant parsers are obliged to enforce, html parsers are not. This being the case the chances of being presented with malformed html are much higher.

If you are in control of the creation of the html you can probably get away with rolling your own parser but if you are not then your parser needs to be able to cope with malformed html or you run the risk of getting unexpected parsing results that mean you'll keep having to add support for edge cases.

A tried and tested sax parser will already be able to cope with such problems (often having configuration options to control how the parser should deal with them), making your life a lot simpler.

Html is a real pain to parser properly. If what you are doing is more than a quick and dirty solution yoou really are better off leaving the parsing up to a proper parser.
0
VlearnsAuthor Commented:
in this code example attached by phoriffic

int main ()
{
  char str[] ="This is a simple string";
  char * pch;
  pch = strstr (str,"simple");
  strncpy (pch,"sample",6);
  puts (str);
  return 0;
}


simple is of the same size as sample

my problem is the following

int main ()
{
  char str[] ="This is a simple string whose size i know";
  char * pch;
  pch = strstr (str,"simple");
  strncpy (pch,mycontent,sizeof(mycontent));
  puts (str);
  return 0;
}

Making the change as above is causing the program to crash


0
VlearnsAuthor Commented:
strncpy (pch,ad_content,sizeof(ad_content));
memset(ad_content,32, sizeof(ad_content));//blank spaces
memcpy(ad_content,tag.c_str(),tag.size());

   char * pch;
   pch = strstr (_in_mem_msg_ptr->buff(),"</body></html>");
   strncpy (pch,ad_content,sizeof(ad_content));
   strncpy (pch,"</body></html>", sizeof("</body></html>"));

this is my code

that crashes at  strncpy (pch,ad_content,sizeof(ad_content));

can you help me debug?
0
phoffricCommented:
How many bytes is mycontent? If sizeof(mycontent) were a few bytes, say 10, then you should be OK, but if it were large, say, 100, then you could overrun the str buffer.
int main ()
{
  char str[] ="This is a simple string whose size i know";
  char * pch;
  pch = strstr (str,"simple");
  strncpy (pch,mycontent,sizeof(mycontent)); // this could overun the str[] buffer and cause crash
  puts (str);
  return 0;
}

Open in new window

0
VlearnsAuthor Commented:
 char * pch;

    tag = tagObj.findTag(getLocationIdByName("us"), rcptList,"html","sbc" );


    char ad_content[300 + 1];  

    memset(ad_content,32, sizeof(ad_content));//blank spaces

   
   memcpy(ad_content,tag.c_str(),tag.size());
 

   pch = strstr (_in_mem_msg_ptr->buff(),"</body></html>");
   strncpy (pch,ad_content,sizeof(ad_content));
   strncpy (pch,"</body></html>", sizeof("</body></html>"));



it crashes at strncpy (pch,ad_content,sizeof(ad_content));

0
VlearnsAuthor Commented:
to phorrific:

yes thats what happening

how do i

increase the size of str buffer so that it can hold the content (which is always 300 characters)

originally
str = original content

after modification

str = original string before </body> + mycontent(300 chars) + original string after </body>

0
phoffricCommented:
If you start using the C++ class, then you could use the string::replace operation:
     http://www.cplusplus.com/reference/string/string/replace/

Otherwise, using c-strings, the easiest way is to have a source buffer (initialized to 0) and a destination buffer. Then strcat the individual string pieces into the destination buffer.

Naturally, you want the destination buffer to be well oversized to handle unanticipated growth in your requirements. And you want to manage the number of bytes so that you don't write more into the destination buffer than there is space. (And don't forget the terminating null byte.)
0
phoffricCommented:
Hi Vlearns,
   I'll be here a for just a little longer; if you have questions on my latest post, I'll be back tomorrow to see them.
    Paul
0
VlearnsAuthor Commented:
   
/* original data */
        data = _in_mem_msg_ptr->buff();
        data_len = _in_mem_msg_ptr->dataLen();


/*location of </body> in the original */

        char *insert = strstr(data, "</body>");

/*length of the new buffer string */

        int length = strlen(data)+strlen(ad_content);
        newdata =(char*)malloc(sizeof(char)*length);
        memset(newdata, 0, length);

/*copy the original data upto </body> into newdata*/

        memcpy(newdata,data,insert-data);

/*now add the ad_content */
        strcat(newdata,ad_content);

/*copy the data from </body> to end of original string(data) into newdata */

        memcpy(newdata,data,data_len - ending );

how do i implement the the last statement : memcpy(newdata,data,data_len - ending );

      i  need to copy the remainer of the data from my char* data beginning from and including </body> to the very end...how do i correctly compute the "ending" parameter in the memcpy?
 
0
VlearnsAuthor Commented:
       data = _in_mem_msg_ptr->buff();
        data_len = _in_mem_msg_ptr->dataLen();
        char *insert = strstr(data, "</body>");
        int length = strlen(data)+strlen(ad_content);
        newdata =(char*)malloc(sizeof(char)*length);
        memset(newdata, 0, length);
        memcpy(newdata,data,insert-data);
        strcat(newdata,ad_content);
        memcpy(newdata,data,data_len - ending );
0
phoffricCommented:
>>     newdata =(char*)malloc(sizeof(char)*length);
I don't believe you made room for the terminating null byte. This omission can cause bugs and even crashes in your program (or worse, it may work now, but eventually fail later when you add a benign simple code addition).

>> memset(newdata, 0, length);
If you are going to zero out the entire allocated region by using memset, you should consider using calloc instead to replace the malloc and the memset.
     http://www.cplusplus.com/reference/clibrary/cstdlib/calloc/

>> i  need to copy the remainer of the data from my char* data beginning from and including </body> to the very end

Since you used the expression, strlen(data), this must mean that data is a bonafide c-style string ending in a terminating null byte. And since you already computed the char * insert pointer which points to the start of </body>, then you can think of insert as a pointer to a bonafide c-style substring of data.

The easiest way to complete this is just to concatenate this substring to newdata, which you have assured is a c-style string since you initialize the entire allocated region with 0's.

If the strcat resulted in performance degradation, then compute the offset into newdata where the current null byte is, and then you can memcpy starting at newdata + offset.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
VlearnsAuthor Commented:
how can i use c++ string class to achieve the same?

thanks!
0
VlearnsAuthor Commented:


does this sound right to you?

        char *insert = strstr(_in_mem_msg_ptr->buff(), "</body>");//get pointer to </body>
       string ad_data = string(_in_mem_msg_ptr->buff(),insert - _in_mem_msg_ptr->buff()) ;//insert the part of _in_mem_msg_ptr->buff() before the </body>
       ad_data.append(ad_content); //add the new html content
       ad_data.append(_in_mem_msg_ptr->buff(),insert- _in_mem_msg_ptr->buff(),_in_mem_msg_ptr->dataLen()); //remainder of _in_mem_msg_ptr->buff() from and including </body> to the end

0
phoffricCommented:
>> how can i use c++ string class to achieve the same?
Good question. I think the question to be asked in a separate question to keep the C and C++ concepts separated for the PAQ. If doing this, be clear what your input is and what you expect the output to be (e.g., using one of the simple examples, as in http:#35389759 ). Also, in your example, it might be best (if your application allows it) to avoid the char type by replacing it with the string class.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.