Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Поиск в строке 3ей запятой... [D6, Win95/98]


Michael C ©   (2002-02-12 10:27:00) 

Как осуществить, кто нить знает??? Я делал с помощью POS, но не получилось. А и ещё трабл, найти четвертую запятую и все что между ними COPY.
Народ выручайте... :(((


vuk   (2002-02-12 15:09:00) [1]

Ну и я тоже влезу. :o) Вот три функции - поиск слова с указания начальной позиции, выделения слова и подсчета количества слов.


function WordScan( const S : string; var StartPos, WordLen : integer; Delimiters : TSysCharSet ) : boolean;
var
i, l : integer;
begin
Result := false;
WordLen := 0;

i := StartPos;
l := length( s );
StartPos := 0;
while i <= l do
if s[i] in Delimiters then
inc(i)
else
begin
StartPos := i;
break;
end;

while i <= l do
if not(s[i] in Delimiters) then
begin
inc(i);
inc( WordLen );
end else
break;

Result := WordLen <> 0;
end;

function ExtractWord( const s : string; WordNumber : integer;
Delimiters : TSysCharSet ) : string;
var
wStart, wLen, n : integer;
begin
wStart := 1;
n := 0;
while WordScan( s, wStart, wLen, Delimiters ) do
begin
inc( n );
if n = WordNumber then
begin
Result := Copy( s, wStart, wLen );
exit;
end
else
inc( wStart, wLen );
end;
end;

function CountWords( const s : string; Delimiters : TSysCharSet ) : integer;
var
wStart, wLen : integer;

begin
Result := 0;
wStart := 1;

while WordScan( s, wStart, wLen, Delimiters ) do
begin
inc( Result );
inc( wStart, wLen );
end;
end;


McSimm   (2002-02-12 15:00:00) [2]

Не должна содержать пробелов, символов кавычек.
Для каких-то задач подойдет, но в общем случае - лучше через Text


oomneeq   (2002-02-12 13:57:00) [3]

2McSimm ©

Вместо
SL.Text := StringReplace(S, ",", #13#10,[rfReplaceAll]);
ecли заведомо нет пробелов
Проще писать
SL.CommaText := S;

Хотя не тестил, что из этого быстрее


Johnmen   (2002-02-12 13:48:00) [4]

кем (чем) ? :)


Romkin   (2002-02-12 12:53:00) [5]

а ты их считай, в цикле


Michael C   (2002-02-12 12:31:00) [6]

Народ, оказывается есть проблема!!!!
Строк в файле 15000!, как убедиться что они все до единой обрабатываются???


Michael C   (2002-02-12 11:44:00) [7]

Не сама строка, это 90 символов, но факт что строк таких эдак 500.


Romkin   (2002-02-12 11:32:00) [8]

Ну до кучи, если строка длинная (метров 15 хотя бы)

function TailPos(const S, SubStr: AnsiString; fromPos: integer): integer;
asm
PUSH EDI
PUSH ESI
PUSH EBX
PUSH EAX
OR EAX,EAX
JE @@2
OR EDX,EDX
JE @@2
DEC ECX
JS @@2

MOV EBX,[EAX-4]
SUB EBX,ECX
JLE @@2
SUB EBX,[EDX-4]
JL @@2
INC EBX

ADD EAX,ECX
MOV ECX,EBX
MOV EBX,[EDX-4]
DEC EBX
MOV EDI,EAX
@@1: MOV ESI,EDX
LODSB
REPNE SCASB
JNE @@2
MOV EAX,ECX
PUSH EDI
MOV ECX,EBX
REPE CMPSB
POP EDI
MOV ECX,EAX
JNE @@1
LEA EAX,[EDI-1]
POP EDX
SUB EAX,EDX
INC EAX
JMP @@3
@@2: POP EAX
XOR EAX,EAX
@@3: POP EBX
POP ESI
POP EDI
end;

function CommaN(const s: string; n: integer): integer;
var
i, APos: integer;
begin
APos := 0;
for i := 1 to n do
begin
APos := TailPos(s, ",", APos + 1);
if APos = 0 then break;
end;
Result := APos;
end;


При этом нарезки строки не производится, и выделения лишней памяти нет..


McSimm   (2002-02-12 11:26:00) [9]

типа как у Romkin © мой 1йвариант,
2йвариант пригодится, если надо получить весь список строк.

Никакой особой нагрузки на программу тут нет.
Вот хороший пример. Есть строка вида
"Key=123,ClassNo=5,Color=Red";
Чтобы получить значения по их имени, можно конечно написать парсинговую функцию, а можно так:
SL := TStringList.Create;
try
SL.Text := StringReplace(S, ",", #13#10,[rfReplaceAll]);
KeyStr := SL.Values["Key"];
ClassStr := SL.Values["ClassNo"];
ColorStr := SL.Values["Color"];
finally
SL.Free
end


IMHO, просто и изящно


Michael C   (2002-02-12 11:20:00) [10]

пасибо Народ, буду пробовать эти варианты,
Очень выручили....
Пасибо за асёмблер тоже, но ...


Johnmen   (2002-02-12 11:13:00) [11]

>McSimm © : Не стоит так грузить свою прогу из-за такой простой задачи !
Хороший вариант - это типа как у Romkin © !


Dimka Maslov   (2002-02-12 11:09:00) [12]

Str - строка
Ch - искомый символ
Entry - номер символа

для поиска третьей запятой - CharEntryPos(Str, ",", 3)

function CharEntryPos(const Str: string; Ch: Char; Entry: Integer): Integer; register;
asm
push edi
push esi
test eax, eax
jnz @@10
xor eax, eax
jmp @@50
@@10:
cmp ecx, 0
jnz @@20
xor eax, eax
jmp @@50
@@20:
mov edi, eax
dec edi
xor esi, esi
@@30:
inc edi
mov dh, [edi]
test dh, dh
jnz @@40
xor eax, eax
jmp @@50
@@40:
cmp dh, dl
jne @@30
inc esi
cmp esi, ecx
jne @@30
sub edi, eax
mov eax, edi
inc eax
@@50:
pop esi
pop edi
end;


McSimm   (2002-02-12 11:07:00) [13]

слова
>Могу предложить еще 2 варианта.
относятся к
>Michael C (12.02.02 10:47)

:)


McSimm   (2002-02-12 11:04:00) [14]

Могу предложить еще 2 варианта.
1й- Все-таки Pos(). Написать такую функцию не сложно.
sTmp := S; // Временная строка
K := Pos(",", sTmp); // Первая запятая
while K > 0 do
begin
ListBox1.Items.Add(Copy(sTmp, 1, K-1)); // очередное слово
sTmp := Copy(sTmp, K+1, Length(sTmp)); // отрезать
K := Pos(",", sTmp); // очередная запятая
end;
ListBox1.Items.Add(sTmp); // последнее слово


2й- С помощью TStringList:
SL := TStringList.Create;
try
SL.Text := StringReplace(S, ",", #13#10,[rfReplaceAll]);
// Здесь в нашем SL все строки уже разделены
finally
SL.Free
end


Romkin   (2002-02-12 10:59:00) [15]

for i := 1 to 3 do
begin
Apos := pos(",",s);
if APos > 0 then
delete(s,1,Apos);
end;
APos := pos(",",s);
if APos > 0 then
Result := copy(s,1,APos-1);


panov (M)   (2002-02-12 10:54:00) [16]

functionSearchString(const FindStr, SourceString: String;Num: Integer):Integer;
var
FirstP: PChar;
functionMyPos(const FindStr, SourceString: PChar;Num: Integer): PChar;
begin
Result := AnsiStrPos(SourceString,FindStr);
if(Result=nil) thenExit;
Inc(Result);
if Num=1 then Exit;
if num>1 then Result := MyPos(FindStr,Result,num-1);
end;
begin
FirstP := PChar(SourceString);
Result := MyPos(PChar(FindStr),PChar(SourceString),Num) - FirstP;
ifResult<0 thenResult := 0;
end;


Michael C   (2002-02-12 10:47:00) [17]

А если нету такой библиотеки, как быть???


McSimm   (2002-02-12 10:38:00) [18]

Если используете библиотеку RX, то есть простое решение:

uses
rxStrUtils; (или StrUtils для D5 и ниже)

for I := 1 to WordCount(S, [","]) do
SL.Add(ExtractWord(I, S, [","]))

В [","] можно перечислить несколько символов


Наверх

Титульная страница Поиск, карта сайта Написать письмо