ТОМ2 - платформа для парсерных игр

Объявление

Открыт сайт tom2-game.ru.


Последнюю версию платформы можно скачать здесь.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.



Как работать со строками?

Сообщений 1 страница 10 из 10

1

Не нашёл в документации функции расширенной работы со строками. Пытался разобраться методом тыка, удалось найти только .len, который определяет длину строки. Как копировать часть строки, удалить несколько символов внутри строки, вклинить одну строку в другую, элементарно получить доступ к отдельным символам строки... всё это мне так и не удалось сделать. Я уже не говорю о таких вкусностях как UpCase и DownCase.
Нельзя ли узнать хотя-бы список функций работы со строками? Или перечисленные мной действия со строками пока не реализованы в ТОМе?

И ещё, можно ли производить операции ">", "<" и подобные над отдельными символами?

2

Функций для работы со строками действительно мало:
  left()
  right()
  mid()
  lower()
  upper()
  trim()

это всё что есть...

3

Alexandr написал(а):

можно ли производить операции ">", "<" и подобные над отдельными символами?

Доступ к отдельному символу можно получить через mid()
Сравнение будет выглядеть как

Код:
  if(mid(Str1,25,1) > mid(Str2,25,1)) {...}
  if(mid(Str1,2,1) < mid(Str2,3,1)) {...}

4

Для тех, кого заинтересовала эта тема.
Великим и могучим народным методом тыка, а так же некоторой долей смекалки и знаний английского языка было установлено назначение каждой из перечисленных функций:
  left(Str, N) - извлекает N символов с начала строки Str
  right(Str, N) - извлекает N символов с конца строки Str
  mid(Str, P, N) - извлекает N символов, начиная с позиции P строки Str
  lower(Str) - переводит строку Str в нижний регистр
  upper(Str) - переводит строку Str в верхний регистр
  trim(Str) - удаляет пробелы с начала и конца строки Str
  Str.len - определяет длинну строки Str

Ещё было определено, что символы в строках нумеруются с единицы, как в Delphi, а не с нуля как в C.

Тестирование проводилось следующим кодом:

Код:
  var Str = "Тестовая строка"
  %<font color=yellow>_Тестирование функций работы со строками:</font>
  % Примеры на строке {Str}
  %left()
  %{left(Str, 3)}
  
  %_
  %right()
  %{right(Str, 3)}
  
  %_
  %mid()
  %{mid(Str, 3, 5)}
  
  %_
  %lower()
  %{lower(Str)}
  
  %_
  %upper()
  %{upper(Str)}
  
  %_
  %trim()
  %{trim("   Тримированная строка    ")}
  
  %_
  %Str.len
  %{Str.len}

5

Угу, всё верно  :D

6

Решил отвлечься от высокоуровневых команд и провести тестирование ТОМа на удобность низкоуровневой ("ручной") обработки строк.
Для тестирования была поставлена задача: создать функцию нормализации выходного текста на ТОМе. Реально прикрутить к нему я возможности не нашёл, но в качестве спортивного интереса всё-же решил сделать. Функция должна была убирать лишние пробелы, подставлять заглавные буквы в начале предложений и не трогать исключения ("и т.д.", "и др."). Задача поставлена. Поехали... (*подробности процесса не описываются, дабы избежать бана за не нормативную лексику*).
Результат: 3 часа убитого времени, 2 тонны потраченных нервов и всего 142 строчки кода (после вырезания всех временных проверок, подпорок и костылей)... я уже не говорю о бедной клавиатуре.
Так-же нельзя не упомянуть о жестоком но неоценимом опыте программирования в ограниченной среде функций.
Из этих трёх часов можно отдельно рассказать о часе, который был затрачен на поиск ошибки с заменой символов. Наверное, 1,5 тонны нервов я потратил на это. Я уж думал, что ТОМ надо мной издевается. Всё написано правильно, все вспомогательные функции протестированы отдельно - всё ок... а основная отказывается работать и выдаёт какую-то ерунду. Всё оказалось в подмене символа "^" на точку. %-) Так-что не пытайтесь проводить манипуляции с символами "^", "%" и подобными! Большинство операций с ними идут какими-то огородами и выдают совершенно не то, что вы ожидаете от них увидеть.
В общем все эти 142 строчки так и не начали работать так, как я хотел. Осталось довести ещё чуть-чуть и оно бы заработало, но оно уже начало так долго обрабатывать строку, что дальнейшая подкрутка могла бы похоронить функцию полностью. Да и основную задачу: проверить ТОМ в низкоуровневом деле, я считаю выполненной. (*Не надо объяснять, почему код работает так медленно. Я прекрасно понимаю, что ТОМ - интерпретатор, а не компилятор. И в этом его неоспоримый плюс*).
Пример работы итоговой функции:
" это плохо    написанная строка  , которая будет служить тестом. .  для нормализатора..     нормализатор убирает лишние пробелы  . . пустые предложения, но оставляет  исключения и т.д.    в общем... тест пройден! ура  "
переводится в
"Это плохо написанная строка, которая будет служить тестом. Для нормализатора. Нормализатор убирает лишние пробелы . Пустые предложения, но оставляет исключения и т.д. в общем... тест пройден! Ура."
Как видно, не убирается единственный пробел.

Ладно, от плохого к хорошему.
Не считайте всё вышенапечатанное камнем в огород ТОМа. ТОМ - хорошая платформа даже сейчас, когда она только на стадии разработки. Она оперирует высокоуровневыми данными, и справляется с этим очень даже хорошо. А то, что я написал выше - не минус, а даже плюс! То, что в платформе, ориентированной на автоматический парсинг текста в высокоуровневые структуры можно оперировать со строками на низком уровне (пускай сложно, но можно же!) - это тоже несомненный плюс.
Я не буду просить добавить функций для работы со строками: они не нужны ТОМу. И главная причина в ТОМ :) , что платформа будет поддерживать подключение сторонних библиотек (dll). А это - самое большое, о чём только можно мечтать. Как только эта система будет достаточно отлажена, никакие функции низкоуровнего программирования будут уже не так важны. Все трудоёмкие операции можно закодить в dll и плевали мы на то, что ТОМ - интерпретатор. Всё будет летать. Мощь интерпретатора + быстрота машинного кода = :cool:
В общем основной упор сейчас надо сделать на интеграцию плагинов (если их можно так назвать).

Кстати, вот то, что я накодил. Вдруг кому-то будет интересно:

Код:
// Определяет, является ли ch буквой
это_буква(ch)
{
  if( ((ch>mid("А", 1, 1))and(ch<mid("я", 1, 1)))or(ch==mid("ё", 1, 1))or(ch==mid("Ё", 1, 1))or
       (ch==mid("А", 1, 1))or(ch==mid("я", 1, 1))or
      ((ch>mid("A", 1, 1))and(ch<mid("Z", 1, 1)))or((ch>mid("a", 1, 1))and(ch<mid("z", 1, 1)))or
       (ch==mid("A", 1, 1))or(ch==mid("Z", 1, 1))or(ch==mid("a", 1, 1))or(ch==mid("z", 1, 1)) )
        return да
  else return нет
}

это_разделитель(ch)
{ если( ".!?"==ch)
    return да
    return нет
}

// Функцию UpCase надо встроить непосредственно в платформу. Это лишь заглушка для теста.
UpCase(ch)
{ if(ch=="э") return "Э"
  if(ch=="д") return "Д"
  if(ch=="к") return "К"
  return ch
}

global.исключения_точек[1] = "и т.д."
global.исключения_точек[2] = "и т.п."
global.исключения_точек[3] = "и др."
global.исключения_точек[4] = "..."
global.исключения_точек[5] = ""

// Вставляет в строку Str подстроку Pst в позицию N
Insert(Str, Pst, N)
{ return left(Str, N-1) + Pst + right(Str, Str.len - N + 1)
}

// Заменяет в строке Str символ с номером N на символ ch
rew(Str, N, ch)
{ var St
  St = left(Str, N-1)
  St = St + ch
  St = St + right(Str, Str.len - N)
  return St
}

Pos(Pst, Str)
// Ищет строку Pst в строке Str
{ var lns = Str.len
  var lnp = Pst.len
  for(var i=1; i<=lns-lnp+1; i++)
    { if(mid(Str, i, lnp)==Pst)
        return i
    }
  return 0
}

sam(Str, chto, na)
// Заменяет в строке Str символы chto на символы na
{ if(chto==na)
    return Str
  var Res = Str
  var n
  while(Pos(chto, Res)>0)
    { n = Pos(chto, Res)
      Res = rew(Res, n, na)
    }
  return Res
}


нормализация_предложения(предл)
// Нормализация отдельного предложения
{ // Чистка от пробелов
  var Str = trim(предл)
  var bo = false
  for(var i=1; i<=Str.len; i++)
    if(не это_разделитель(mid(Str, i, 1)))
      bo = true
  if(не bo)
    return ""
  // Лишние пробелы внутри предложения
  for(var i=Str.len-1; i>=1; i--)
    if((" "==mid(Str, i, 1))and(" ,:"==mid(Str, i+1, 1)))
      { Str = rew(Str, i, "")
	i++
      }
  // Заглавная буква в начале предложения
  for(var i=1; i<=Str.len; i++)
    {if(это_буква(mid(Str, i, 1)))
       return rew(Str, i, upper(mid(Str, i, 1)))
    }

  return Str
}

global.CorrectOutputString(Строка)
{ var Str = ""
  Строка = trim(Строка)
  // Поиск исключений
  var n
  var k = 0
  for (var i=1; исключения_точек[i]<>""; i++)  // Перебираем все исключения
    { k = 0
      while (Pos(исключения_точек[i], Строка)>0)
        { n = Pos(исключения_точек[i], Строка)
	  Строка = left(Строка, n-1) + sam(исключения_точек[i], ".", "*") + right(Строка, Строка.len - n + 1 - исключения_точек[i].len)
	  k++
	  if(k>10)
	    break
	}
    }
  // Делим на предложения
  var Res = ""
  var p = 1
  var n = 1
  Строка = Строка + "."
  for(var i=1; i<=Строка.len; i++)
    { if(это_разделитель(Строка[i]))
        { Str = mid(Строка, p, n)
	  Str = нормализация_предложения(Str)
	  if(Str)
	    Res = Res + Str + " "
	  Str = ""
	  n = 1
	  p = i+1
	}
      else
        n++;
    }
  // Меняем звёзды на точки2 
  Res = sam(Res, "*", ".")

  return trim(Res)
}

var ТестСтр = " это плохо    написанная строка  , которая будет служить тестом. .  для нормализатора..     нормализатор убирает лишние пробелы  . . пустые предложения, но оставляет  исключения и т.д.    в общем... тест пройден! ура  "

%<font color=yellow>_Тест нормализатора.</font>
%_____<font color=red>Не нормализованная строка:</font>
%{ТестСтр}
%_____<font color=green>Нормализованная строка:</font>
%{CorrectOutputString(ТестСтр)}

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

Ой, что-то я слишком увлёкся. Закругляюсь.

7

хм...

if( ((ch>mid("А", 1, 1))and(ch<mid("я", 1, 1)))or(ch==mid("ё", 1, 1))or(ch==mid("Ё", 1, 1))or
       (ch==mid("А", 1, 1))or(ch==mid("я", 1, 1))or
      ((ch>mid("A", 1, 1))and(ch<mid("Z", 1, 1)))or((ch>mid("a", 1, 1))and(ch<mid("z", 1, 1)))or
       (ch==mid("A", 1, 1))or(ch==mid("Z", 1, 1))or(ch==mid("a", 1, 1))or(ch==mid("z", 1, 1)) )

ch>mid("А", 1, 1) эквивалентно ch>"А"
скобки для логических операций не нужны, т.к. операция "and" приоритетнее "or"
ch>="А" - не работает!!! позор мне!!!

8

ASBer написал(а):

ch>="А" - не работает!!!

А то. С чего бы я тогда писал "(ch>mid("А", 1, 1))or(ch==mid("А", 1, 1))" :)

ASBer написал(а):

ch>mid("А", 1, 1) эквивалентно ch>"А"

т.к. вариант ch>="А" не сработал, то подумал, что дело в типах строка и символ (которого нету в ТОМе), вот и начал экспериментировать...

А вообще проще было алфавит перечислить. Короче получилось бы :D

Отредактировано Alexandr (2010-10-19 18:50:12)

9

Тип "символ" не существует - это простро строка длинной в один символ :D

10

ASBer написал(а):

Тип "символ" не существует

...в ТОМе. Почти во всех других языках тип символ существует отдельно. Вот и появились подозрение.