2009-05-22 4 views
2

Für eine Schulaufgabe muss ich ein Projekt in C++ mit Borland C++ Builder implementieren.Konvertieren von C++ Builder AnsiString in std :: string über boost :: lexical_cast

Da die VCL AnsiString für alle GUI-Komponenten verwendet, muss ich alle meine std :: strings in AnsiString konvertieren, um sie anzuzeigen.

std::string inp = "Hello world!"; 
AnsiString outp(inp.c_str()); 

funktioniert natürlich, aber ist ein bisschen langweilig zu schreiben und Code-Duplizierung möchte ich vermeiden. Da wir Boost in anderen Kontexten verwenden, entschloss ich mich, einige Hilfsfunktionen zur Verfügung zu stellen. Holen Sie sich boost :: lexical_cast, um mit AnsiString zu arbeiten. Hier ist meine Umsetzung so weit:

std::istream& operator>>(std::istream& istr, AnsiString& str) { 
    istr.exceptions(std::ios::badbit | std::ios::failbit | std::ios::eofbit); 
    std::string s; 
    std::getline(istr,s); 
    str = AnsiString(s.c_str()); 
    return istr; 
} 

Am Anfang habe ich Zugriffsverletzung nach Zugriffsverletzung, aber da ich die .exceptions hinzugefügt() stopft das Bild klarer wird. Wenn die Konvertierung durchgeführt wird, ich die folgende Ausnahme erhalten:

ios_base::eofbit set [Runtime Error/std::ios_base::failure] 

Hat jemand eine Idee, wie es zu beheben und kann erklären, warum der Fehler auftritt? Meine C++ Erfahrung ist sehr begrenzt.

Die Konvertierungsroutine die andere Art und Weise würde rund sein:

std::ostream& operator<<(std::ostream& ostr,const AnsiString& str) { 
    ostr << (str.c_str()); 
    return ostr; 
} 

Vielleicht hat jemand einen Fehler hier erkennen :)

Mit freundlichen Grüßen!

Edit:

Im Moment bin ich die bearbeitete Version von Jem verwenden, funktioniert es am Anfang. Nach einer Weile der Verwendung des Programms erwähnt der Borland Codeguard einige Zeigerarithmetik in bereits freigegebenen Regionen. Irgendwelche Ideen, wie das zusammenhängen könnte?

Das Codeguard log (Ich bin die Deutsch Version, Übersetzungen mit Sternen markiert):

------------------------------------------ 
Fehler 00080. 0x104230 (r) (Thread 0x07A4): 
Zeigerarithmetik in freigegebenem Speicher: 0x0241A238-0x0241A258. **(pointer arithmetic in freed region)** 
| d:\program files\borland\bds\4.0\include\dinkumware\sstream Zeile 126: 
|    { // not first growth, adjust pointers 
|    _Seekhigh = _Seekhigh - _Mysb::eback() + _Ptr; 
|>    _Mysb::setp(_Mysb::pbase() - _Mysb::eback() + _Ptr, 
|     _Mysb::pptr() - _Mysb::eback() + _Ptr, _Ptr + _Newsize); 
|    if (_Mystate & _Noread) 
Aufrufhierarchie: **(stack-trace)** 
    0x00411731(=FOSChampion.exe:0x01:010731) d:\program files\borland\bds\4.0\include\dinkumware\sstream#126 
    0x00411183(=FOSChampion.exe:0x01:010183) d:\program files\borland\bds\4.0\include\dinkumware\streambuf#465 
    0x0040933D(=FOSChampion.exe:0x01:00833D) d:\program files\borland\bds\4.0\include\dinkumware\streambuf#151 
    0x00405988(=FOSChampion.exe:0x01:004988) d:\program files\borland\bds\4.0\include\dinkumware\ostream#679 
    0x00405759(=FOSChampion.exe:0x01:004759) D:\Projekte\Schule\foschamp\src\Server\Ansistringkonverter.h#31 
    0x004080C9(=FOSChampion.exe:0x01:0070C9) D:\Projekte\Schule\foschamp\lib\boost_1_34_1\boost/lexical_cast.hpp#151 

Objekt (0x0241A238) [Größe: 32 Byte] war erstellt mit new **(Object was created with new)** 
| d:\program files\borland\bds\4.0\include\dinkumware\xmemory Zeile 28: 
| _Ty _FARQ *_Allocate(_SIZT _Count, _Ty _FARQ *) 
| { // allocate storage for _Count elements of type _Ty 
|> return ((_Ty _FARQ *)::operator new(_Count * sizeof (_Ty))); 
| } 
| 
Aufrufhierarchie: **(stack-trace)** 
    0x0040ED90(=FOSChampion.exe:0x01:00DD90) d:\program files\borland\bds\4.0\include\dinkumware\xmemory#28 
    0x0040E194(=FOSChampion.exe:0x01:00D194) d:\program files\borland\bds\4.0\include\dinkumware\xmemory#143 
    0x004115CF(=FOSChampion.exe:0x01:0105CF) d:\program files\borland\bds\4.0\include\dinkumware\sstream#105 
    0x00411183(=FOSChampion.exe:0x01:010183) d:\program files\borland\bds\4.0\include\dinkumware\streambuf#465 
    0x0040933D(=FOSChampion.exe:0x01:00833D) d:\program files\borland\bds\4.0\include\dinkumware\streambuf#151 
    0x00405988(=FOSChampion.exe:0x01:004988) d:\program files\borland\bds\4.0\include\dinkumware\ostream#679 

Objekt (0x0241A238) war Gelöscht mit delete **(Object was deleted with delete)** 
| d:\program files\borland\bds\4.0\include\dinkumware\xmemory Zeile 138: 
| void deallocate(pointer _Ptr, size_type) 
|  { // deallocate object at _Ptr, ignore size 
|>  ::operator delete(_Ptr); 
|  } 
| 
Aufrufhierarchie: **(stack-trace)** 
    0x004044C6(=FOSChampion.exe:0x01:0034C6) d:\program files\borland\bds\4.0\include\dinkumware\xmemory#138 
    0x00411628(=FOSChampion.exe:0x01:010628) d:\program files\borland\bds\4.0\include\dinkumware\sstream#111 
    0x00411183(=FOSChampion.exe:0x01:010183) d:\program files\borland\bds\4.0\include\dinkumware\streambuf#465 
    0x0040933D(=FOSChampion.exe:0x01:00833D) d:\program files\borland\bds\4.0\include\dinkumware\streambuf#151 
    0x00405988(=FOSChampion.exe:0x01:004988) d:\program files\borland\bds\4.0\include\dinkumware\ostream#679 
    0x00405759(=FOSChampion.exe:0x01:004759) D:\Projekte\Schule\foschamp\src\Server\Ansistringkonverter.h#31 

------------------------------------------ 

Ansistringkonverter.h wird die Datei mit den gebuchten Betreiber und Linie 31:

std::ostream& operator<<(std::ostream& ostr,const AnsiString& str) { 
    ostr << (str.c_str()); **(31)** 
    return ostr; 
} 

Danke für Ihre Hilfe :)

+0

wahrscheinlich ein Tippfehler, aber die & in std :: ostream & operator << – Jem

+0

fixiert dank Jem nicht vergessen. :) – leen

+0

Gemäß http://www.cppreference.com/wiki/io/exceptions wird der Fehler ignoriert, wenn ich den Aufruf .exceptions() weglasse. Also, wenn ich sofort mit dem Ergebnis gearbeitet habe, ohne dass es dazu gekommen ist, hat das zu Zugriffsverletzungen geführt. Das war zumindest meine Erklärung bisher. – leen

Antwort

0

Ihre Konvertierung konvertiert eine Zeile des Eingangs. Das ist ein ernsthaftes Problem, wenn es zwei Zeilen gibt, und einen ziemlich fatalen Fehler, wenn es keine gibt. Die beste Lösung ist in diesem Fall keine neue operator>>, sondern eine Template-Spezialisierung. Spitze von meinem Kopf:

template< > AnsiString lexical_cast<AnsiString, std::string>(std::string const& s) 
{ 
    return AnsiString(s.c_str()); 
} 

(Sie sind nicht Vorlagen Überlastung andere Völker sollten in std ::, es ist illegal, die sonst nur schlechte Praxis.)

+0

@James: Natürlich können Sie Vorlagenfunktionen spezialisieren - nur eine teilweise Spezialisierung ist für sie nicht möglich. –

1

Noch nicht boost, können aber sei ein erster Schritt, um dein aktuelles Problem zu lösen.Sie können dies versuchen:

std::istream& operator>>(std::istream& istr, AnsiString& str) { 
    istr.exceptions(std::ios::badbit | std::ios::failbit | std::ios::eofbit); 
    std::string s; 
    istr >> s; 
    str = AnsiString(s.c_str()); 
    return istr; 
} 

EDIT: vollständigere Lösung, op Kommentare berücksichtigt:

std::istream& operator>> (std::istream& istr, AnsiString& str) 
{ 
    std::string tmp; 

    std::istreambuf_iterator<char> it(istr), end; 
    std::copy(it, end, std::inserter(tmp, tmp.begin())); 

    str = AnsiString(tmp.c_str()); 

    return istr; 
} 

jedoch für verschiedene Betreiber >> Verhalten mit std :: string und Ansistring ist wahrscheinlich ok für Ihre Bedürfnisse, aber im Allgemeinen nicht sehr nett. Sie können ihm immer noch einen eindeutigen Namen geben.

+0

Ich denke, das wird nur ein einziges Wort kopieren –

+0

Ja, aber es kann das erwartete Verhalten sein (oder nicht). Das Lesen des gesamten Puffers könnte auf einer höheren Ebene erfolgen. Ich weiß nicht Streams auswendig, aber es ist wahrscheinlich möglich, hier sogar die temporäre Zeichenfolge zu vermeiden, indem ich stream.get() – Jem

+0

Ich habe vor einiger Zeit von >> zu getline() geschaltet, weil ich das gesamte lesen möchte Zeichenfolge. Also das Lesen der ganzen Zeichenfolge ist was ich will :) – leen

0

Neben MSalters Kommentare, wäre es effizienter sein, die std :: string tatsächliche Länge zu passieren und zu Ansistring, so dass es keine Abfälle CPU-Zyklen zur Berechnung der Länge manuell benötigt:

template<> System::AnsiString lexical_cast<System::AnsiString, std::string>(std::string const& s) 
{ 
    return System::AnsiString(s.c_str(), s.length()); 
} 
0

Sie können dies auch versuchen! Ich hatte auch dieses Problem mit hashlib ++.

String toAnsiString(const std::string& myString) 
{ 
    return String(myString.c_str()); 
} 
Verwandte Themen