Вверх ↑
Этот топик читают: Гость
Ответов: 537
Рейтинг: 14
#406: 2019-11-18 18:47:45 ЛС | профиль | цитата
Да, стоял английский язык для программ, изменил на иврит, теперь все хорошо. Спасибо.
карма: 4

0
Ответов: 17
Рейтинг: 0
#407: 2019-12-31 03:18:37 ЛС | профиль | цитата
С наступающим годом!
При использовании компонента Mask, во всех новый компиляторах "Delphi, FPC-xx" не производится сравнение части строки и последующей (*) звёздочки. см. пример.
Проверил на стандартных компиляторах всё работает.


Add(MainForm,2953706,21,105)
{
}
Add(Edit,14729050,70,105)
{
Left=10
Top=5
Text="Ed*"
}
Add(Edit,15909518,140,105)
{
Left=85
Top=5
}
Add(Button,16659015,21,154)
{
Left=10
Top=35
Caption="Mask"
link(onClick,7370736:doData,[])
}
Add(Button,10948459,21,63)
{
Left=85
Top=35
Caption="Compare"
link(onClick,15627684:doCompare,[(110,69)(110,153)])
}
Add(LED,4053424,189,140)
{
Left=160
Top=15
}
Add(DoData,7370736,70,154)
{
link(onEventData,15627684:doMask,[])
link(Data,14729050:Text,[])
}
Add(StrMask,15627684,140,147)
{
Point(doMask)
link(onFalse,4053424:doOff,[])
link(onTrue,4053424:doOn,[])
link(Str,15909518:Text,[])
}

карма: 0

0
Ответов: 4621
Рейтинг: 746
#408: 2019-12-31 20:36:25 ЛС | профиль | цитата
Да, есть такое.
Для исправления строка 33 файла hiStrMask.pas должна выглядеть так:
if (PChar(Msk + 1)^ = #0) or _StrCmp(Str, Msk + 1) then

Сообщите, если будут другие ошибки.

Редактировалось 1 раз(а), последний 2019-12-31 20:36:53
карма: 26

0
Ответов: 9906
Рейтинг: 351
#409: 2020-01-01 18:15:33 ЛС | профиль | цитата
Netspirit писал(а):
if (PChar(Msk + 1)^ = #0) or _StrCmp(Str, Msk + 1) then


Хм........
Многое я забыл, конечно же.
Однако, nesco, я тебе один умный вещь скажу: возможно, что Netspirit -- таки прав.

Его код (в FPC2) отличается от нашего (пакет Delphi) прежде всего тем, что он не захотел ставить в хвост Строке и Маске по дополнительному символу (у нас это #1).
За что и выхватил, конечно же.
НО: вроде бы и исправил.



Отсюда предложение: давай и мы сделаем аналогично. Все таки, добавлять в хвосты какой-то непонятный #1 - не самое красивое решение.
Да и тестеров у нас побольше (а то он еще два года тестировать будет)....


--- Добавлено в 2020-01-01 18:52:56

Хотя фигушки
Netspirit не поймал еще один глюк: при маске типа Ed??** в вышеприведенной схеме

Netspirit, попробуй как у меня
Может тоже что найдешь.... Говорю же - давно все это было, и позабылось кое чего.

Редактировалось 9 раз(а), последний 2020-01-03 22:39:03
карма: 9

0
Ответов: 9906
Рейтинг: 351
#410: 2020-01-01 19:36:12 ЛС | профиль | цитата
Ах, да
С НОВЫМ ГОДОМ ВСЕХ

Редактировалось 1 раз(а), последний 2020-01-01 19:39:58
карма: 9

1
Голосовали:UtoECat
Разработчик
Ответов: 26066
Рейтинг: 2120
#411: 2020-01-01 21:30:40 ЛС | профиль | цитата
Galkov писал(а):
Отсюда предложение: давай и мы сделаем аналогично

Только после праздников смогу добавить.
карма: 22

0
Ответов: 9906
Рейтинг: 351
#412: 2020-01-01 22:39:26 ЛС | профиль | цитата
Дык спешить то и не надо....
Сперва послушаем начальника транспортного цеха - он же о чем-то думал, когда шел наперекор "тестированному"
Netspirit тоже, вроде бы только "по будням" активизируется (типа - с работы).
А деваться-то ему и некуда, ибо его фикс не работает.

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

Редактировалось 1 раз(а), последний 2020-01-01 22:40:23
карма: 9

0
Ответов: 4621
Рейтинг: 746
#413: 2020-01-02 12:10:06 ЛС | профиль | цитата
Galkov писал(а):
что он не захотел ставить в хвост Строке и Маске по дополнительному символу
БИНГО!

Galkov писал(а):
Netspirit тоже, вроде бы только "по будням" активизируется (типа - с работы).
Точно.

Galkov писал(а):
А деваться-то ему и некуда, ибо его фикс не работает.
Ага. Я подозревал что там ещё не всё, так как в голове не сложилась полная картина алгоритма этой функции. Но не смог подобрать неработающую комбинацию (видимо, по причине праздничного настроения ).

Буду думать.

--- Добавлено в 2020-01-02 12:49:31

Вариант от Galkov работает. Думаю, можно использовать, пока кто-то не предложит неработающую маску.

Galkov писал(а):
добавление символа "в хвосты" автоматически снимало вопросы уникальности строки. У меня уже есть как бы фиксинг и к этому делу...
В предложенном коде? Не увидел. И на пустой маске и строке падает:
Add(MainForm,12868012,210,133)
{
Position=1
}
Add(Edit,14729050,427,231)
{
Left=10
Top=5
Width=75
Text="Ed*"
}
Add(Edit,15909518,420,133)
{
Left=110
Top=5
Width=95
}
Add(Button,10948459,308,168)
{
Left=110
Top=35
Caption="Compare"
link(onClick,15424608:doEvent1,[])
}
Add(LED,4053424,609,217)
{
Left=230
Top=15
}
Add(DoData,7370736,427,280)
{
link(onEventData,15627684:doMask,[(512,286)(512,237)])
link(Data,14729050:Text,[])
}
Add(StrMask,15627684,560,224)
{
Point(doMask)
link(onFalse,4053424:doOff,[])
link(onTrue,4053424:doOn,[])
}
Add(ListBox,1658272,595,126)
{
Left=10
Top=85
Width=205
Height=155
}
Add(Hub,4695875,469,175)
{
OutCount=3
link(onEvent1,8948855:doEvent1,[(523,181)(523,132)])
link(onEvent2,15627684:doCompare,[(514,188)(514,230)])
link(onEvent3,8948855:doEvent2,[(533,195)(533,139)])
}
Add(Hub,8948855,546,126)
{
InCount=2
OutCount=1
link(onEvent1,1658272:doAdd,[])
}
Add(DoData,12636045,420,175)
{
link(onEventData,4695875:doEvent1,[])
link(Data,15909518:Text,[])
}
Add(Hub,15424608,357,168)
{
link(onEvent1,7370736:doData,[(399,174)(399,286)])
link(onEvent2,12636045:doData,[])
}
Так что уникализация требуется. Но не добавлением символов, естественно (StrCase в этом плане жжот ).

Редактировалось 13 раз(а), последний 2020-01-02 13:20:56
карма: 26

0
Ответов: 9906
Рейтинг: 351
#414: 2020-01-02 15:49:03 ЛС | профиль | цитата
Netspirit писал(а):
Но не добавлением символов, естественно

Для кого естественно, а для кого и не очень. Когда-то было
Коллега, побольше слов, пожалуйста. Хотелось бы убийственного аргумента в этом направлении.
Чтобы душа развернулась, а потом обратно свернулась

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

Netspirit писал(а):
(StrCase в этом плане жжот )

Это CharLower жжот. Вот такое есть winapi... Наступал я уже на эти грабли где-то, но позабыл. Пришлось вспомнить: нормально работает CharLower(pointer(String)), а не PChar.

Netspirit писал(а):
В предложенном коде? Не увидел

Не, не в ранее предложенном....
До меня ведь тоже не все сразу после праздника доходит.
Выкладываю пофиксенную версию (в INI изменен порядок свойств, чтобы при инициализации Mask было известно: он CaseSesinive, или нет).

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

Редактировалось 5 раз(а), последний 2020-01-02 15:54:49
карма: 9

0
Ответов: 4621
Рейтинг: 746
#415: 2020-01-02 16:12:37 ЛС | профиль | цитата
Не, ну к CharLower() никаких претензий нет: она то работает так как написано в документации.
Galkov писал(а):
нормально работает CharLower(pointer(String)), а не PChar
В данном случае не поможет, так как все равно не приводит к копированию строки (по-моему). Упадёт, например, на константе, как и PChar(). А вот CharLower(@S[1]) может и проканает: доступ по индексу, вроде, копирует строку. В Delphi, но не в FPC, или не во всех случаях. UniqueString() - наше всё.
(Galkov имел в виду пустую строку и CharLower(), а не её уникальность)

К последнему выложенному варианту не имею вопросов (кроме как к форматированию кода, ну, и названия функций, обычно, должны отражать действие, то-есть, SetMask(), а не просто Mask()).

Редактировалось 7 раз(а), последний 2020-01-02 16:29:42
карма: 26

0
Ответов: 9906
Рейтинг: 351
#416: 2020-01-02 22:36:29 ЛС | профиль | цитата
Netspirit писал(а):
Не, ну к CharLower() никаких претензий нет:

Как бы это помягче сказать...
Скажем так: Если бы она не падала, при попытке модифицировать пустую строку (т.е., когда не надо делать ничего), то я бы сказал, что она работает так как написано в документации.

Netspirit писал(а):
Упадёт, например, на константе, как и PChar()

Не совсем понял: ты имеешь в виду исключения при попытке модификации в кодовом сегменте, защищенном от записи ???
Так не помню я у нас таких строк... А падала она на пустой строке (повторюсь: когда не надо делать ничего).
И что точно можно сказать, что даже константная строка (у которой RefCnt=-1) после UniqueString попадает в хип, т.е. в сегмент памяти разрешенный на запись.

Netspirit писал(а):
А вот CharLower(@S[1]) может и проканает

Вспомнил, было такое:
procedure THIFileSearch.OutFiles;
var fn:string; i:integer;
begin
fn := Name; {$ifdef F_P}UniqueString(fn);{$endif} CharLower(@fn[1]);
.............
И все как ты сказал: Delphi воспринимает сие как вмешательство в строку и автоматом уникализирует ее, а FPC - фигушки.
Самолично проверял дизасмом: чего это за фигня, думаю себе - два раза подряд вызывается UniqueString, я же один раз писал.
Хотя уникализация уже уникальной строки не делает ничего (в смысле - не заморачивается с хипом). В отличие, между прочим, от AnsiLowerCase. И в котором, не к ночи будет сказано, вызов winapi таки защищается от пустой строки.
Причем, что занимательно: использование @fn[1] воспринимается как вмешательство в строку, а использование pointer(fn) - не воспринимается.
Велик и могуч буржуинский интеллект, однако

Netspirit писал(а):
кроме как к форматированию кода, ну, и названия функций, обычно, должны отражать действие, то-есть, SetMask(), а не просто Mask()

Про SetMask согласен сразу, это была просто неистребимая природная лень в написании тех буковок.

А про форматирование - не соглашусь.
Вопрос не принципиальный, и агитировать никого не буду, но мне ближе Обероновский стиль.
На котором это выглядело бы примерно так (на вскидку, в спецификации давно не лазил):
  WHILE (Str^<>#0)and(Msk^<>#0) DO
IF Msk^ = '*' THEN
Result := _StrCmp(Str,Msk+1);
IF Result THEN EXIT;
ENDIF;
ELSEIF Msk^ = '#' THEN
IF Str^ IN ['0'..'9'] THEN INC(Msk);
ELSE BREAK;
ENDIF;
ELSEIF (Msk^ = '?')OR(Msk^ = Str^) THEN INC(Msk);
ELSE BREAK;
ENDIF;
INC(Str);
ENDWHILE;
WHILE Msk^ = '*' DO INC(Msk);
ENDWHILE;
Result := (Str^ = #0)AND(Msk^ = #0);
Ну нет там begin-ов, потому нет вопроса, на какой строке его моднее ставить. Ну я и ставлю его как бы типа не очень заметно.
А отсутствие в языке elseif-а не вынуждает меня строить лесенки...
Нет, ну конечно, совсем канонически было БЫ после служебных слов THEN ELSE DO - начинать новый statement с новой строки с отступом.
Но, отнесем это к совсем уж мелкой вредности... Типа, если statement всего один, то можно и нахулиганить. Самую малость.
Вообще-то, я комбинацию end else if воспринимаю (но никому не навязываюсь) как единый и целый elseif.
А лесенки при форматировании - только запутывают. Обероновцы, они вообще на цикл Дейкстры молятся. Который позволяет много-вложенный цикл писать не лесенкой, а на одном отступе.
Но, повторюсь: никому не навязываюсь.
Просто немного не соглашусь

Редактировалось 8 раз(а), последний 2020-01-02 23:24:28
карма: 9

0
Ответов: 9906
Рейтинг: 351
#417: 2020-01-03 00:30:50 ЛС | профиль | цитата
Вообще-то, стиль выравнивания вещь сугубо индивидуальная. Лишь бы система была законченная и непротиворечивая.
Чего здесь главное, спрашивается...
А вот глядишь ты на этот код, и как-то это отражается на твоей мозговой деятельности.
По разному написано, по разному и отражается.
Вот посмотрел я на обероновский код выше, посмотрел, посмотрел -- и подумал себе: а может вот эдак красивше будет ???
function _StrCmp(Str,Msk:PChar):boolean;
begin
while (Str^<>#0)and(Msk^<>#0) do begin
if Msk^ = '*' then begin
Result := _StrCmp(Str,Msk+1);
if Result then exit;
end else begin
if Msk^='#' then Result := Str^in['0'..'9']
else Result := (Msk^='?')or(Msk^=Str^);
if Result then Inc(Msk)
else exit;
end;
Inc(Str);
end;
while Msk^ = '*' do inc(Msk);
Result := (Str^ = #0)and(Msk^ = #0);
end;
Вот у меня так... Не виноватый я

Редактировалось 10 раз(а), последний 2020-01-03 02:12:04
карма: 9

0
Ответов: 4621
Рейтинг: 746
#418: 2020-01-03 12:15:28 ЛС | профиль | цитата
Galkov писал(а):
ты имеешь в виду исключения при попытке модификации в кодовом сегменте, защищенном от записи ???Так не помню я у нас таких строк...

"Кодовый сегмент" - это, насколько я понимаю у нас получается разве что в CharLower(PChar(S)), когда при пустой S Delphi приведением к PChar() подставляет ссылку на байт $00, лежащий где-то там же в коде функции рядом с проверкой строки на пустоту. А CharLower() с какого-то чуда, видимо, пытается этот 0 "ловернуть", хотя по достижении 0 должен был выйти из цикла перебора символов.

Но есть ещё секция констант "только для чтения" в исполняемом файле, где лежат строковые константы. Причём они остаются лежать там даже после множества присвоений переменным и передачи как аргументов функций. До применения UniqueString() или других методов копирования.
Add(MainForm,2953706,21,105)
{
Position=1
}
Add(Button,10504036,168,105)
{
Left=170
Top=40
link(onClick,11970995:doWork,[])
}
Add(InlineCode,11970995,252,105)
{
WorkPoints=#6:doWork|
EventPoints=#8:onResult|
VarPoints=#4:Var1|4:Var2|
DataPoints=#5:Data1|5:Data2|
Code=#15:unit HiAsmUnit;|0:|9:interface|0:|4:uses|29: Windows, KOL, Share, Debug;|0:|4:type|29: THiAsmClass = class(TDebug)|11: private|0:|10: public|30: Data1, Data2: THI_Event;|29: onResult: THI_Event; |54: procedure doWork(var _Data: TData; Index: Word);|52: procedure Var1(var _Data: TData; Index: Word);|52: procedure Var2(var _Data: TData; Index: Word);|6: end;|0:|14:implementation|0:|5:const|19: STRCONST = 'AAA';|0:|0:|0:|60:procedure THiAsmClass.doWork(var _Data: TData; Index: Word);|3:var|13: S: string; |5:begin|16: S := STRCONST;|34: CharLower(Pointer(S)); // Падает|29: CharLower('BBB'); // Падает|4:end;|0:|0:|59:procedure THiAsmClass.Var1(var _Data: TData; Index: Word); |5:begin|22: dtInteger(_Data, 0);|4:end;|0:|59:procedure THiAsmClass.Var2(var _Data: TData; Index: Word); |5:begin|22: dtString(_Data, '');|4:end;|0:|4:end.|
}
Тут есть такой любопытный нюанс. Такие константы существовали бы у нас повсюду, где мы задаём строковые свойства по-умолчанию компонентов. Но в кодогенераторе стоит костыль при заполнении строковых свойств:
_prop_Name := PChar('XXX'#0);
Это делает строки в свойствах компонентов модифицируемыми. Но не защищает от возможности получить константу из какого-то другого места. Мне не понравилось, поэтому в данной редакции пакета я это убрал. Кроме того, это не позволяет использовать символ с кодом #0 в строковых свойствах.

Galkov писал(а):
а использование pointer(fn) - не воспринимается.
К счастью. Нужно иметь возможность получить указатель на строку без дельфийского самоуправства.

По форматированию - кроме отступов нужно учитывать ещё регистр идентификаторов, и некоторые правила вроде префиксов "T" для типов, "P" для ссылочных типов, "F" для приватных полей класса.
Скажем, я бы предпочел
function _StrCmp(Str, Msk: PChar): Boolean;
begin
while (Str^ <> #0) and (Msk^ <> #0) do
begin
if Msk^ = '*' then
begin
Result := _StrCmp(Str, Msk + 1);
if Result then Exit;
end
else
if Msk^ = '#' then
begin
if Str^ in ['0'..'9'] then Inc(Msk)
else Break;
end
else
if (Msk^ = '?') or (Msk^ = Str^) then Inc(Msk)
else Break;
Inc(Str);
end;

while Msk^ = '*' do Inc(Msk);

Result := (Str^ = #0) and (Msk^ = #0);
end;

Редактировалось 7 раз(а), последний 2020-05-26 16:50:33
карма: 26

0
Ответов: 9906
Рейтинг: 351
#419: 2020-01-03 15:04:35 ЛС | профиль | цитата
Netspirit писал(а):
Но есть ещё секция констант "только для чтения" в исполняемом файле

Да понятно все. Твой пример убедителен, хотя и не удивил аж нисколько.

Netspirit писал(а):
Но в кодогенераторе стоит костыль

Его не так просто убрать... Мне это тоже не нравилось, но в то время я не решался так глубоко лезть в наши системные файлы.
Да и не все я решал.
Во-первых, принудительное добавление нулика в хвост - это один из способов уговорить Delphi что это таки строка а не символ, для односимвольной строки.
Во-вторых, если текст длиннее 255 символов, то Delphi огорчается, и не хочет компилировать. В этом случае таковая строка помещается в соответствующую секцию ресурса, откуда возвращается только как PChar. Т.е, опять облом с нулевым символом.
Надо, видимо, помещать в ресурс также, как и Stream, с соответствующим извлечением (а это функции из share). И найти таки вариант записи для односимвольной строки.
Ну не смогла я В то время...
В общем, не все так просто.

Netspirit писал(а):
"F" для приватных полей класса

Да запросто
Замена Mask на SetMask добавила 12 символов код. Замена intMask на FMask - вернет обратно 10

Netspirit писал(а):
Скажем, я бы предпочел

А вот смотри сюда:

function _StrCmp(Str, Msk: PChar): Boolean;
begin
while (Str^ <> #0) and (Msk^ <> #0) do
begin
if Msk^ = '*' then
begin //Statement-1
Result := _StrCmp(Str, Msk + 1);
if Result then Exit;
end
else if Msk^ = '#' then
begin //Statement-2
if Str^ in ['0'..'9'] then Inc(Msk)
else Break;
end
else if (Msk^ = '?') or (Msk^ = Str^) then
//Statement-3
Inc(Msk)
else
//Statement-4
Break;
Inc(Str);
end;

while Msk^ = '*' do Inc(Msk);

Result := (Str^ = #0) and (Msk^ = #0);
end;
Модифицировал твой код самым минимальным образом (старался, между прочим).
И у меня все Statement-ы имеют одинаковый отступ.
А у тебя каждый последующий все глубже и глубже. Ну хорошо, что их всего 4... А если бы 20 ???
Вот это я и называю "лесенкой", особого семантического смысла не имеющего.
Такая комбинация ELSEIF-ов (если их записать раздельно, как else if - смысл-то от этого не меняется) - это же просто как супер-навороченный CASE.
Нас же не оскорбляет, что все его ветки на одном уровне отступа. Почему же здесь мы должны обижаться...
Netspirit, я не спорю, у тебя все канонически правильно. Просто пойми, что в мой подход тоже системен и логичен.
Вот и все.

Хм... А есть еще особо тонкие ценители отступов. Так они еще на один отступ смещают BEGIN-END, а то, что внутри - тоже на один (как у тебя).
Не, ну действительно, почему это последний BREAK с отступом, а первый BEGIN - нет... Чем это он хуже BREAK-а
Вот я не хочу спорить с этим народом, и располагаю этот BEGIN на другой строке.

Но это все так... Размышления о прекрасном. Не более того.




Да, вот. Netspirit, ты ничего не сказал про мой код из предыдущего поста. Функционально эквивалентный, как мне пока кажется, тому, что мы обсуждаем.
Там, между прочим, нет ELSEIF-ов
Вместо одного EXIT-а и двух BREAK-ов -- два EXIT-а. Что уже легче.
Да и BREAK-и были нацелены на то, что в результате некой оконечной суеты таки произойдет выход с обязательным FALSE.
Теперь тот же выход, но без суеты.

А то придет nesco после праздника, и строго спросит: так на чем же вы все-таки договорились ???
Я его знаю
карма: 9

0
Ответов: 4621
Рейтинг: 746
#420: 2020-01-03 15:56:00 ЛС | профиль | цитата
Galkov писал(а):
Во-первых, принудительное добавление нулика в хвост - это один из способов уговорить Delphi что это таки строка а не символ, для односимвольной строки.
А вот тут мне не очень понятно чем "односимвольная строка" отличается от остальных. Не, я знаю в чём разница между типами Char и string, но на уровне кода с этим никогда проблем не было. Как минимум присвоение Char -> string, 'A' -> string происходит незаметно. Если у нас свойства типа string - то зачем нам ещё беспокоиться добавлять туда 0? Делфи и так все string гарантирует с конечным 0.

Galkov писал(а):
В этом случае таковая строка помещается в соответствующую секцию ресурса, откуда возвращается только как PChar.
А свойства у нас типа string - все равно PChar неявно сканируется на наличие ограничивающего 0, затем из этого конструируется тот же string и присваивается свойству. Поэтому в моем пакете в Share она сразу возвращается как string. А ещё она знает с какой системной кодировкой она помещалась в ресурсы, чтобы в юникодном режиме отображалась на всех системах корректно (поскольку HiAsm и кодогенератор в ресурсы пишет строку в кодировке системы).

Galkov писал(а):
И найти таки вариант записи для односимвольной строки.
Все равно не понимаю сути проблемы...

Galkov писал(а):
ты ничего не сказал про мой код из предыдущего поста
Я смотрел только на оформление, поэтому если функционал тот же - не имею чего возразить.

Galkov писал(а):
Вот это я и называю "лесенкой", особого семантического смысла не имеющего.
Так тут вопрос, так сказать, в "эстетической составляющей", то есть, удобство восприятия. А это дело привычки, которые у каждого свои. Поэтому не готов настаивать. Просто выбрал для себя "канонически правильно", согласно гайдам и кодам в том же VCL или других приличных местах.
Главное чтобы было "системно", а не кто в лес, кто по дрова, чего можно насмотреться по кодам наших компонентов.

Galkov писал(а):
Я его знаю
Да, тоже не сомневаюсь.

Редактировалось 1 раз(а), последний 2020-01-03 15:57:23
карма: 26

0
Сообщение
...
Прикрепленные файлы
(файлы не залиты)