строки из нутри и указатели

Предыдущая тема Следующая тема Перейти вниз

строки из нутри и указатели

Сообщение  Eric-S в Вс Окт 05, 2008 9:26 am

введение

В случае работы со строками, для указателей случай особый.
Дело в том, что строки ближе к массивам.
Но FreeBasic поддерживает 3 типа строк, которые очень различны. Давайте будем рассматривать всё по отдельности. А заодно изучим и то, как устроены строки.


zstring

ZString это самая простая строка. строка в стиле языка C.

zstring, представляет из себя массив бит (аски кодов), оканчивающихся нулевым кодом. Отсюда и название "zero string".

У этой строки нет дескрипторов.

Работая с внешними библиотеками вы обязательно столкнётесь с такими строками. Этот формат очень популярен и широко распространённ.

Символ представлен 8 битами. В строке разрешены любые символы от 1 до 255. Признаком конца строки считаеться код 0.

Объявлять строку надо так
Код:

dim zs1 as zstring * 20
zs1 = "Hello, world!"
После типа zstring мы указали ещё *20, означающее, что наша строка состоит из 20 символов. Нужно оставить символ для закрывающего нуля.
Такое объявление называеться статическим. Строка будет неизменной длины в памяти.

На статическую строку можно создать указатель
Код:

dim zs2 as zstring ptr
zs2 = @zs1
print *zs2

Короче, всё как обычно с указателями.



wstring

Стандартный тип строк, очень похожий на zstring. Но здесь коды могуд быть больше. Эти строки для рассширенной кодировки или юникода (unicode). Расшифровываеться как "wide character string".

Строка заканчиваеться нулевым кодом. Нет дескрипторов. Эти строки часто используються для работы с winApi.
Ну и вообще, если вам нужна поддержка юникода, то это единственный вариант.

Код:

' Статическое объявление
dim ws1 wstring * 20
ws1 = "Hello, world!"


' указатель
dim ws2 as wstring ptr
ws2 = @ws1
print *ws2



динамическая строка

Чтобы изменять размер строки, можно воспользоваться функциями allocate, realocate и dealocate.


allocate - захватывает память указанного размера и возвращает на неё указатель. В качестве параметра, размер в байтах.

dealocate - освобождает захваченную память. В качестве параметра указатель на освобаждаемый фрагмент.

Код:

dim zs3 as zstring ptr
zs3 = allocate( 20 )
 *zs3 = "Hello, world!"
print *zs3
deallocate zs3

Такой подход позволит вам использовать динамические строки типа zstring и особенно wstring. Но очистка памяти ложиться на совесть программиста.


string

String - основной тип строк в языке basic. В этой главе я расказываю о нём в последнюю очередь, поскольку он сложнее.

Эти строки имеют дескриптор, что делает их гибче и удобнее.

В основе всё тот же однобайтовый массив символов, что и в zstring, но уже не нужно закрывающего символа. В строках типа string можно использовать символы с любыми кодами от 0 до 255.

Дескриптор же нужен для управления этим массивом. Уже не нужно динамически изменять размеры строки, захватывая и переинициализируя память. Всё делаеться автоматически.

В дескрипторе содержиться информация о положении и длине строки. Что усложняет задачу получения указателя на саму строку.

Вот пример, как перевести строку из типа string в zstring. В этом нам поможет функция [strptr[/i].

StrPtr() - возвращает указатель на саму строку. В качестве параметра переменная типа string.

Код:

' объявление строки
dim s as string
s = "Hello, world!" & chr(0)

' объявление указателя
dim zs2 as zstring ptr
zs2 = StrPtr( s )
print *zs2

Я добавил в конец строки chr(0), но по опыту скажу, что это не так обязательно. Похоже что FreeBasic автоматически его добавляет.


конвертация юникода

Для начала, нужно рассказать немного о юникоде (unicode). Подробности вы можете прочитать здесь.
Юникод это набор символов, включающих почти все алфавиты.
8'битовй кодировки не хватает для того чтобы передать все нужные символы.

Стандартов юникода есть несколько. Различия заключаються и в размере одного символа. FreeBasic полагаеться на функции операционной системы. Например для win32 размер символа 16 бит. А для dos, поддержка юникода не реализована вообще.

Перекодировка из юникода в аски и обратно возможна, но это не равноценные операции. Когда символ юникода преобразуеться в аски, теряеться дополнительная информация. Когда же аски код переводиться в юникод дополнительная информация не востанавливаеться.
Если перекодировать с помощью национальных кодовых страниц, то части проблем можно избежать, но потери неизбежны.

Но есть ситуации, когда перекодировка необходима, например функция библиотеки требует zstring или wstring. Хотя в принципе это может быть не критично.

Str - конвертация unicode в ascii. В качестве параметра wstring ptr. На выходе string или zstring.

wStr - конвертация ascii в wstring. В качестве параметра строка типа string или zstring ptr. На выходе wstring.

Код:


dim ws as wstring * 80
ws = "Hello, world! = Привет, мир!"
print ws

dim a as string
a = str( ws )
print a

ws = wstr( a )
print ws

a = "latin and русский text."
ws = wstr( a )
print ws
sleep

Этот пример демонстрирует возможности и отрицательные стороны подобных преобразований.


Последний раз редактировалось: Eric-S (Вс Окт 05, 2008 12:39 pm), всего редактировалось 1 раз(а)

Eric-S

Сообщения : 738
Дата регистрации : 2008-08-06
Возраст : 34
Откуда : Россия, Санкт-Петербург

Посмотреть профиль http://eric50.narod.ru

Вернуться к началу Перейти вниз

Re: строки из нутри и указатели

Сообщение  Eric-S в Вс Окт 12, 2008 2:34 am

Очередная реинкорнация моей функции копирования подстроки. Она кажеться более удачной, чем предыдущие версии. А ещё она демонстрирует работу с указателями на строки.

Код:


' копирование подстроки
function str_copy( _
byVal w as wstring ptr, _ ' указатель на исходную строку
byVal s as uinteger = 0, _ ' номер первого символа
byVal l as uinteger = 0 _ ' длина подстроки
) as wstring ptr ' возвращает указатель новой подстроки
dim r as wstring ptr

' номер символ переводим к смещению
if s then s -= 1

' находим длину строки если она не указана
if l = 0 then
do while w[l] > 0
l += 1
loop

' если был указан стартовый символ укорачиваем длину подстроки
if s then
l -= s
end if
end if

' резервируем память
r = allocate( l * len( wstring ))

' посимвольно копируем подстроку
dim p as uinteger
for p = 0 to l - 1
(*r)[p] = (*w)[s + p]
next

' ставим конечный нулевой код
(*r)[l] = 0

' возвращаем указатель
function = r
end function


' тестовая строка
dim ws as wstring * 20
ws = "Hello, world!"

' копируем всю строку
print "'" & * str_copy( @ws) & "'"

' копируем от 8 символа и до конца
print "'" & * str_copy( @ws, 8) & "'"

' копируем первое слово
print "'" & * str_copy( @ws, 1, 5) & "'"

' один символ под номером 6
print "'" & * str_copy( @ws, 6, 1) & "'"

sleep

Как вы видете, функция без проверок и защит. Это целиком и полностью ложиться на программиста. Поступил я так из трёх соображений.
1. функция легче и быстрее.
2. проверки не всегда нужны, а для некоторых операций они могут мешать.
3. когда надо и где надо, можно вставить те проверки, которые надо!

Если знаете, как ускорить или оптимизировать код, подскажите. Принимаються все соображения кроме ассемблера.

Eric-S

Сообщения : 738
Дата регистрации : 2008-08-06
Возраст : 34
Откуда : Россия, Санкт-Петербург

Посмотреть профиль http://eric50.narod.ru

Вернуться к началу Перейти вниз

Re: строки из нутри и указатели

Сообщение  vbman в Вс Дек 07, 2008 4:22 pm

affraid У любой строки есть дескриптор - как тогда на нее ссылаться? сама переменная, в принципе, и есть дескриптор
avatar
vbman

Сообщения : 52
Дата регистрации : 2008-11-19
Возраст : 35
Откуда : Украина, Кировоград

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: строки из нутри и указатели

Сообщение  Спонсируемый контент


Спонсируемый контент


Вернуться к началу Перейти вниз

Предыдущая тема Следующая тема Вернуться к началу


 
Права доступа к этому форуму:
Вы не можете отвечать на сообщения