конвертация строк
|
|
sashasold | Дата: Среда, 24.11.2021, 12:48 | Сообщение # 1 |
Лейтенант
Группа: Пользователи
Сообщений: 41
Статус: Offline
| Здравия всем! Вопрос такой: как преобразовать строку из DOS(OEM) в Unicode WString может библиотека какая есть? в WinAPI видел подобную функцию, но там меж ANSI и Unicode Желательно что бы можно было конвертировать все 3 кодировки меж собой и инвариантно (DOS, ANSI, Unicode) а то эта тема надоела, мелочь, а не приятно =D
|
|
| |
haav | Дата: Среда, 24.11.2021, 15:24 | Сообщение # 2 |
Генералиссимус
Группа: Администраторы
Сообщений: 1366
Статус: Offline
| Код #Include "windows.bi"
function encode(pIn as any ptr , sOptions as string) as any ptr Dim As DWORD dwNum select case sOptions Case "ua" dwNum = WideCharToMultiByte(CP_ACP , 0 , pIn , -1 , NULL , 0 , NULL , NULL) Dim As zstring ptr pSZ = Callocate(dwNum+1) WideCharToMultiByte(CP_ACP , 0 , pIn , -1 , pSZ , dwNum , NULL , NULL) return pSZ case "uo" dwNum = WideCharToMultiByte(866 , 0 , pIn , -1 , NULL , 0 , NULL , NULL) Dim As zstring ptr pSZ = Callocate(dwNum+1) WideCharToMultiByte(866 , 0 , pIn , -1 , pSZ , dwNum , NULL , NULL) return pSZ case "au" dwNum = MultiByteToWideChar(CP_ACP , 0 , pIn , -1 , NULL , 0) Dim As WString Ptr pSZ = CAllocate(dwNum*2+2) MultiByteToWideChar(CP_ACP , 0 , pIn , -1, pSZ , dwNum) return pSZ case "ou" dwNum = MultiByteToWideChar(866 , 0 , pIn , -1 , NULL , 0) Dim As WString Ptr pSZ = CAllocate(dwNum*2+2) MultiByteToWideChar(866 , 0 , pIn , -1, pSZ , dwNum) return pSZ case "ao" Dim As zstring ptr pSZ = Callocate(len(*cast(zstring ptr, pIn))+1) CharToOem(pIn , pSZ) return pSZ case "oa" Dim As zstring ptr pSZ = Callocate(len(*cast(zstring ptr, pIn))+1) OemToChar(pIn , pSZ) return pSZ End Select End Function
' --------------- TEST -----------------
?
dim as string s = "БЛА..БЛА"
? "Initial text ascii:" , s ? ' ascii to oem dim as zstring ptr pOEM = encode(strptr(s) , "ao")
? "ascii to oem:" , *pOEM
' oem to ascii dim as zstring ptr pASCII = encode(pOEM , "oa")
? "oem to ascii:" , *pASCII
' oem to unicode dim as wstring ptr pUNICODE = encode(pOEM , "ou")
? "oem to unicode:" , *pUNICODE
deallocate(pOEM)
deallocate(pASCII)
deallocate(pUNICODE)
' ascii to unicode pUNICODE = encode(strptr(s) , "au")
? "ascii to unicode:" , *pUNICODE
' unicode to ascii pASCII = encode(pUNICODE , "ua")
? "unicode to ascii:" , *pASCII
deallocate(pASCII)
' unicode to oem pOEM = encode(pUNICODE , "uo")
? "unicode to oem:" , *pOEM
deallocate(pOEM)
deallocate(pUNICODE)
sleep
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
sashasold | Дата: Пятница, 26.11.2021, 01:29 | Сообщение # 3 |
Лейтенант
Группа: Пользователи
Сообщений: 41
Статус: Offline
| Спасибо, Станислав! это у тебя была функция такая, или для меня набрал по быстрому?) кстати на 32битном компиляторе вылетает
64 работает
|
|
| |
haav | Дата: Пятница, 26.11.2021, 07:38 | Сообщение # 4 |
Генералиссимус
Группа: Администраторы
Сообщений: 1366
Статус: Offline
| Цитата sashasold ( ) это у тебя была функция такая, или для меня набрал по быстрому?)
Была похожая , чуть подправил
Цитата кстати на 32битном компиляторе вылетает
Ну конечно вылетает , я раздолбай Забыл звездочки поставить. Пример исправил.
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
sashasold | Дата: Пятница, 26.11.2021, 13:18 | Сообщение # 5 |
Лейтенант
Группа: Пользователи
Сообщений: 41
Статус: Offline
| Спасибо! )) Переформатировал под себя, может кому удобнее такой вариант будет Код #Include "Windows.bi"
Function Perecodirovka(pIn As Any Ptr, kodirovka As String) As Any Ptr Dim As DWORD dwNum Select Case kodirovka Case "Unicode_A" dwNum = WideCharToMultiByte(CP_ACP, 0, pIn, -1, NULL, 0, NULL, NULL) Dim As ZString Ptr pSZ = Callocate(dwNum+1) WideCharToMultiByte(CP_ACP, 0, pIn, -1, pSZ, dwNum, NULL, NULL) Return pSZ Case "Unicode_OEM" dwNum = WideCharToMultiByte(866, 0, pIn, -1, NULL, 0, NULL, NULL) Dim As ZString Ptr pSZ = Callocate(dwNum+1) WideCharToMultiByte(866, 0, pIn, -1, pSZ, dwNum, NULL, NULL) Return pSZ Case "A_Unicode" dwNum = MultiByteToWideChar(CP_ACP, 0, pIn, -1, NULL, 0) Dim As WString Ptr pSZ = Callocate(dwNum*2+2) MultiByteToWideChar(CP_ACP, 0, pIn, -1, pSZ, dwNum) Return pSZ Case "OEM_Unicode" dwNum = MultiByteToWideChar(866, 0, pIn, -1, NULL, 0) Dim As WString Ptr pSZ = Callocate(dwNum*2+2) MultiByteToWideChar(866, 0, pIn, -1, pSZ, dwNum) Return pSZ Case "A_OEM" Dim As ZString Ptr pSZ = Callocate(Len(*Cast(ZString Ptr, pIn))+1) CharToOem(pIn, pSZ) Return pSZ Case "OEM_A" Dim As ZString Ptr pSZ = Callocate(Len(*Cast(ZString Ptr, pIn))+1) OemToChar(pIn, pSZ) Return pSZ End Select End Function
'--- Dim As String s = "БЛА...бла_123"
Print "Initial text ascii:", s Print
'A_OEM Dim As ZString Ptr pOEM = Perecodirovka(StrPtr(s), "A_OEM") Print "ascii to oem:", *pOEM
'OEM_A Dim As ZString Ptr pASCII = Perecodirovka(pOEM, "OEM_A") Print "oem to ascii:", *pASCII
'OEM_Unicode Dim As WString Ptr pUNICODE = Perecodirovka(pOEM, "OEM_Unicode") Print "oem to unicode:", *pUNICODE
DeAllocate(pOEM) DeAllocate(pASCII) DeAllocate(pUNICODE)
'A_Unicode pUNICODE = Perecodirovka(StrPtr(s), "A_Unicode") '@ - адрес дескриптора, а не данных, строки Print "ascii to unicode:", *pUNICODE
'Unicode_A pASCII = Perecodirovka(pUNICODE, "Unicode_A") Print "unicode to ascii:", *pASCII
'Unicode_OEM pOEM = Perecodirovka(pUNICODE, "Unicode_OEM") Print "unicode to oem:", *pOEM
DeAllocate(pOEM) DeAllocate(pASCII) DeAllocate(pUNICODE)
Sleep
Сообщение отредактировал sashasold - Пятница, 26.11.2021, 13:19 |
|
| |
electrik | Дата: Понедельник, 10.01.2022, 01:50 | Сообщение # 6 |
Полковник
Группа: Друзья
Сообщений: 182
Статус: Offline
| Привет. Я видел в Window9 класс для работы со строками extwstring. Почему для перекодировки используются виндовые функции, ведь есть utfconf.bi? Эти функции вроде от самих создателей юникода, или они кривые? Просто я уже сталкивался с проблемой при использовании виндовых функций в синтезаторе речи. Я перегонял с юникода в cp866, и на английской винде у людей синтезатор не говорил по-русски. Там есть какое-то шаманство, запрятанное в дебрях винды. короче, я написал свою. Теперь проблем нет. Есть ли в планах у создателей FreeBasic всё же делать нормальную поддержку юникода? Бывают случаи, когда одна библиотека работает в utf16, а Lua лучше строки слать в UTF8. Вот тут то и начинаются шаманства. Если сохранять исходник в UTF8, значит подразумевается юзать char *, по аналогии FreeBasic - это zstring ptr. Если это UTF8 с BOM, он начинает ругаться на типы. приводить типы - ну тоже такое. Вобщем, всё не однозначно. Зачем хранить исходник в utf8? В луа есть удобные функции регистрации lua функций, и проще запилить таблицу при инициализации массива и её передавать в lua. В пурике мы делали массив, аллоцировали нужную память, передавали в lua а потом очищали. Но это костыли великие! функции в utfconf.bi, действительно не для новичков, но думаю это можно поправить. В общем какие есть мысли. Можно заюзать libiconv, но это громоздко и таскание библиотек - не штырно.
|
|
| |
haav | Дата: Понедельник, 10.01.2022, 08:37 | Сообщение # 7 |
Генералиссимус
Группа: Администраторы
Сообщений: 1366
Статус: Offline
| На винде для перекодировки я не знаю инструментов лучше чем WideCharToMultiByte | MultiByteToWideChar. libiconv - хорошая библиотека , но на винде она не сравнится с WideCharToMultiByte | MultiByteToWideChar. Хотя , если дело касается кроссплатформы , то очевидно libiconv будет предпочтительнее. libiconv плохо обрабатывает ошибочные данные. То есть встретив ошибку в тексте , она сразу возвращает ошибку. В свою очередь WideCharToMultiByte | MultiByteToWideChar будет конвертировать текст до самого конца , пропуская ошибки или пытаясь преобразовать данные. Насчет скорости их работы не знаю , скорее всего обе конвертируют по таблицам, поскольку ручной метод перекодировки всегда проигрывает. Для Linux в window9 я использую ручной метод (там по сути только UTF8<->UTF32), поскольку не захотел привязывать библиотеку к libiconv. Ручной метод имеет свои плюсы , поскольку можно контролировать проблемы с ошибочным текстом. Я как то писал для себя ручной метод для перекодировки UTF8 , UTF16 , UTF32 , KOI8-R , CP866 , CP1251 , и решил что буду использовать его в проектах , где скорость не критична.
Насчет utfconf.bi. Я попробовал это чудо , когда создавал редактор , но мне показалось , что это вообще нормально не работает. Скорее всего , это что-то вроде wcstombs , mbstowcs.
Цитата Просто я уже сталкивался с проблемой при использовании виндовых функций в синтезаторе речи. Я перегонял с юникода в cp866, и на английской винде у людей синтезатор не говорил по-русски.
А зачем вообще привязываться к ASCII , если проект международный?
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
zamabuvaraeu | Дата: Понедельник, 10.01.2022, 17:06 | Сообщение # 8 |
Подполковник
Группа: Друзья
Сообщений: 149
Статус: Offline
| Я не очень хорошо понимаю, зачем в 21 веке, когда везде работает юникод, нужна возня с 866, 1251. Для вывода на консоль? Но консоль прекрасно работает с юникодом (см. функции WriteConsoleW и ReadConsoleW). Ну разве что когда стандартные потоки ввода‐вывода перенаправлены, но и тогда не нужно полагаться что обязательно будет кодировка 1251 или 866, кодировку следует выяснять через GetConsoleC и GetConsoleOutputCP, самостоятельная установка кодировки — это вообще категории образцовых примеров как не надо делать.
Я раньше все исходники хранил в UTF-16. В старом блокноте эта кодировка загадочно называется «Юникод». И это даже работает в FBEdit. Все строковые литералы становятся юникодными, это лечится через Str("литерал"). Но главная проблема исходников в UTF-16, что система контроля версий такой файл считает бинарным и не отображает его историю изменений на гитхабе. Я перекатил все исходники обратно на ASCII. Строковые литералы теперь всегда обрамляю либо в Str("строка"), либо в WStr("строка"). Если в строке встречаются символы, которые не входят в младшую половину ASCII, то это значит, что такие строки требуют локализации, я всегда выношу их в ресурсы программы. Ну а с ресурсами проблем нет, потому что ресурсы всегда хранятся в юникоде.Добавлено (10.01.2022, 17:11) --------------------------------------------- Ну и всегда использую обобщённые типы вроде TCHAR и PTSTR для символов и строк.
|
|
| |
electrik | Дата: Понедельник, 10.01.2022, 20:11 | Сообщение # 9 |
Полковник
Группа: Друзья
Сообщений: 182
Статус: Offline
| Да я с удовольствием бы использовал юникод. Дело в том, что синтезатор старый, и написан на asme, и привязан к 866. Новая версия, которая написана на C и опубликована недавно на гитхабе, привязана к koi8. хотя если посмотреть, внутреннее представление подобных программ может быть любым, ибо парсить внутри синта UTF8 удовольствие не для слабонервных. Гораздо удобней юзать кодировки которые чему-то кратны. Тем более, этот синтезатор русский. Мы конечно при помощи обвесок заставляем его говорить и по-грузински, но это всё на основе русских фонем. Я конечно в данную секунду не бегу за кросс-платформенностью, но всё же хочется сделать запил, для возможного будущего, а может и не возможного. Перекодировку кратных кодировок, думаю напишет пятилетний, меня больше интересует в UTF8 и из неё. Я видел исходник написанный юникодовцами в 2004 году, куски которого находятся в utfconv, но не уверен как оно работает, поэтому тут и спросил. Если сможешь показать реально рабочий ручной вариант, можно будет подумать о таблицах или о оптимизациях. Как я понимаю, вариант из utf16 в utf8 будет любой язык, и обратно, а в cp1251 - только кириллица, ибо все языки невозможно засунуть в один байт. Или у тебя только везде кирилица?
Сообщение отредактировал electrik - Понедельник, 10.01.2022, 20:24 |
|
| |
haav | Дата: Понедельник, 10.01.2022, 21:48 | Сообщение # 10 |
Генералиссимус
Группа: Администраторы
Сообщений: 1366
Статус: Offline
| Цитата electrik ( ) Если сможешь показать реально рабочий ручной вариант, можно будет подумать о таблицах или о оптимизациях.
Код Function EncodeUTF8ToUnicode(sTextUtf8 as string) as Wstring ptr Dim as Long iIndex dim as SHORT shUnicodeSymbol dim as wstring ptr ws = allocate(len(sTextUtf8)*sizeof(wstring)+1) for i as Long = 0 to len(sTextUtf8) -1 if (sTextUtf8[i] and &hF0) = &hE0 andalso (sTextUtf8[i+1] and &hC0) = &h80 andalso (sTextUtf8[i+2] and &hC0) = &h80 then ' 3 shUnicodeSymbol = ((sTextUtf8[i] and &hF) shl 12) or (((sTextUtf8[i+1] and &h3F) shl 6) or (sTextUtf8[i+2] and &h3F)) i+=2 elseif (sTextUtf8[i] and &hC0) = &hC0 andalso (sTextUtf8[i+1] and &hC0) = &h80 then ' 2 shUnicodeSymbol = ((sTextUtf8[i] and &h1F) shl 6) or ((sTextUtf8[i+1] and &h3F)) i+=1 elseif (sTextUtf8[i] and &h80) = &h0 then ' 1 ' если нужно кодировать строку, содержащую нули в середине строки, но вырезать эти нули , то раскомментировать код ниже ' если оставить как есть, то первый попавшийся ноль станет концом строки 'if s[i] = 0 then continue for shUnicodeSymbol = sTextUtf8[i] else ' суррагаты и прочую фигню заменяем рекомендуемым знаком вопроса shUnicodeSymbol = &hFFFD EndIf (*ws)[iIndex] = shUnicodeSymbol iIndex+=1 Next (*ws)[iIndex] = 0 return ws End Function
Function EncodeUnicodeToUTF8(wsText as wstring ptr ) as string Dim as Long iSimbol dim as string sRet For i as long = 0 to len(*wsText)-1 iSimbol = wsText[i] If iSimbol < &h80 Then sRet &= chr(iSimbol) ElseIf iSimbol < &h800 Then sRet &= chr(&hC0 or (iSimbol shr 6)) & chr(&h80 or (iSimbol and &h3f)) ElseIf iSimbol < &h10000 Andalso (iSimbol < &hD800 Orelse iSimbol > &hDFFF) Then sRet &= chr((&he0 or (&hF and (iSimbol shr 12)))) & chr(&h80 or (&h3f and (iSimbol shr 6))) & chr(&h80 or (iSimbol and &h3F)) Else 'нафиг суррогаты , заменим рекомендуемым знаком вопроса sRet &= Chr(&hEF) & Chr(&hBF) & Chr(&hBD) End If Next return sRet End Function
dim shared as Short ku(&hC0 to &hFF) = {&h44E , &h430 , &h431 , &h446 , &h434 , &h435 , &h444 , &h433 ,_ &h445 , &h438 , &h439 , &h43A , &h43B , &h43C , &h43D , &h43E , &h43F , &h44F , &h440 , &h441 , &h442 ,_ &h443 , &h436 , &h432 , &h44C , &h44B , &h437 , &h448 , &h44D , &h449 , &h447 , &h44A , &h42E , &h410 ,_ &h411 , &h426 , &h414 , &h415 , &h424 , &h413 , &h425 , &h418 , &h419 , &h41A , &h41B , &h41C , &h41D ,_ &h41E , &h41F , &h42F , &h420 , &h421 , &h422 , &h423 , &h416 , &h412 , &h42C , &h42B , &h417 , &h428 ,_ &h42D , &h429 , &h427 , &h42A}
dim shared as Short uk(&h410 to &h44F) = {&hE1 , &hE2 , &hF7 , &hE7 , &hE4 , &hE5 , &hF6 , &hFA , &hE9 ,_ &hEA , &hEB , &hEC , &hED , &hEE , &hEF , &hF0 , &hF2 , &hF3 , &hF4 , &hF5 , &hE6 , &hE8 , &hE3 , &hFE ,_ &hFB , &hFD , &hFF , &hF9 , &hF8 , &hFC , &hE0 , &hF1 , &hC1 , &hC2 , &hD7 , &hC7 , &hC4 , &hC5 , &hD6 ,_ &hDA , &hC9 , &hCA , &hCB , &hCC , &hCD , &hCE , &hCF , &hD0 , &hD2 , &hD3 , &hD4 , &hD5 , &hC6 , &hC8 ,_ &hC3 , &hDE , &hDB , &hDD , &hDF , &hD9 , &hD8 , &hDC , &hC0 , &hD1}
function EncodeUnicodeToKOI8R(wsText as Wstring ptr) as string dim as Long iLen = len(*wsText) dim as string sText = space(iLen+1) for i as Long = 0 to iLen-1 select case (*wsText)[i] Case &h401 sText[i] = &hB3 case &h451 sText[i] = &hA3 case &h410 to &h44F sText[i] = uk((*wsText)[i]) case is < 128 sText[i] = (*wsText)[i]
End Select Next sText[iLen] = 0 return sText End Function
function EncodeKOI8RToUnicode(sText as string) as Wstring ptr dim as Long iLen = len(sText) dim as wstring ptr ws = allocate(iLen*sizeof(wstring)+1) for i as Long = 0 to iLen-1 select case (sText)[i] Case &hB3 (*ws)[i] = &h401 case &hA3 (*ws)[i] = &h451 case &hC0 to &hFF (*ws)[i] = ku((sText)[i]) case is < 128 (*ws)[i] = (sText)[i]
End Select Next (*ws)[iLen] = 0 return ws End Function
function EncodeUnicodeToCp1251(wsText as Wstring ptr) as string dim as Long iLen = len(*wsText) dim as string sText = space(iLen+1) for i as Long = 0 to iLen-1 select case (*wsText)[i] Case &h401 sText[i]= &hA8 case &h451 sText[i]= &hB8 case &h410 to &h44F sText[i]= ((*wsText)[i]) - &h350 case is < 128 sText[i]=(*wsText)[i] End Select Next sText[iLen] = 0 return sText End Function
Function Encode1251ToUnicode(sText1251 as string) as Wstring ptr dim as Long iLen = len(sText1251) dim as wstring ptr ws = allocate(len(sText1251)*sizeof(wstring)+1) for i as Long = 0 to iLen-1 select case (sText1251)[i] Case &hA8 (*ws)[i]= &h401 case &hB8 (*ws)[i]= &h451 case &hC0 to &hFF (*ws)[i]= ((sText1251)[i]) + &h350 case is < 128 (*ws)[i]=(sText1251)[i] End Select Next (*ws)[iLen] = 0 return ws End Function
function EncodeUnicodeToCp866(wsText as Wstring ptr) as string dim as Long iLen = len(*wsText) dim as string sText = space(iLen+1) for i as Long = 0 to iLen-1 select case (*wsText)[i] Case &h401 sText[i]= &hf0 case &h451 sText[i]= &hf1 case &h410 to &h43F sText[i]= ((*wsText)[i]) - &h390 case &h440 to &h44F sText[i]= ((*wsText)[i]) - &h360 case is < 128 sText[i]=(*wsText)[i] End Select Next sText[iLen] = 0 return sText End Function
Function Encode866ToUnicode(sText866 as string) as Wstring ptr dim as Long iLen = len(sText866) dim as wstring ptr ws = allocate(len(sText866)*sizeof(wstring)+1) for i as Long = 0 to iLen-1 select case (sText866)[i] Case &hf0 (*ws)[i]= &h401 case &hf1 (*ws)[i]= &h451 case &h80 to &hAF (*ws)[i] = ((sText866)[i]) + &h390 case &hE0 to &hEF (*ws)[i] = ((sText866)[i]) + &h360 case is < 128 (*ws)[i]=(sText866)[i] End Select Next (*ws)[iLen] = 0 return ws End Function
function Encode866ToCp1251(sText866 as string) as string dim as Long iLen = len(sText866) dim as string sText1251 = space(iLen+1) for i as Long = 0 to iLen-1 select case (sText866)[i] Case &h80 to &hAF sText1251[i] = sText866[i]+ &h40 case &hE0 to &hEF sText1251[i]= sText866[i]+ &h10 case &hF0 sText1251[i]= &hA8 case &hF1 sText1251[i]= &hB8 case is < 128 sText1251[i]=sText866[i] End Select Next sText1251[iLen] = 0 return sText1251 End Function
function Encode1251ToCp866(sText1251 as string) as string dim as Long iLen = len(sText1251) dim as string sText866 = space(iLen+1) for i as Long = 0 to iLen-1 select case (sText1251)[i] Case &hC0 to &hEF sText866[i] = sText1251[i] - &h40 case &hF0 to &hFF sText866[i]= sText1251[i] - &h10 case &hA8 sText866[i]= &hF0 case &hB8 sText866[i]= &hF1 case is < 128 sText866[i]=sText1251[i] End Select Next sText866[iLen] = 0 return sText866 End Function
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
electrik | Дата: Понедельник, 10.01.2022, 23:36 | Сообщение # 11 |
Полковник
Группа: Друзья
Сообщений: 182
Статус: Offline
| За функции Приогромнейшее спасибо! будем изучать.
|
|
| |
WQ | Дата: Среда, 12.01.2022, 23:27 | Сообщение # 12 |
Полковник
Группа: Проверенные
Сообщений: 215
Статус: Offline
| У меня сложилось мнение, что функцию Chr можно заменить вызовом из заранее созданного массива, будет быстрее
|
|
| |
zamabuvaraeu | Дата: Четверг, 13.01.2022, 10:58 | Сообщение # 13 |
Подполковник
Группа: Друзья
Сообщений: 149
Статус: Offline
| Я всегда строку рассматриваю как массив символов с индексацией в виде квадратным скобок, и мне кажутся довольно странными такие функции как Chr и Asc.
Добавлено (13.01.2022, 11:01) --------------------------------------------- Например:
Код Dim s As WString Ptr = каким‐либо образом получаем строку
' Устанавливаем первым символом пробел s[0] = 32
' Получаем первый символ в строке Dim firstChar As Integer = s[0]
Строки типа String не использую, у них много недостатков.
Сообщение отредактировал zamabuvaraeu - Четверг, 13.01.2022, 11:02 |
|
| |
haav | Дата: Воскресенье, 23.01.2022, 12:12 | Сообщение # 14 |
Генералиссимус
Группа: Администраторы
Сообщений: 1366
Статус: Offline
| Цитата zamabuvaraeu ( ) Строки типа String не использую, у них много недостатков. Ну какие-то недостатки есть , как минимум нежелательно их использовать в сложно-составных структурах. Я уже обжигался. Но в простых структурах использовал и проблем не было. Возможно даже что это уже давно пофиксено и сейчас уже этого недостатка нет. Просто после того случая , когда полезли баги в программе , я теперь использую в структурах только zstring*n , wstring*n , zstring ptr , wstring ptr. Работая с UTF-8 , есть общий недостаток для zstring , string: бесполезность строковых функций mid , left , ucase и пр. для не латинских символов. Выйти из положения можно преобразованием текста в unicode и обратно.
Я перечислю достоинства:
1) избавляет от необходимости заботиться о выделении\освобождении памяти и не трахать мозги по этому поводу 2) безопасны , если конечно не использовать прямой доступ к памяти 3) быстрое получение длины строки (размер попросту лежит в структуре), в отличии от zstring , wstring , где длину надо всегда высчитывать
Я приведу пример со своим редактором. Там где использовался тип string , серьезных багов никогда не было. А вот при использовании zstring , wstring , массивов было с десяток багов , которые иногда приходилось ловить часами или даже днями. И тут отладчик бессилен , поскольку ошибка (креш) происходила там, где ее по определению быть не должно. Так что , если обильно работаешь с текстом , то безопасные динамические строки - это залог того , что меньше будешь париться с ошибками. Да где-то с потерей производительности , но узкие места всегда можно потом оптимизировать.
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
zamabuvaraeu | Дата: Понедельник, 24.01.2022, 13:00 | Сообщение # 15 |
Подполковник
Группа: Друзья
Сообщений: 149
Статус: Offline
| Для моей задачи Я сделал собственный класс строк.
Строка устроена по принципу BSTR: длина + данные + нулевой символ. Строка совместима с WinAPI и КОМ без всяких конвертаций.
Длину строки не нужно вычислять, она хранится.
Строка неизменяемая, значит, нельзя испортить данные «для другого потребителя».
Так как строка неизменяемая, то у моей строки есть счётчик ссылок, это значит, что данные не нужно копировать при присваивании, достаточно лишь инкрементировать счётчик.
Используя правило подсчёта ссылок, потребитель уменьшает счётчик когда объект больше не нужен. Экземпляр строки самоуничтожится тут же, без промедления, когда на него больше нет ссылок.
Строка хранит ссылку на аллокатор памяти, значит, строка может быть создана в отдельной куче памяти без синхронизации доступа к основной куче.
Потребителю строки не нужно думать каким образом была создана строка, чтобы правильно её уничтожить. Аллокатор памяти сам знает каким образом память была создана, и умеет уничтожать такую память. Поэтому строка может быть создана «на массиве» или вообще не в куче, а в разделяемой между процессами памяти.
|
|
| |
|