Посимвольный перебор строки.

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Посимвольный перебор строки.

Сообщение kotompazb » 16.06.2013 21:01:26

В общем, задача такая. Есть текстовый файл в unicode. Необходимо открыв его найти все кириллические слова/фразы.
Делаю так.
Код: Выделить всё
const
  Cyrillic='АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯабвгдеёжзийклмнопрстуфхцчшщьыъэюя';
 
//.....

    While Not EOF(SrcFile) do
    begin
      ReadLn(SrcFile,SrcString);
      j:=1;
      while j <= Length(SrcString) do
      begin
        if Pos(SrcString[j],Cyrillic)<>0 then
        begin
          FormAdd.EditCtxt.Caption:=SrcString;
          SubString:=SrcString[j..Length(SrcString)];
          FormAdd.EditFind.Caption:=SubString;
          FormAdd.ShowModal;
          j:=j+FormAdd.EditFind.SelLength;
        end;
      j:=j+1;
      end;
    end;

Логика такая. Находим кириллический символ. Копируем, начиная с него и до конца, строку в Edit. В нем выделяем участок нужной длины. Обрабатываем строку дальше, пропуская выделенный участок.

То есть, допустим, есть строка 'Congratulation=Поздравляю с праздником'
Код находит 'П'. Копирует в Edit строку 'Поздравляю с праздником'
Выделяем, например, 'Поздравляю'.
Пропуская этот участок, должны вроде получить 'с праздником'
Однако результат получается несколько неожиданным.
Получается что-то типа 'вляю с праздником'.

Я смутно догадываюсь о причине такого поведения. Но не совсем понимаю, как его побороть.
Аватара пользователя
kotompazb
постоялец
 
Сообщения: 153
Зарегистрирован: 21.06.2012 13:03:39
Откуда: Novosibirsk, xUSSR

Re: Посимвольный перебор строки.

Сообщение trexxet » 16.06.2013 23:26:27

Я уже не помню стандартные функции лазаря, все с библиотеками работаю :D
Посмотри тут http://www.ex.ua/view_storage/142319221199 (моя старая программа по работе с "базой данных"). В файле FormEditDb в процедуре TDbEditForm.SearchName выполняется перебор строки по символам, может это поможет тебе.
trexxet
новенький
 
Сообщения: 31
Зарегистрирован: 25.03.2013 22:58:00
Откуда: Смоленск

Re: Посимвольный перебор строки.

Сообщение SSerge » 17.06.2013 05:11:49

kotompazb писал(а):Логика такая


Логика в корне неправильная. В unicode utf-8 у вас нет такой единицы "кириллический символ", у вас есть только сегмент строки, являющийся лексемой utf-8.
Функции rtl freepascal также работают не с символами, кои они определять не умеют, а с байтовым представлением строки.

Читаем Первоисточник: http://wiki.freepascal.org/LCL_Unicode_Support/ru

Если там непонятно, то вот еще: http://sirserge.altai.info/articles/?id=41
SSerge
энтузиаст
 
Сообщения: 971
Зарегистрирован: 12.01.2012 05:34:14
Откуда: Барнаул

Re: Посимвольный перебор строки.

Сообщение kotompazb » 17.06.2013 21:10:29

Разобрался.
Имел в виду подобное решение:
Код: Выделить всё
const
  Cyrillic='АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯабвгдеёжзийклмнопрстуфхцчшщьыъэюя';
 
//.....

    While Not EOF(SrcFile) do
    begin
      ReadLn(SrcFile,SrcString);
      SrcString:=Utf8ToSys(SrcString);
      j:=1;
      while j <= Length(SrcString) do
      begin
        if Pos(SrcString[j],Utf8ToSys(Cyrillic))<>0 then
        begin
          FormAdd.EditCtxt.Caption:=SysToUtf8(SrcString);
          SubString:=SrcString[j..Length(SrcString)];
          FormAdd.EditFind.Caption:=SysToUtf8(SubString);
          FormAdd.ShowModal;
          j:=j+FormAdd.EditFind.SelLength-1;
        end;
      j:=j+1;
      end;

    end;         
Аватара пользователя
kotompazb
постоялец
 
Сообщения: 153
Зарегистрирован: 21.06.2012 13:03:39
Откуда: Novosibirsk, xUSSR

Re: Посимвольный перебор строки.

Сообщение SSerge » 18.06.2013 04:43:27

kotompazb писал(а):Разобрался.


Не, не разобрался.

У вас на каждой строке конверсия между utf8 и системной кодовой страницей, что в некоторых случаях будет искажать информацию, а функции применяете опять же байтовые.

тогда уж:

Код: Выделить всё
const
  Cyrillic='АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯабвгдеёжзийклмнопрстуфхцчшщьыъэюя';

//.....

    While Not EOF(SrcFile) do
    begin
      ReadLn(SrcFile,SrcString);
      j:=1;
      while j <= Utf8Length(SrcString) do
      begin
        if Pos(Utf8Copy(SrcString,j,1),Cyrillic)<>0 then
        begin
          FormAdd.EditCtxt.Caption:=SrcString;
          SubString:=Utf8Copy(SrcString,j,Utf8Length(SrcString)-j+1);
          FormAdd.EditFind.Caption:=SubString;
          FormAdd.ShowModal;
          j:=j+FormAdd.EditFind.SelLength-1;   // вот это тоже сомнительно, но лениво выяснять
        end;
      j:=j+1;
      end;

    end;       
SSerge
энтузиаст
 
Сообщения: 971
Зарегистрирован: 12.01.2012 05:34:14
Откуда: Барнаул

Re: Посимвольный перебор строки.

Сообщение kotompazb » 18.06.2013 07:37:12

SSerge писал(а):У вас на каждой строке конверсия между utf8 и системной кодовой страницей, что в некоторых случаях будет искажать информацию

Вы имеете в виду случай, когда utf8-строка содержит символы, которых нет в системной кодовой странице? Это в моем случае не важно. Но все равно спасибо, так как ваше замечание позволит мне избежать ошибки немного в другом месте :)

SSerge писал(а):а функции применяете опять же байтовые

Системная кодовая страница у меня именно "однобайтная" (то, что сейчас мной пишется, предназначено for inside using only).

В любом случае сейчас мой код делает именно то, что мне нужно, и именно так, как мне это нужно. Однако, ваш вариант тоже попробую. Правда, по поводу этого
SSerge писал(а):
Код: Выделить всё
j:=j+FormAdd.EditFind.SelLength-1;   // вот это тоже сомнительно, но лениво выяснять
у меня тоже сомнения.
Аватара пользователя
kotompazb
постоялец
 
Сообщения: 153
Зарегистрирован: 21.06.2012 13:03:39
Откуда: Novosibirsk, xUSSR


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 262

Рейтинг@Mail.ru