:: Visual Foxpro, Foxpro for DOS
Инверсия символьной строки
Simple777
Автор

Сообщений: 33855
Дата регистрации: 05.11.2006
Положим, есть строка '!МОДОГ 7102 МЫВОН C'

Нужно строку "развернуть", чтобы получилось "С НОВЫМ 2017 ГОДОМ!"

Притом сделать такой разворот как можно быстрее по времени исполнения.

Ясное дело, что можно побайтно читать строку справа налево и перезаписать ее. Но можно ли символьную строку "развернуть", используя какую-нибудь функцию VFP?

Поискал на форуме. Вроде бы есть похожая тема, но там речь шла о разворачивании данных типа FLOAT.

forum.foxclub.ru

Похоже, что функции bintoc/ctobin с флажком R для символьных строк применять нельзя. Может быть, можно еще как-то "развернуть" символьную строку?
Ratings: 0 negative/0 positive
Re: Инверсия символьной строки
Pliskin

Сообщений: 2959
Откуда: Новосибирск
Дата регистрации: 19.11.2003
Чем не нравится такое:

str1 = '!МОДОГ 7102 МЫВОН C'
str2 = ''
for i = len( str1 ) to 1 step -1
str2 = str2 + substr( str1, i, 1 )
endfor
Ratings: 0 negative/0 positive
Re: Инверсия символьной строки
Simple777
Автор

Сообщений: 33855
Дата регистрации: 05.11.2006
Да, такое не нравится. Такое я и сам умею.

Если так разворачивать нехилый по размеру текст, то будет весьма долго работать. К этому способу прибегну, если другого не найдется.
Ratings: 0 negative/0 positive
Re: Инверсия символьной строки
leonid

Сообщений: 3202
Откуда: Рига
Дата регистрации: 03.02.2006
Function RevertString
lparameter m.str
local m.str_len, m.str1
m.str_len=len(m.str)
if m.str_len=0
return ""
endif
if !pemstatus(_screen,"revw_ptr",5) or _screen.revw_ptr=0
Declare Integer GetProcessHeap in Win32API
Declare Integer HeapAlloc in Win32Api Integer, Integer, Integer
Declare RtlMoveMemory in Win32API Integer, String, Integer
local m.hhnd, m.ptr, m.st2
m.st2= ;
chr(0x55)+chr(0x89)+chr(0xE5)+chr(0x56)+chr(0x57)+chr(0x51)+chr(0x50)+chr(0x8B)+ ;
chr(0x75)+chr(0x08)+chr(0x8B)+chr(0x7D)+chr(0x0C)+chr(0x8B)+chr(0x4D)+chr(0x10)+ ;
chr(0x8A)+chr(0x44)+chr(0x0E)+chr(0xFF)+chr(0x88)+chr(0x07)+chr(0x47)+chr(0x49)+ ;
chr(0x75)+chr(0xF6)+chr(0x58)+chr(0x59)+chr(0x5F)+chr(0x5E)+chr(0x89)+chr(0xEC)+ ;
chr(0x5D)+chr(0xC2)+chr(0x10)+chr(0x00)
m.hhnd=GetProcessHeap()
m.ptr=HeapAlloc(m.hhnd,0,len(m.st2)+16)
RtlMoveMemory(m.ptr,m.st2,len(m.st2))
_screen.addproperty("revw_ptr",m.ptr)
endif
m.str1=replicate(chr(0), m.str_len)
Declare CallWindowProc in Win32API Integer, String, String @, Integer, Integer
CallWindowProc(_screen.revw_ptr, m.str, @m.str1, m.str_len, 0)
return m.str1
Ratings: 0 negative/0 positive
Re: Инверсия символьной строки
Simple777
Автор

Сообщений: 33855
Дата регистрации: 05.11.2006
Проверил - работает, и очень быстро!

Спасибо!..


"Непонятно, но здорово!.." (C)
Ratings: 0 negative/0 positive
Re: Инверсия символьной строки
of63

Сообщений: 25161
Откуда: Н.Новгород
Дата регистрации: 13.02.2008
В VFP есть SYS(2600, ...) - читатель/записыватель байтов в памяти ОС. Немного поступившись быстродействем ассемблера, можно сделать и через нее. Дело в том, что фокс, похоже, при операции x = X + "A", где x - строка, похоже заново резервирует память для строки x копирует в нее старое содержимое + новый байт. Это конечно тормоза. При помощи SYS(2600... подобное можно выполнять на порядок быстрее фоксового сумматора строк. Т.е.:
- выделяем память в ОС (размером в выходную строку = входной Y), получаем ее адрес A
- пишем в адрес A+0 последний символ из исходной строки B (SUBSTR(y, LEN(y)-0, 1)
- пишем в адрес A+1 последний символ из исходной строки B (SUBSTR(y, LEN(y)-1, 1)
... повторить по количеству символов Y
Уверяю, что будет на порядок быстрее, чем фоксовые же: x = x + SUBSTR(y, ...) (но медленнее, чем ассемблер)
Ratings: 0 negative/0 positive
Re: Инверсия символьной строки
WbrErr

Сообщений: 1960
Дата регистрации: 05.12.2006
А в VBA есть функция StrReverse.
Ratings: 0 negative/0 positive
Re: Инверсия символьной строки
Simple777
Автор

Сообщений: 33855
Дата регистрации: 05.11.2006
Интересно, будет ли эта функция работать быстрее/медленнее, чем из VFP с ассемблерной вставкой?
Ratings: 0 negative/0 positive
Re: Инверсия символьной строки
spinz

Сообщений: 5263
Дата регистрации: 21.01.2016
leonid
Function RevertString
chr(0x55)+chr(0x89)+chr(0xE5)+chr(0x56)+chr(0x57)+chr(0x51)+chr(0x50)+chr(0x8B)+ ;
chr(0x75)+chr(0x08)+chr(0x8B)+chr(0x7D)+chr(0x0C)+chr(0x8B)+chr(0x4D)+chr(0x10)+ ;
chr(0x8A)+chr(0x44)+chr(0x0E)+chr(0xFF)+chr(0x88)+chr(0x07)+chr(0x47)+chr(0x49)+ ;
chr(0x75)+chr(0xF6)+chr(0x58)+chr(0x59)+chr(0x5F)+chr(0x5E)+chr(0x89)+chr(0xEC)+ ;
chr(0x5D)+chr(0xC2)+chr(0x10)+chr(0x00)

Для небольших строк конечно сгодится и так, но в общем случае эффективней обрабатывать строку не побайтово, а двордами.

Можно использовать вот такой цикл (esi указывает на последний дворд исходной строки, edi - на начало результирующей, 32-битный код)
lodsd
bswap eax
stosd
sub esi,8

Естественно, не надо забывать про "хвост" в случае когда длина строки не кратна 4
Ratings: 0 negative/0 positive
Re: Инверсия символьной строки
Crispy

Сообщений: 18571
Дата регистрации: 16.05.2005
Simple777
Интересно, будет ли эта функция работать быстрее/медленнее, чем из VFP с ассемблерной вставкой?

Чисто по терминологии. Нету тут никакой "ассемблерной вставки". Тут таки простая виндовская апишность как бы. [sm128] А ассемблерная или уж какая иная "вставка" - было бы нечто совсем иное. Да и вызывалось бы по иному.


------------------
В действительности все иначе, чем на самом деле.
                                      (Антуан де Сент-Экзюпери)
Ratings: 0 negative/0 positive
Re: Инверсия символьной строки
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Тут имеет место вставка машинного кода, который, очевидно, получен из соответствующего ассемблерного исходного кода - возможно, используя ту или иную программу-ассемблер, а возможно и просто "вручную", благо команд там всего-ничего
ВинАПИ используется исключительно в качестве небольшого трюка для вызова этого машинного кода, т.к. "напрямую" фокс не позволяет вызывать ничего этакого.


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Инверсия символьной строки
Crispy

Сообщений: 18571
Дата регистрации: 16.05.2005
Igor Korolyov
ВинАПИ используется исключительно в качестве небольшого трюка для вызова этого машинного кода, т.к. "напрямую" фокс не позволяет вызывать ничего этакого.

Если так рассуждать, то и фокс служит всего лишь для "вызова машинного кода". ;)
Вообще говоря, "машинный код" - как раз таки наиболее близок лишь к ассемблеру (было дело, писал немного и на первом и на втором), разве что ассемблер содержит много "ненужной" информации, связанной с именованием команд, а так, местами в чем-то даже схожи. И если так уж строго подходить, в dll скорее всего "содержится" даже и не ассемблерный код, а что-нибудь вроде сишной программки. Сомневаюсь, что ассемблер вообще использовался при написании винды. Ну может в каких-то редких случаях.


------------------
В действительности все иначе, чем на самом деле.
                                      (Антуан де Сент-Экзюпери)
Ratings: 0 negative/0 positive
Re: Инверсия символьной строки
spinz

Сообщений: 5263
Дата регистрации: 21.01.2016
Crispy
в dll скорее всего "содержится" даже и не ассемблерный код, а что-нибудь вроде сишной программки.
Жжошь
Ratings: 0 negative/0 positive
Re: Инверсия символьной строки
pasha_usue

Сообщений: 3647
Откуда: Е-бург
Дата регистрации: 06.10.2006
spinz
Crispy
в dll скорее всего "содержится" даже и не ассемблерный код, а что-нибудь вроде сишной программки.
Жжошь
Жжот, конечно. Но мысль, в общих чертах, верная. Машинного кода скомпилированного из исходников на ассемблере, действительно очень немного. А вот машинного кода, скомпилированного из исходников на C (C++), действительно большинство.

И компилятор C++ скомпилирован компилятором C++.
Ratings: 0 negative/0 positive
Re: Инверсия символьной строки
spinz

Сообщений: 5263
Дата регистрации: 21.01.2016
pasha_usue
Машинного кода скомпилированного из исходников на ассемблере, действительно очень немного.
Это если говорить про платформу PC. Хотя, например, первую версию ядра линукса Торвальдс сделал целиком на ассемблере - других средств у него просто не было.

А если взглянуть шире, то существует огромное количество всяких контроллеров с крайне ограниченными ресурсами, где другого выбора, кроме ассемблера, быть не может.



Исправлено 1 раз(а). Последнее : spinz, 10.01.17 12:10
Ratings: 0 negative/0 positive
Re: Инверсия символьной строки
Crispy

Сообщений: 18571
Дата регистрации: 16.05.2005
spinz
А если взглянуть шире, то существует огромное количество всяких контроллеров с крайне ограниченными ресурсами, где другого выбора, кроме ассемблера, быть не может.

Ну ты это тетке скажи, которая сидит за вордом и косынкой с пауком, много ей контроллеров-то надо. [sm128]
Тем более речь тут шла только о винде и фоксе в задачке с обращением строки, где решение использует виндовскую функцию. Найди там ассемблер. Хотя, если бы скажем написать на ассемблере функцию обращения и подгружать в фокс, возможно тоже было бы неплохо. [sm128]


------------------
В действительности все иначе, чем на самом деле.
                                      (Антуан де Сент-Экзюпери)
Ratings: 0 negative/0 positive
Re: Инверсия символьной строки
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Crispy
решение использует виндовскую функцию. Найди там ассемблер.

Ещё раз - "виндовые функции" в примере Леонида используются для выделения памяти под блок кода, и для вызова этого самого блока кода. Сам же код представлен в виде машинного кода. И это
m.st2= ;
chr(0x55)+chr(0x89)+chr(0xE5)+chr(0x56)+chr(0x57)+chr(0x51)+chr(0x50)+chr(0x8B)+ ;
chr(0x75)+chr(0x08)+chr(0x8B)+chr(0x7D)+chr(0x0C)+chr(0x8B)+chr(0x4D)+chr(0x10)+ ;
chr(0x8A)+chr(0x44)+chr(0x0E)+chr(0xFF)+chr(0x88)+chr(0x07)+chr(0x47)+chr(0x49)+ ;
chr(0x75)+chr(0xF6)+chr(0x58)+chr(0x59)+chr(0x5F)+chr(0x5E)+chr(0x89)+chr(0xEC)+ ;
chr(0x5D)+chr(0xC2)+chr(0x10)+chr(0x00)
Ассемблерную программу, из которой получен данный машинный код, Леонид не приводил. Впрочем, её несложно получить в любом win32 отладчике/дизассемблере.
push ebp
mov ebp,esp
push esipush edi
push ecx
push eax
mov esi,[ebp+8]
mov edi,[ebp+0C]
mov ecx,[ebp+10]
loop:
mov al,[ecx+esi-1]
mov [edi],al
inc edi
dec ecx
jne loop
pop eax
pop ecx
pop edi
pop esi
mov esp,ebp
pop ebp
retn 10

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


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Инверсия символьной строки
Crispy

Сообщений: 18571
Дата регистрации: 16.05.2005
Ну так бы и сказал.

[attachment 26848 hqdefault.jpg]


------------------
В действительности все иначе, чем на самом деле.
                                      (Антуан де Сент-Экзюпери)
Ratings: 0 negative/0 positive
Re: Инверсия символьной строки
Taran

Сообщений: 13623
Откуда: Красноярск
Дата регистрации: 16.01.2008
Igor Korolyov
Crispy
Хотя, если бы скажем написать на ассемблере функцию обращения и подгружать в фокс, возможно тоже было бы неплохо.
Именно это он и делает.

Не в обиду Леониду, но для осторожности новых.

Как-то использовал расчет MD5 (а может SHA1 не помню) по аналогичной схеме от Леонида.
Программа теневая крутится сутки напролет. Примерно на пятые сутки вылетала.
Заменил этот расчет на чистое API - перестало.
Видимо где-то утечка.
Ratings: 0 negative/0 positive
Re: Инверсия символьной строки
spinz

Сообщений: 5263
Дата регистрации: 21.01.2016
И на Солнце есть пятна...))
Ratings: 0 negative/0 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 9 (Гостей: 9)

© 2000-2024 Fox Club 
Яндекс.Метрика