XGM Forum
Сайт - Статьи - Проекты - Ресурсы - Блоги

Форуме в режиме ТОЛЬКО ЧТЕНИЕ. Вы можете задать вопросы в Q/A на сайте, либо создать свой проект или ресурс.
Вернуться   XGM Forum > Warcraft> Академия: форум для вопросов> Jass
Ник
Пароль
Войти через VK в один клик
Сайт использует только имя.

Закрытая тема
 
J
expert
offline
Опыт: 48,447
Активность:
[Task] Разбивка строки
Задача решена MrSmiLe-ом, ему перечисленно 600 опыта. (пост)

вообщем эта задача большей частью только на алгоритмику, нужно сделать функцию
Код:
globals
    string array udg_PartStr
endglobals

function PriceStr takes string Str, integer Amount returns integer
    local integer Index = 0
    // --------
    return Index
endfunction

которая разбивает строку Str на отдельные составляющие длина которых не больше числа Amount, они суются по порядку в массив udg_PartStr начиная с [0], и после функция возвращает количество занятых ячеек в этом массиве на эту строку.
Теперь самое сложное, нужно сделать так чтобы каждая часть не имела обрыва слова, т.е. разбиение строки проходило только между слов, а также усложняя задачу - Str может содержать цветовые теги, именно это является главной задачей...
Также нужно учитывать возможность нахождении одного или нескольких цветовых тегов внутри другово
И если я подставлю эту функцию в код:
Код:
function Display takes nothing returns nothing
    local integer i = 0
    local integer Index = PriceStr("|cFFFF0000Jass|r – это |cFF00FF00интерпретируемый язык|r (скр|cFF0000FFипт), который использует вар для создан|rия сценариев, с помощью |cFFFF0000Jass|r-а можно управ|cFF0000FFлять только игровыми проце|rссами", 30)
    // Я произвольно поставил цветовые теги, но они должны нормально все учитыватся как это бы делалалось при полной строке!!
    loop
        exitwhen i > Index
        call DisplayTextToForce( bj_FORCE_ALL_PLAYERS, udg_PartStr[ i])
        set i = i + 1
    endloop
endfunction

выполнялось то что надо...

--------------------------------------------------
Если кто непонял, то обьясню на примере
Str = Шла Саша по шоссе и сосала сушку
Amount = 12
в результате в масиве должно быть:
[0] - "Шла Саша по"
[1] - "шоссе и"
[2] - "сосала сушку"
--------------------------------------------------

P.S.
Не стесняйтесь предлагать идеи, может вы сами не можете сделать, но поможете другим.

эту задачу я выбрал потому что она большей степенью зависит от настойчивости и заинтересованности, чем от знаний (последняя задача от тоадкопа про Локал Плауер).

Отредактировано ShadoW DaemoN, 07.08.2008 в 00:23.
Старый 26.06.2007, 20:33
J
expert
offline
Опыт: 48,447
Активность:
если для вас это сложно сделайте пока что алгоритм без учитывания цветовых тегов...
Старый 26.06.2007, 21:28
adic3x

offline
Опыт: 108,439
Активность:
через пробелы отлавливать кол-во слов. смотреть сколько у нас будет полнеценных "частей" (т.е. там где кол-во необходимых часетй -1 делится без остатка). в первые числа вкидывать по несколько слов + в конец то что останется... вроде примерно так, расписывать лень=)
Старый 27.06.2007, 11:24
J
expert
offline
Опыт: 48,447
Активность:
ADOLF лень=/ ненавижу лень всегда мне мешает, попробуй осуществить, сначало без учитывания цыетовых тегов хотябы, а потом с учитыванием.

P.S.
Есль много способов которыми можно решить эту задачу, пытайтесь найти самый легкий, оптимальность здесь не самое важное, т.к. код выполняется еденично...
Если через неделю ничего не будет придуманно, я выложу свой алгоритм...
Старый 27.06.2007, 11:37
YasonDelAlt

offline
Опыт: 862
Активность:
Jon
Что-то приблизительно такое забацал тут минут за 10 (не могу проверить, вара у меня под рукой нет сейчас):
» код
Код:
globals
    string array udg_PartStr
endglobals

function PriceStr takes string Str, integer Amount returns integer
    local integer Index = 0
    local integer blockBegin = 0
    local integer logicBlockSize = 0
    local integer lastSpace = 0
    local integer srcPos = 0
    local integer srcLen = StringLength(Str)
    local boolean tagFlag = false
    local string char

    loop
        exitwen srcPos >= srcLen
        set char = StringCase(SubString(Str, srcPos, srcPos+1), false) //Перевести в нижний регистр (не помню точно функцию)
        if char == '|' then
            set tagFlag = true
        elseif char == 'c' then
            if tagFlag then
                 set srcPos = srcPos + 7
            else
                 set logicBlockSize = logicBlockSize + 1
            endif
        elseif char == 'r' then 
            if tagFlag then
                 set srcPos = srcPos + 1
            else
                 set logicBlockSize = logicBlockSize + 1
            endif
        elseif char == ' ' then
            if logicBlockSize >= Amount then
                set udg_PartStr[Index] = SubString(Str, blockBegin, lastSpace)
                set Index = Index + 1
                set blockBegin = lastSpace + 1
                set logicBlockSize = 0
            endif
            set lastSpace = srcPos
        else
            set logicBlockSize = logicBlockSize + 1
        endif
        set tagFlag = false

        set srcPos = srcPos + 1
    endloop
    if blockBegin < srcLen-1 then
        set udg_PartStr[Index] = SubString(Str, blockBegin, srcLen)
        set Index = Index + 1
    endif
    return Index
endfunction
Функция еще сырая, но надеюсь общий смысл ясен: парсим всю строку в поисках пробелов и тегов, напоролись на тег цвета: увеличиваем позицию в строке, но трогаем логическую длину, тоже самое с конечным тегом,
напоролись на пробел: сравниваем логическую длину с требуемой, если больше то сбрасываем кусок до предыдущего пробела и устанавлеваем начало блока на прошлый пробелл, восстанавливаем значения нужных переменных и продолжаем парсить. Вот и все. Да чуть не забыл, с русским текстом функция работать не будет, если нужен русский текст то используйте мою библиотеку Russian Strings Librarry, заменив вызовы функций по работе с текстом на аналоги из библиотеки.

Отредактировано Jon, 28.06.2007 в 20:21.
Старый 27.06.2007, 11:55
J
expert
offline
Опыт: 48,447
Активность:
YasonDelAlt неплохо, (Для справки: страки в джазе (и символы тоже) нужно выделять двойными ковычками...), но немаловажное замечание - Цветовой тег не переносится на следующую строку.

олодец что догодался насчет регистра

Jon добавил:
+ неточное разбиение строки, т.е. разбивает строку иногда там где вошло бы еще слово...

Отредактировано Jon, 11.07.2007 в 19:40.
Старый 27.06.2007, 12:12
adic3x

offline
Опыт: 108,439
Активность:
лан, раз уж умничаем то тогда если вам нужно сделать аналого тега |n :
Код:
set s="
"
Старый 27.06.2007, 12:14
J
expert
offline
Опыт: 48,447
Активность:
ADOLF не все так просто, т.к. если поставить в строку эту переменую, то по алгоритму она будет воспринимать это как обычный симвло, и получится что одну часть разобьет еще на 2, это надо делать также джазом, т.е. если встретился тег |n, перейти к следующему индексу массива, а текущий закончить

Отредактировано Jon, 30.06.2007 в 19:10.
Старый 27.06.2007, 12:21
adic3x

offline
Опыт: 108,439
Активность:
я имел ввиду если вставлять просто в строку...
Старый 27.06.2007, 12:23
J
expert
offline
Опыт: 48,447
Активность:
было бы неплохо кстате предусмотреть возможность нахождения одного или нескольких цветовых тегов внутри другого.
Старый 27.06.2007, 15:29
J
expert
offline
Опыт: 48,447
Активность:
смотрите верх первого поста

Отредактировано Jon, 28.06.2007 в 20:07.
Старый 28.06.2007, 20:00
dk

offline
Опыт: 60,293
Активность:
Мой вариант, есть поддержка русских символов и вложенных тегов... Теги должны быть заданы в стандарте |cXXXXXXXX|r
» код

[script]globals
string array udg_PartStr
endglobals

function PriceStr takes string Str, integer Amount returns integer
local integer Index = 0
local integer lspace = 0
local integer length = 0
local integer maxlength = StringLength(Str)
local integer partlength = 0
local integer dpart = 0
local integer position = 0
local string symbol = ""
local string tag = ""
local string a = SubString("À", 0, 1)
local string b = SubString("ð", 0, 1)
// --------
loop
// --------
set symbol = SubString(Str, position, position + 1)

if symbol == a or symbol == b then
set position = position + 1
elseif symbol == "|" then
set tag = SubString(Str, position + 1, position + 2)
if tag == "c" then
set position = position + 9
set partlength = partlength - 1
elseif tag == "r" then
set position = position + 1
set partlength = partlength - 1
endif
elseif symbol == " " then
set lspace = position
endif
// --------
set partlength = partlength + 1
if partlength > Amount then
set udg_PartStr[Index] = SubString(Str, dpart, lspace)
set Index = Index + 1
set position = lspace
set dpart = lspace + 1
set partlength = 0
endif
// --------
set position = position + 1
exitwhen position > maxlength
endloop
return Index
endfunction[/script]


Dead_knight добавил:
Кста джон в твоей функции для проверки превышена максимальная длина строки...
Старый 29.06.2007, 12:01
exAres
I love magic :)
offline
Опыт: 7,788
Активность:
Dead_knight твой алгоритм работает не корректно, русские буквы не правильно считает + если в конце строки пробел то последняя строка не защитывается.
Я от нечего делать сделал свой вариант, имхо он не далеко не идеален, но работает :)
» Код
см. ниже

Отредактировано MrSmiLe, 02.07.2007 в 02:48.
Старый 30.06.2007, 17:58
J
expert
offline
Опыт: 48,447
Активность:
молодцы.. начну тестить кодики через пару часиков.. ща пока отдохните

Jon добавил:
Dead_knight у тебя последняя строка не показывается и цветовые теги не переносятся на следующую строчку
MrSmiLe у тебя с цветовыми тегагами какаято хня получается (в текст добовляются левые сиволы, некоторые теги переносятся, а некоторые на одной же строчке не доходят до конца)... и строчки не ровные получаются...

Jon добавил:
MrSmiLe, из твоего кода:
Код:
if SubString(Str,i-1,i+1)=="|c" then
            set s=s+SubString(Str,i-1,i+10)
            set i=i+9
        endif
        if SubString(Str,i-1,i+1)=="|r" then
            set s=s+SubString(Str,i-1,i+2)
            set i=i+1
        endif

хех... слишком большие строки отрезаеш

Jon добавил:

люди... вы че делаете? я же сказал что вы должны предусмотреть возможность нахождения одного или много тегов внутри другово тега.
Это без покрайне мере 2-ух массивов не сделать...

Необязательно делать подержку руских символов... главное это работа с тегами

Jon добавил:
я ща подправлю строку в первом посте... сделаю ее так чтобы демонстрировать больше багоф...

Jon добавил:
награда опыта увеличина:)

Отредактировано Dead_knight, 01.07.2007 в 04:52.
Старый 30.06.2007, 19:44
J
expert
offline
Опыт: 48,447
Активность:
Я уезжаю на неделю... приеду посмотрю че сдесь еще скажут... если скажут вообще... напомню что необязательно надо делать поддержку руских символов, конечно было бы лучше сделать основной является работа с тегами
Старый 01.07.2007, 01:06
dk

offline
Опыт: 60,293
Активность:
Так я вроде все исправил и добавил перенос тегов...
» code

Код:
globals
    string array udg_PartStr
endglobals

function PriceStr takes string Str, integer Amount returns integer
    local integer Index = 0
    local integer itags = 0
    local integer i = 0
    local integer lspace = 0
    local integer maxlength = StringLength(Str)
    local integer partlength = 0
    local integer dpart = 0
    local integer position = 0
    local string symbol = ""
    local string tag = ""
    local string array tags
    local string a = SubString("А", 0, 1)
    local string b = SubString("р", 0, 1)
    // --------
    loop
        // --------
        set symbol = SubString(Str, position, position + 1)
        
        if symbol == a or symbol == b then
            set position = position + 1
        elseif symbol == "|" then
            set tag = SubString(Str, position + 1, position + 2)
            if  tag == "c" then
                set tags[itags] = SubString(Str, position, position + 10)
                set itags = itags + 1
                set position = position + 9
                set partlength = partlength - 1
            elseif tag == "r" then
                set itags = itags - 1
                set tags[itags] = ""
                set position = position + 1
                set partlength = partlength - 1
            endif
        elseif symbol == " " then
            set lspace = position
        endif
        // --------
        set partlength = partlength + 1
        if partlength > Amount then
            set udg_PartStr[Index] = udg_PartStr[Index] + SubString(Str, dpart, lspace)
            set Index = Index + 1
            set position = lspace
            set dpart = lspace + 1
            set partlength = 0
            if itags > 0 then
                set i = itags
                loop
                    set i = i - 1
                    set udg_PartStr[Index] = tags[i] + udg_PartStr[Index]  
                    set udg_PartStr[Index-1] = udg_PartStr[Index-1] + "|r"
                    exitwhen i == 0
                endloop
            endif
        endif
        // --------
        set position = position + 1
        if position > maxlength then
            set udg_PartStr[Index] = udg_PartStr[Index] + SubString(Str, dpart, maxlength)
        endif
        exitwhen position > maxlength
    endloop
    return Index
endfunction




Отредактировано Dead_knight, 02.07.2007 в 08:49.
Старый 01.07.2007, 11:53
Toadcop

offline
Опыт: 54,313
Активность:
ну имхо я тоже попробую... =)
Старый 01.07.2007, 13:45
exAres
I love magic :)
offline
Опыт: 7,788
Активность:
Dead_knight если смотреть только пример с этой строкой и с таким количеством символов то норм, а ты попробуй количество символов 100 или 10 поставь :)
Вот я исправил свои ошибки + добавил возможность использования |n и продолжения цветовых тегов вложеных друг в друга.
» StrParse
Код:
function PriceStr takes string Str, integer Amount returns integer
 local integer Index=0
 local integer i=0
 local integer lst=0
 local integer lwd=0
 local integer tags=0
 local integer min=0
 local integer inW=0
 local integer clear=0
 local string s=""
 local string word=""
 local string color=""
 local string tag=""
 local string mark="" 
 local boolean find=false
 local boolean end=false
 loop
 exitwhen end
  set i=i+1
  set mark=SubString(Str,i-1,i)
  if mark=="|" then
   set tag=StringCase(SubString(Str,i,i+1),false)
   if tag=="c" then
    if word!="" then
     set inW=inW+1
    endif
    set word=word+SubString(Str,i-1,i+9)
    set tags=tags+1
    set color=color+SubString(Str,i-1,i+9)
    set i=i+9
   elseif tag=="r" then
    if word=="" then
     set s=s+"|r"
    else
     if inW>0 then
      set inW=inW-1
     endif
     set word=word+"|r"
     if tags>0 then
      set word=word+SubString(color,0,10*tags-10)
     endif
    endif
    set clear=clear+1
    set i=i+1
   elseif tag=="n" then
    if s!="" then
     set word=" "+word
     set lwd=lwd+1
    else
     set word=color+word
    endif
    if lwd+lst>Amount then
     set udg_PartStr[Index]=s
     set Index=Index+1
     set udg_PartStr[Index]=color+word
     set Index=Index+1
    else
     set udg_PartStr[Index]=s+word
     set Index=Index+1
    endif
    set s=""
    set word=""
    set lwd=0
    set lst=0
    set i=i+1
    set find=false
   endif
  else
   if find and (mark==" " or mark=="") then
    if SubString(Str,i-1,i)==" " then
     if lst+1+lwd>Amount then
      if s=="" then
       if inW>0 then
        set udg_PartStr[Index]=SubString(color,0,10*tags-inW*10)+word
        set inW=0
       else
        set udg_PartStr[Index]=color+word
       endif
       set Index=Index+1
      else
       set udg_PartStr[Index]=s
       set Index=Index+1
       if inW>0 then
        set s=SubString(color,0,10*tags-inW*10)+word
        set inW=0
       else
        set s=color+word
       endif
       set lst=lwd
      endif
     else
      set inW=0
      if s!="" then
       set s=s+" "+word
       set lst=lst+1
      else
       set s=color+word
       set lst=lwd
      endif
     endif
     set word=""
     set lwd=0
     set find=false
    else
     if s!="" then
      if lst+1+lwd>Amount then
       set udg_PartStr[Index]=s
       set Index=Index+1
       set udg_PartStr[Index]=color+word
      else
       set udg_PartStr[Index]=s+" "+word
      endif
     else
      set udg_PartStr[Index]=color+word
     endif
     set end=true
    endif
    if clear>0 then
     if tags>1 then
      set color=SubString(color,0,tags*10-clear*10+1)
      set tags=tags-1
     else
      set color=""
      set tags=0
     endif
     set clear=0
    endif
   else
    if mark==" " then
     if lst+1>Amount then
      set udg_PartStr[Index]=s
      set Index=Index+1
      set s=""
      set lst=0
     endif
     set s=s+" "
     set lst=lst+1
    elseif mark=="" then
     set udg_PartStr[Index]=s
     set end=true
    else
     if not find then
      set find=true
     endif
     set word=word+mark
     set lwd=lwd+1
    endif
   endif
  endif
 endloop
 return Index
endfunction

Отредактировано MrSmiLe, 02.07.2007 в 10:48.
Старый 02.07.2007, 02:51
dk

offline
Опыт: 60,293
Активность:
ну когда делишь на 100 все работает правильно... Просто вар имеет свою встроенную функцию переноса которая и переносит, а вот с 10 не работает, ну и понятно нех задавать промежуток меньше максимальной длины слова, хотя впринципи можно было и предусмотреть это...
Старый 02.07.2007, 08:49
YasonDelAlt

offline
Опыт: 862
Активность:
Jon
Код я свой писал не проверяя (вара у меня под рукой нету, да и компа тоже), на счет кавычек это ты верно подметил, привычка, что поделать, сейчас больше пишу на С-образных языках. На счет неточного разбиения: кажется я сравнение перепутал:
Код:
if logicBlockSize >= Amount then

Нужно заменить на:
Код:
if logicBlockSize > Amount then

и должно заработать.


Этот "конкурс" я выйграть не смогу (отлаживать код не на чем), а вот другим постараюсь помочь.

Значит так, над кирилицей особо не партесь, потом отлаженную функцию легко можно будет перевести на русский с помощью моей библиотеки (сомореклама ;) см. выше). Перенос вложенных тегов можно легко реализовать с помощью стека (надеюсь все знают что это такое), сам стек создается с помощью локального массива строк и переменной счетчика. Во время парсинга строки, если напарываемся на цветовой тег, то запихиваем цветовую составляющую в стек, если напоролись на конечный тег ("|R"), то вытаскиваем из стека элемент, если пришло время сбрасывать строку в массив, смотрим есть ли что-нибудь в стеке, если есть, то обрамляем строку в тег, иначе сбразываем в массив чистую стоку без тега.

Обработку тега "|N" добавить проще простого: берем кусок, где обрабатывается тег "|R", копируем его, вставляем рядом и заменяем "r" на "n" и все!

Медетируйте! :)

Jon,
что-то я запамятовал, функция StringCase обрабатывает кирилицу или нужно шаманить над аналогом в библиотеку?

MrSmiLe,
у тебя жутко не оптимизированный код, чего только стоит куча бесполезных вызовов SubString в цикле. Куда лучше выделить отдельную переменную и в начале цикла запихивать в нее отдельный символ, а после уже сравнивать с этой переменной. Будет быстрее работать в несколько раз, да и выглядить будет лучше, нагляднее.
Старый 02.07.2007, 09:09
Закрытая тема

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы можете скачивать файлы

BB-коды Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход



Часовой пояс GMT +3, время: 07:22.