Преобразование C++Builder AnsiString в std::string с помощью boost::lexical_cast
Для школьного задания я должен реализовать проект на C++, используя Borland C++ Builder.
Поскольку VCL использует AnsiString для всех компонентов GUI, я должен преобразовать все мои std:: strings в AnsiString для отображения.
std::string inp = "Hello world!";
AnsiString outp(inp.c_str());
работает конечно, но это немного утомительно для написания и дублирования кода, которого я хочу избежать. Поскольку мы используем Boost в других контекстах, я решил предоставить некоторые вспомогательные функции, чтобы получить boost::lexical_cast для работы с AnsiString. Вот моя реализация до сих пор:
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;
}
Вначале я получил Access Violation после Access Violation, но с тех пор, как я добавил материал.exceptions(), картина проясняется. Когда преобразование выполнено, я получаю следующее исключение:
ios_base::eofbit set [Runtime Error/std::ios_base::failure]
У кого-нибудь есть идеи как это исправить и можно объяснить, почему происходит ошибка? Мой опыт C++ очень ограничен.
Процедура преобразования наоборот:
std::ostream& operator<<(std::ostream& ostr,const AnsiString& str) {
ostr << (str.c_str());
return ostr;
}
Может быть, кто-то также обнаружит ошибку здесь:)
С наилучшими пожеланиями!
Редактировать:
На данный момент я использую отредактированную версию Jem, она работает в начале. Через некоторое время использования программы Borland Codeguard упоминает некоторую арифметику указателей в уже освобожденных регионах. Есть идеи, как это может быть связано?
Журнал Codeguard (я использую немецкую версию, переводы отмечены звездочками):
------------------------------------------
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 - это файл с опубликованными операторами, а строка 31:
std::ostream& operator<<(std::ostream& ostr,const AnsiString& str) {
ostr << (str.c_str()); **(31)**
return ostr;
}
Спасибо за вашу помощь:)
4 ответа
По-прежнему не используется повышение, но может стать первым шагом к решению вашей текущей проблемы. Вы можете попробовать это:
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;
}
РЕДАКТИРОВАТЬ: более полное решение, принимая во внимание комментарии оп:
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;
}
Тем не менее, иметь другое поведение оператора >> для std:: string и AnsiString, вероятно, хорошо для ваших нужд, но в целом не очень хорошо. Вы все еще можете дать ему явное имя.
Вы также можете попробовать это! У меня была такая проблема при работе с hashlib++.
String toAnsiString(const std::string& myString)
{
return String(myString.c_str());
}
Ваше преобразование преобразует одну строку ввода. Это серьезная проблема, если есть две строки, и довольно фатальная ошибка, если их нет. Лучшее решение в этом случае не новое operator>>
, но специализация шаблона. Верх моей головы:
template< > AnsiString lexical_cast<AnsiString, std::string>(std::string const& s)
{
return AnsiString(s.c_str());
}
(Вы не должны перегружать шаблоны других людей. В std:: это запрещено, в других местах просто плохая практика)
В дополнение к комментариям MSalters было бы более эффективно передать фактическую длину std::string в AnsiString, чтобы не требовалось тратить циклы ЦП для вычисления длины вручную:
template<> System::AnsiString lexical_cast<System::AnsiString, std::string>(std::string const& s)
{
return System::AnsiString(s.c_str(), s.length());
}