CorelScript: как из string получить все символы в array?

Статус
Закрыто для дальнейших ответов.

yann

Участник
Топикстартер
Сообщения
3
Реакции
0
всем привет,
нужен срочный хелп. собственно, сабж: из переменной типа string необходимо получить все символы в array. К сожалению, в хелпе ничего не нашел...

ЗЫ. в паскале это выглядит так: string, в корелскрипт эта структура не работает...
 

Arkady

Участник
Сообщения
697
Реакции
2
Ответ: CorelScript: как из string получить все символы в array?

yann сказал(а):
всем привет,
нужен срочный хелп. собственно, сабж: из переменной типа string необходимо получить все символы в array. К сожалению, в хелпе ничего не нашел...

ЗЫ. в паскале это выглядит так: string, в корелскрипт эта структура не работает...

Можно так (один из способов без использования Win32 API):

Код:
Sub stringToArray(s As String, ByRef a() As Byte)
    Dim fNum As Byte
    Dim f As String
    Set fs = CreateObject("Scripting.FileSystemObject")
    
    ReDim a(Len(s))
    f = fs.GetSpecialFolder(2) + "\" + fs.GetTempName
    fNum = FreeFile()
    Open f For Output As #fNum
        Print #fNum, s
    Close #fNum
    Open f For Binary As #fNum Len = Len(s)
        Get #fNum, , a
    Close #fNum
    fs.DeleteFile (f)
End Sub
 

yann

Участник
Топикстартер
Сообщения
3
Реакции
0
Ответ: CorelScript: как из string получить все символы в array?

Arkady сказал(а):
Можно так (один из способов без использования Win32 API):

Код:
Sub stringToArray(s As String, ByRef a() As Byte)
    Dim fNum As Byte
    Dim f As String
    Set fs = CreateObject("Scripting.FileSystemObject")
    
    ReDim a(Len(s))
    f = fs.GetSpecialFolder(2) + "\" + fs.GetTempName
    fNum = FreeFile()
    Open f For Output As #fNum
        Print #fNum, s
    Close #fNum
    Open f For Binary As #fNum Len = Len(s)
        Get #fNum, , a
    Close #fNum
    fs.DeleteFile (f)
End Sub

Нормальные герои всегда идут в обход...
Спасибо, я тоже рассматривал вариант обращения к файлу, но мне это никогда не нравилось (даже не знаю, почему). Уже удалось разобраться самому, кстати, иным способом:
Код:
'numb$ - переменная, которую требуется загнать в массив
DIM _label (len(numb$))

tmp$=numb$

for i% = 1 to len(numb$)
    _label(i%) = ASC(tmp$)
    MID(tmp$,1,1)=chr(32)
    tmp$ = LTRIM(tmp$)
next
1) функция ASC возвращает значение первого символа из string в формате ascii. Читаем ее в массив _label.
2) функция MID подменяет символы в string - в данном случае, 1й символ в кол-ве 1й шт. на значение chr(32), то есть пробел.
3) функция LTRIM удаляет все пробелы в начале переменной вплоть до первого символа.

Таким образом, циклом, длина которого равна количеству символов переменной, я прочитал в массив все символы строки, просто убирая по одному символу после прочтения (именно для этого понадобилось использовать временную переменную tmp$).
 

Arkady

Участник
Сообщения
697
Реакции
2
Ответ: CorelScript: как из string получить все символы в array?

yann сказал(а):
Нормальные герои всегда идут в обход...
…1) функция ASC …
2) функция MID…
3) функция LTRIM…
Таким образом, циклом, длина которого равна… bla-bla-bla… для этого понадобилось использовать временную переменную tmp$).
Очень «долгоиграющий» код :) Да и к тому же весьма не симпатишный — на уровне урока информатики 5-го класса Верхнемухосранской церковноприходской школы.
То же, но короче и без лишних телодвижений:
Код:
Sub String2Vector(ByVal sSRC As String, _
                   ByRef s() As String * 1)
    Dim L As Integer
    L = Len(sSRC) - 1
    ReDim s(L)
    For i% = 0 To L
        s(i%) = Mid$(sSRC, i% + 1, 1)
    Next
End Sub
Если использовать Win32 API, то получается вообще одна строчка без циклов. В этом случае выходной вектор состоит из байтов, что в ряде случаев даже намного предпочтительнее; преобразование его в Array of String*1 не составит труда. Код работает не просто быстро, а очень быстро:

Код:
REM =================================================
REM Описание интерфейса с Win32 API
REM Желательно вынести в отдельный модуль, заменив Private на Public
REM =================================================

Private Declare Function str2bytes& Lib "kernel32" Alias "lstrcpyA" _
    (ByRef bFirst As Byte, _
     ByVal lpString2 As String)

Private Declare Function lstrlen& Lib "kernel32" Alias "lstrlenA" _
    (ByVal lpString As String)

REM ===============================================
REM Далее собственно сама «чудо»-процедура
REM Предполагается, что передаваемая строка всегда непустая,
REM т.е. содержит минимум один символ, отличный от нуля.
REM ===============================================

Sub String2Vector(ByVal sSRC As String, _
                   ByRef b() As Byte)

   ReDim b(lstrlen&(sSRC) - 1)
   lResult& = str2bytes&(b(0), sSRC) ' /* Вот, собственно, и всё :p */
End Sub

P.S. Мощь процессоров убивает в программисте алгоритмиста.
 

yann

Участник
Топикстартер
Сообщения
3
Реакции
0
Ответ: CorelScript: как из string получить все символы в array?

Arkady сказал(а):
на уровне урока информатики 5-го класса Верхнемухосранской церковноприходской школы.
Не стОит ёрничать, Аркадий. Программирование - не самая сильная моя сторона, единственно, почему этим занимаюсь - производственная необходимость. Тем не менее благодарю за подробный и развернутый ответ.
 

Hippo

Участник
Сообщения
29
Реакции
0
Ответ: CorelScript: как из string получить все символы в array?

А почему не на ассемблере?

Странно, Аркадий, что использование/знание функций Виндоус Вы приравниваете к умению строить хорошие алгоритмы...
 

Hippo

Участник
Сообщения
29
Реакции
0
Ответ: CorelScript: как из string получить все символы в array?

Кстати, как человек, программирующий под Корелом с 1998 года... не могу не отметить, что выщипывание блох Мухосранской школы никак не поможет ускорить работу проекта в целом...

Наверняка этот кусок стоит внури какой-нибудь процедуры, которая или читает с диска файлег метров в 100, или его записывает, или делает в Кореле две-три тысячи объектов...

Поэтому никакого прироста заметно не будет...

Чтобы, Аркадий, не быть голословным (говоря по-бандитски - объявляюсь)...

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

Что примечательно - при замене на двумерные массивы скорость работы действительно выросла на 12,5 процентов...

Когда я в ТурбоПрофайлере измерял скорость работы, то предварительно выгрузил СмартДрайв (дело было на 486 машине, Винда запускалась из-под Доса, СамартДрайв стоял в автоэкзеке).

И тогда старший товарищ высказал похвалу, которая осталась со мной по сей день - "появились первые признаки профессионализма" :).

Резюме - выигрыш по скорости от использования функций Виндоус, если он будет, будет меньше, чем дельта от того, будет ли Корел запущен первый раз при старте машины, или второй :).

Здесь - надо кодить быстро, не раздумывая. В Кореле есть только одна действительно медленная штука - GetPixel в Фотопэйнте. Работает как "поставить точку" с помощью 10 прерывания биоса на 286 машине.

Но и то - переписывать кусок с использованием функций Виндоус я не стал. При текущем использовании я теряю... ну... минуту в неделю...

Это ж не задача сортировки в Ворде... Или не трёхмерная диффузия...
 

Arkady

Участник
Сообщения
697
Реакции
2
Ответ: CorelScript: как из string получить все символы в array?

Hippo сказал(а):
А почему не на ассемблере?

Странно, Аркадий, что использование/знание функций Виндоус Вы приравниваете к умению строить хорошие алгоритмы...

Алгоритм немного отличается способа его реализации :)

К сожалению, работа со строками также не слишком сильная (быстрая) сторона BASIC'а. Работа с указаталеми отсутствует напрочь, хотя для данной задачи байтовый массив суть то же, что и исходная строка во внутреннем представлении и «преобразовать» строку в массив суть то же, что просто изменить тип указываемого объекта. Что и элементарно решается с помощью той же lstrcpyA, которая копирует байты-символы из исходной строки в байтовый массив. Как видно из screenshot'a, сама процедура копирования занимает 10 (!) байт машинного кода (6 машинных команд).

Для сравнения приведен код, выполняемый при вызове BASIC'овской функции Len() в случае аргумента string type и API kernel32:strlenA (обычный поиск нулевого байта в цепочке — выделен стрелкой от JNZ) .
И это при том, что функция Len() — только небольшая часть реализации алгоритма на BASIC'е. А ведь есть еще цикл FOR…TO, функция MID$() и т.д. порождающие выполнение не менее длинных цепочек, чем приведенная в качестве примера Len().
Как видим, сравнение не в пользу BASIC'а :)

В первоначальном варианте решения YANN кроме того щедро сдобрил минимум необходимого «инструментария» trim'ом и проч., что не прибавило скорости исполнения кода.

Наверняка этот кусок стоит внури какой-нибудь процедуры, которая или читает с диска файлег метров в 100, или его записывает, или делает в Кореле две-три тысячи объектов...
Поэтому никакого прироста заметно не будет...
Я с ваших слов прямо смеюся… Какой-то прямо пораженческий подход к делу. А вдруг это преобразование запускается 10.000.000 раз c рекурсивным вызовом самое себя (кстати, еще один вариант преобразования — особо нешустрый)?
 

Вложения

  • lstrcpyA.gif
    lstrcpyA.gif
    6.6 КБ · Просм.: 793
  • BasicLen.gif
    BasicLen.gif
    25.4 КБ · Просм.: 760
  • API_StrLenA.gif
    API_StrLenA.gif
    12.1 КБ · Просм.: 997

Hippo

Участник
Сообщения
29
Реакции
0
Ответ: CorelScript: как из string получить все символы в array?

Аркадий...

[скриплю старыми костями... вспоминаю 10 класс, когда я программировал в кодах на ДВК... вспоминаю 3 курс... когда я начал писАть на ассемблере... вспоминаю свою прогу, которая писала сектор в обход 13 прерывания биоса... вспоминаю другую свою прогу, которая рисовала на экране быстрее, чем движется луч... вспоминаю, что потом я решил вообще работать с видеопамятью в офлайне, нарисовав всё заранее, и только переключая цветА черех порты... вспоминаю, что ТурбоДебаггер я не видел уже лет 13... опять скреплю старыми костями... и...]

Аркадий... а зачем переливать байты из пустого в порожнее?

А аффтара есть уже структура данных. Он делает другую структуру и руками, грубо, говорит - вот эта структура начинается в памяти с того же места, откуда начинается первая структура.

Особенно эффективно это будет для Вашего примера с 10 миллионами... Мы не переливаем эти 10 метров из одной области в другую, а просто переназначаем пойнтеры.


В общем же, лично я теперь работаю, например, так:

AppActivate ("CorelDraw"), False
SendKeys "% {DOWN 4}{ENTER}"
newHour = Hour(Now())
newMinute = Minute(Now())
newSecond = Second(Now()) + 1
waitTime = TimeSerial(newHour, newMinute, newSecond)
Application.Wait waitTime

' Close #1
CorelScript.SetReferencePoint 9
CorelScript.CreateTextString 550000, -550000, -550000, 550000, outstr$
'CorelScript.UnSelectAll
'CorelScript.CreateRectangle 560000, -560000, -560000, 560000, 0
CorelScript.SelectObjectsInRect 560000, -560000, -560000, 560000, 0
CorelScript.SetFrameColumn 0, 330000, 10000
CorelScript.SetFrameColumn 1, 330000, 10000
CorelScript.SetFrameColumn 2, 330000, 10000


newHour = Hour(Now())
newMinute = Minute(Now())
newSecond = Second(Now()) + 1
waitTime = TimeSerial(newHour, newMinute, newSecond)
Application.Wait waitTime


SendKeys "^8", True

и очень хорошо себя чувствую.

Вы можете спросить - что делает последний сендкиз? Отвечу - в Кореле на этом кее сидит команда "подогнать текст под рамку". Она в скриптах не разрешена. И из меню/шорткатов - пожалуйста. Поэтому мы садим в Кореле команду на шорткат, а потом вот так вот впихиваем Корелу в глотку.

А Вы говорите - экономный код...

Главное - решить задачу в целом. Ни к чему стремиться на секунду быстрее спуститься на лифте, если впереди большой турпоход...
 
Статус
Закрыто для дальнейших ответов.