Teil aus einem String herauslesen
-
Hallo zusammen,
momentan mache ich folgendes im einen Teilstring aus einem String auszulesen :
if (*_current == '<') { char * workptr = _current+1; // Next we expect the name of the element to be retrieved if (!memcmp(workptr,tag,strlen(tag))) { char* endtag = (char*)malloc(strlen(tag)+4); sprintf(endtag,"</%s>",tag); // search for the end tag char * endptr = strstr(workptr,endtag); if (endptr) { workptr = endptr + strlen(endtag); buffer.append(_current,workptr -_current ); _current = workptr; return true; }D.h. ich habe ein Element z.B. <TAG> und später ein </TAG> und alles was dazwischen ist, möchte ich in den Buffer einfügen, das geht auch alles prima mit dem Code.
Problematisch wird es allerdings wenn ich in dem String eine Abfolge von folgendem habe :
<TAG>fniifnwinfinf<TAG>fjebfijew<TAG>kfnjfiff</TAG>kjfbkbfkj</TAG>kjfbjekfeb</TAG>
dann würde er mir mit obigem Code ja den Inhalt bei den beiden hinteren </TAG>s vergessen.
Jetzt wäre meine Überlegung gewesen ob man nicht irgendwie das ganze mit Iteratoren lösen könnte, dass man einen string::iterator von vorne losschickt und das <TAG> suchen lässt und einen string::reverse_iterator von hinten laufen lässt der dann nach </TAG> sucht...
allerdings weiß ich nicht so recht ob das geht und wenn dann wie ?
Vielleicht habt Ihr ja eine Idee wie ich das am effektivsten lösen kann ...
DANKE
-
Hi,
also ich würde ja mit C++ arbeiten, wenn ich könnte....

also statt char* mit std::string .. da gibt's dann auch insert() für. (dann aber auch ohne memcpy, strlen, sprintf, ....)Letztlich kommt es genau zu dem von Dir beschriebenen Problem: Ein längerer String braucht mehr Platz.
Den musst Du also entweder beschaffen (z.B. mit new[] und die bisherigen Daten reinkopieren) oder voraussetzen (einfach "verschieben und hoffen, dass der Aufrufer dafür gesorgt hat, dass er "hinten noch genug Platz" hat.
Dieses "Kopieren und verlängern" erledigt std::string jedenfalls für Dich.Gruß,
Simon2.
-
Schau dir mal Regular Expressions an... zb in den Boost-Libraries enthalten. Damit sollte das sehr einfach sein...
http:\\boost.org
-
und an sonnsten würde ich mir halt merken auf welcher ebene du bist ...
std::string test("<foo>test01<foo>test2<foo>test3</foo></foo></foo>"); std::size_t pos_beg = test.find_first_of("<foo>"); std::size_t pos_end = test.find_first_of("</foo>"); std::cout << test.substr(pos_beg, pos_end - pos_beg) << std::endl;void get_tag_string(const std::string& string, const std::string& tag, std::string& result) { std::string tag_beg("<"); tag_beg += tag + ">"; std::string tag_end("</"); tag_end += tag + ">"; std::size_t pos_beg = string.find_first_of(tag_beg); std::size_t pos_end = string.find_first_of(tag_end, pos_beg); std::size_t pos_tmp = string.find_first_of(tag_beg, pos_beg); if (pos_tmp > pos_end) { result = string.substr(pos_beg, pos_end - pos_beg); return; } std::size_t layers = 0; for (std::size_t pos = pos_tmp; pos != std::string::npos; pos = string.find_first_of(tag_beg, pos)) ++layers; for (std::size_t pos = pos_end; pos != std::string::npos && layers != 0; pos = string.find_first_of(tag_end, pos)) { --layers; pos_end = pos; } result = string.substr(pos_beg, pos_beg - pos_end); }sollte schon eher gehen ... ist aber nicht getestet ...