2009-05-22 13 views
2

Pour une tâche scolaire, je dois implémenter un projet en C++ en utilisant Borland C++ Builder. Comme la VCL utilise AnsiString pour tous les composants de l'interface graphique, je dois convertir toutes mes chaînes std :: AnsiString pour l'affichage.Convertir C++ Builder AnsiString en std :: string via boost :: lexical_cast

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

fonctionne bien sûr mais est un peu fastidieux pour écrire et coder la duplication que je veux éviter. Comme nous utilisons Boost dans d'autres contextes, j'ai décidé de fournir quelques fonctions d'assistance pour obtenir boost :: lexical_cast pour travailler avec AnsiString. Voici ma mise en œuvre jusqu'à présent:

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; 
} 

Au début, je suis violation d'accès après une violation d'accès, mais depuis que j'ajouté les .exceptions() farcir l'image se précise. Lorsque la conversion est effectuée, je reçois l'exception suivante:

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

Est-ce que quelqu'un a une idée comment le corriger et peut expliquer pourquoi l'erreur se produit? Mon expérience C++ est très limitée.

La routine de conversion dans l'autre sens arrondissent être:

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

Peut-être que quelqu'un va repérer une erreur ici aussi :)

Avec mes meilleures salutations!

Edit:

En ce moment je suis en utilisant la version éditée de Jem, il fonctionne au début. Après un certain temps d'utilisation du programme, Borland Codeguard mentionne une certaine arithmétique du pointeur dans les régions déjà libérées. Des idées comment cela pourrait être lié?

Le journal Codeguard (j'utilise la version allemande, les traductions marqués par étoiles):

------------------------------------------ 
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 est le fichier avec les opérateurs affichés et la ligne 31 est:

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

Merci pour votre aide :)

+0

Probablement une faute de frappe, mais ne pas oublier le & dans std :: ostream & operator << – Jem

+0

fixe, grâce Jem. :) – leen

+0

Selon http://www.cppreference.com/wiki/io/exceptions l'erreur est ignorée lorsque j'omets l'appel .exceptions(). Donc, quand j'ai travaillé immédiatement avec le résultat sans le faire, cela a entraîné des violations d'accès. C'était au moins mon explication jusqu'à présent. – leen

Répondre

0

Votre conversion convertit une ligne de l'entrée. C'est un problème sérieux s'il y a deux lignes, et un bug plutôt fatal s'il n'y en a pas. La meilleure solution dans ce cas n'est pas une nouvelle operator>>, mais une spécialisation de modèle. Haut de ma tête:

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

(Vous n'êtes pas censé surcharge autres des modèles de peuples Dans std ::, il est illégal, ailleurs que les mauvaises pratiques.)

+0

@James: Bien sûr, vous pouvez spécialiser les fonctions de modèle - seulement une spécialisation partielle n'est pas possible pour eux. –

1

encore ne pas utiliser boost, mais peut soyez un premier pas pour résoudre votre problème actuel.Vous pouvez essayer ceci:

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: solution plus complète, en prenant les commentaires op en compte:

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; 
} 

Cependant, ayant un comportement différent opérateur >> pour std :: string et AnsiString est probablement ok pour vos besoins, mais pas très bien en général. Vous pouvez toujours lui donner un nom explicite.

+0

Je pense que cela ne fera que copier un seul mot –

+0

Oui, mais ce peut être le comportement attendu (ou non). La lecture de tout le tampon pourrait être faite à un niveau supérieur. Je ne connais pas les flux par coeur, mais il est probablement possible ici même d'éviter la chaîne temporaire, en utilisant stream.get() – Jem

+0

Je suis passé de >> à getline() il y a quelque temps parce que je veux lire l'ensemble chaîne. Donc, la lecture de toute la chaîne est ce que je veux :) – leen

0

En plus des commentaires de MSalters, il serait plus efficace de passer la std longueur réelle de :: chaîne à AnsiString aussi bien, de sorte qu'il n'a pas besoin de cycles de CPU des déchets pour le calcul de la longueur manuellement:

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

Vous pouvez aussi essayer ça! J'ai aussi eu ce genre de problème avec hashlib ++.

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