Работа со строками
Приведу несколько простых функций, позволяющих работать с отдельными словами в строке. Возможно они пригодятся вам для разбивки текстовых полей на отдельные слова (for i := 1 to NumToken do ...) с последующим сохранением их в базе данных.
Code: |
function GetToken(aString, SepChar: string; TokenNum: Byte): string; { параметры: aString : полная строка
SepChar : единственный символ, служащий разделителем между словами (подстроками) TokenNum: номер требуемого слова (подстроки)) result : искомое слово или пустая строка, если количество слов
меньше значения 'TokenNum' } var
Token: string; StrLen: Byte; TNum: Byte; TEnd: Byte;
begin
StrLen := Length(aString); TNum := 1; TEnd := StrLen; while ((TNum <= TokenNum) and (TEnd <> 0)) do begin TEnd := Pos(SepChar, aString); if TEnd <> 0then begin Token := Copy(aString, 1, TEnd - 1); Delete(aString, 1, TEnd); Inc(TNum); end else begin Token := aString; end; end; if TNum >= TokenNum then begin GetToken1 := Token; end else begin GetToken1 := ''; end; end;
function NumToken(aString, SepChar: string): Byte; { parameters: aString : полная строка
SepChar : единственный символ, служащий разделителем между словами (подстроками) result : количество найденных слов (подстрок) }
var
RChar: Char; StrLen: Byte; TNum: Byte; TEnd: Byte;
begin
if SepChar = '#'then begin RChar := '*' end else begin RChar := '#' end; StrLen := Length(aString); TNum := 0; TEnd := StrLen; while TEnd <> 0do begin Inc(TNum); TEnd := Pos(SepChar, aString); if TEnd <> 0then begin aString[TEnd] := RChar; end; end; Result := TNum; end;
// Или другое решение:
function CopyColumn(const s_string: string; c_fence: char; i_index: integer): string; var i, i_left: integer; begin
result := EmptyStr; if i_index = 0then begin exit; end; i_left := 0; for i := 1to Length(s_string) do begin if s_string[i] = c_fence then begin Dec(i_index); if i_index = 0then begin result := Copy(s_string, i_left + 1, i - i_left - 1); exit; end else begin i_left := i; end; end; end; Dec(i_index); if i_index = 0then begin result := Copy(s_string, i_left + 1, Length(s_string)); end; end; |
Я знаю что в GetToken параметр SepChar (в моем случае c_fence) строка, не символ, но комментарий гласит, что функция ожидает единственный символ в этой строке, и это очевидно, поскольку если вы пошлете более одного символа, функция попросту несработает. ( Delete(aString,1,TEnd) будет ошибкой, если Length( SepChar ) > 1 ).
Взято с https://delphiworld.narod
Code: |
{ **** UBPFD *********** by delphibase.endimus.com **** >> Разбивка строки на отдельные слова
function StringToWords(const DelimitedText: string; ResultList: TStrings; Delimiters: TDelimiter = []): boolean - разбивает отдельную строку на состовляющие ее слова и результат помещает в TStringList
function StringsToWords(const DelimitedStrings: TStrings; ResultList: TStrings; Delimiters: TDelimiter = []): boolean - разбивает любое количество строк на состовляющие их слова и все помещяет в один TStringList
Delimiters - список символов являющихся разделителями слов, например такие как пробел, !, ? и т.д.
Зависимости: Classes Автор: Separator, Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра., Алматы Copyright: Separator Дата: 13 ноября 2002 г. ***************************************************** }
unit spUtils;
interface
uses Classes;
type TDelimiter = setof#0..'я' ;
const StandartDelimiters: TDelimiter = [' ', '!', '@', '(', ')', '-', '|', '\', ';', ':', '"', '/', '?', '.', '>', ',', '<'];
//Преобразование в набор слов function StringToWords(const DelimitedText: string; ResultList: TStrings; Delimiters: TDelimiter = []; ListClear: boolean = true): boolean;
function StringsToWords(const DelimitedStrings: TStrings; ResultList: TStrings; Delimiters: TDelimiter = []; ListClear: boolean = true): boolean;
implementation
function StringToWords(const DelimitedText: string; ResultList: TStrings; Delimiters: TDelimiter = []; ListClear: boolean = true): boolean; var i, Len, Prev: word; TempList: TStringList;
begin Result := false; if (ResultList <> nil) and (DelimitedText <> '') then try TempList := TStringList.Create; if Delimiters = [] then Delimiters := StandartDelimiters; Len := 1; Prev := 0; for i := 1to Length(DelimitedText) do begin if Prev <> 0then begin if DelimitedText[i] in Delimiters then begin if Len = 0then Prev := i + 1 else begin TempList.Add(copy(DelimitedText, Prev, Len)); Len := 0; Prev := i + 1 end end else Inc(Len) end elseifnot (DelimitedText[i] in Delimiters) then Prev := i end; if Len > 0then TempList.Add(copy(DelimitedText, Prev, Len)); if TempList.Count > 0then begin if ListClear then ResultList.Assign(TempList) else ResultList.AddStrings(TempList); Result := true end; finally TempList.Free end end;
function StringsToWords(const DelimitedStrings: TStrings; ResultList: TStrings; Delimiters: TDelimiter = []; ListClear: boolean = true): boolean; begin if Delimiters = [] then Delimiters := StandartDelimiters + [#13, #10] else Delimiters := Delimiters + [#13, #10]; Result := StringToWords(DelimitedStrings.Text, ResultList, Delimiters, ListClear) end;
end. //Пример использования:
StringToWords(Edit1.Text, Memo1.Lines); StringToWords(Edit1.Text, Memo1.Lines, [' ', '.', ',']); StringsToWords(Memo1.Lines, Memo2.Lines); StringsToWords(Memo1.Lines, Memo2.Lines, [' ', '.', ',']);
|
Code: |
{ **** UBPFD *********** by delphibase.endimus.com **** >> Разбиение текста на слова + получение количества слов в тексте
T : Собственно строка, которая будет разбиваться на слова Mode: Режим, может быть 0: получение английских и русских слов 1: только русских 2: только английских List: Здесь хранятся найденые слова (по умолчанию = nil)
возвращаемое значение: количество слов.
P/S По идейным соображениям специальные символы, цифры и пробелы игнорируются.
Зависимости: Windows, Classes Автор: 777, Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра., Архангельск Copyright: 777 Дата: 15 июня 2002 г. ***************************************************** }
function StringToWords(T: string; Mode: Short; List: Tstrings = nil): integer; var i, z: integer; s: string; c: Char;
procedure Check; begin if (s > '') and (List <> nil) then begin List.Add(S); z := z + 1; end; s := ''; end;
begin i := 0; z := 0; s := ''; if t > ''then begin while i <= Length(t) + 1do begin c := t[i]; case Mode of 0: {русские и английские слова} if (c in ['a'..'z']) or (c in ['A'..'Z']) or (c in ['а'..'я']) or (c in ['А'..'Я']) and (c <> ' ') then s := s + c else Check; 1: {только русские слова} if (c in ['а'..'я']) or (c in ['А'..'Я']) and (c <> ' ') then s := s + c else Check; 2: {только английские слова} if (c in ['a'..'z']) or (c in ['A'..'Z']) and (c <> ' ') then s := s + c else check; end; i := i + 1; end; end; result := z; end; //Пример использования:
procedure TForm1.Button1Click(Sender: TObject); var Source, Dest: Tstrings; i: integer; begin Source := TstringList.Create; Dest := TstringList.Create; Source.LoadFromFile('c:\MyText.txt'); for i := 0to Source.Count - 1do begin StringToWords(Source[i], 2, Dest); Application.ProcessMessages; end; Dest.SaveToFile('c:\MyWords.txt'); ShowMessage('Найдено ' + IntToStr(Dest.Count) + ' слов'); end;
|
Code: |
procedure SplitTextIntoWords(const S: string; words: TstringList); var startpos, endpos: Integer; begin Assert(Assigned(words)); words.Clear; startpos := 1; while startpos <= Length(S) do begin // skip non-letters while (startpos <= Length(S)) andnot IsCharAlpha(S[startpos]) do Inc(startpos); if startpos <= Length(S) then begin // find next non-letter endpos := startpos + 1; while (endpos <= Length(S)) and IsCharAlpha(S[endpos]) do Inc(endpos); words.Add(Copy(S, startpos, endpos - startpos)); startpos := endpos + 1; end; { If } end; { While } end; { SplitTextIntoWords }
function StringMatchesMask(S, mask: string; case_sensitive: Boolean): Boolean; var sIndex, maskIndex: Integer; begin ifnotcase_sensitive then begin S := AnsiUpperCase(S); mask := AnsiUpperCase(mask); end; { If } Result := True; // blatant optimism sIndex := 1; maskIndex := 1; while (sIndex <= Length(S)) and (maskIndex <= Length(mask)) do begin case mask[maskIndex] of '?': begin // matches any character Inc(sIndex); Inc(maskIndex); end; { case '?' } '*': begin // matches 0 or more characters, so need to check for // next character in mask Inc(maskIndex); if maskIndex > Length(mask) then // * at end matches rest of string Exit elseif mask[maskindex] in ['*', '?'] then raise Exception.Create('Invalid mask'); // look for mask character in S while (sIndex <= Length(S)) and (S[sIndex] <> mask[maskIndex]) do Inc(sIndex); if sIndex > Length(S) then begin // character not found, no match Result := False; Exit; end; { If } end; { Case '*' } elseif S[sIndex] = mask[maskIndex] then begin Inc(sIndex); Inc(maskIndex); end{ If } else begin // no match Result := False; Exit; end; end; { Case } end; { While } // if we have reached the end of both S and mask we have a complete // match, otherwise we only have a partial match if (sIndex <= Length(S)) or (maskIndex <= Length(mask)) then Result := False; end; { stringMatchesMask }
procedure FindMatchingWords(const S, mask: string; case_sensitive: Boolean; matches: Tstrings); var words: TstringList; i: Integer; begin Assert(Assigned(matches)); words := TstringList.Create; try SplitTextIntoWords(S, words); matches.Clear; for i := 0to words.Count - 1do begin if stringMatchesMask(words[i], mask, case_sensitive) then matches.Add(words[i]); end; { For } finally words.Free; end; end;
{ The Form has one TMemo for the text to check, one TEdit for the mask, one TCheckbox (check = case sensitive), one TListbox for the results, one Tbutton } procedure TForm1.Button1Click(Sender: TObject); begin FindMatchingWords(memo1.Text, edit1.Text, checkbox1.Checked, listbox1.Items); end; |
Взято с сайта: https://www.swissdelphicenter
Расщепить строку в слова и обратно
Code: |
unit StrFuncs;
interface
uses SysUtils, Classes;
function StrToArrays(str, r: string; out temp: TStrings): Boolean; function ArrayToStr(str: TStrings; r: string): string;
implementation
function StrToArrays(str, r: string; out temp: TStrings): Boolean; var j: Integer; begin if temp <> nilthen begin temp.Clear; while str <> ''do begin j := Pos(r, str); if j = 0then j := Length(str) + 1; temp.Add(Copy(Str, 1, j - 1)); Delete(Str, 1, j + Length(r) - 1); end; Result := True; else Result := False; end; end;
function ArrayToStr(str: TStrings; r: string): string; var i: Integer; begin Result := ''; for i := 0to Str.Count - 1do begin Result := Result + Str.Strings[i] + r; end; end; end.
|
https://delphiworld.narod
DelphiWorld 6.0
- Подробности
- Родительская категория: Работа со строками
- Категория: Слова
Code: |
{ **** UBPFD *********** by delphibase.endimus **** >> Сканирование строки начиная с указанной позиции с целью нахождения слова.
Функция предназначена для разбиения строки на слова. Границы слов определяются по разделителям.
Описание параметров:
S - строка, в которой производится поиск;
StartPos - на входе принимает позицию с которой начинается сканирование строки, на выходе содержит позицию символа, с которого начинается слово;
WordLen - на выходе содержит длину найденного слова;
Delimiters - множество, содержащее символы-разделители слов;
Возвращаемое значение - true если слово найдено, инече false;
Зависимости: SysUtils Автор: vuk, Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра. Copyright: Алексей Вуколов
***************************************************** }
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 ifnot (s[i] in Delimiters) then begin inc(i); inc(WordLen); end else break;
Result := WordLen <> 0; end; //Пример использования:
//Консольная программа, выводящая на экран слова из заданной строки.
program Project1; {$APPTYPE CONSOLE} uses SysUtils;
var s: string; wStart, wLen: integer; begin s := 'This is a test string. String contains delimiters.'; wStart := 1; wLen := 0; while WordScan(s, wStart, wLen, [' ', '.', ',']) do begin writeln(copy(s, wStart, wLen)); inc(wStart, wLen); end; readln; end. |
- Подробности
- Родительская категория: Работа со строками
- Категория: Слова
Code: |
//Функция возвращающая N-ое слово в строке //Если N=0, то функция возвращает подстоку начиная с первого разделителя function GetWord(str:string;n:word;sep:char):string; var i,space,l,j:integer; buf:string; begin l:=length(str); if n=0thenbegin//особый параметр j:=pos(GetWord(str,2,sep),str); GetWord:=copy(str,j,l-j+1); exit end; space:=0; i:=0; while (space<>(n-1))and(i<=l) do begin i:=i+1; if str[i]=sep then space:=space+1 end; i:=i+1; buf:=''; while (i<=l)and(str[i]<>sep) do begin buf:=buf+str[i]; i:=i+1 end; GetWord:=buf; end; |
Автор: TP@MB@Y
Взято с Vingrad ruhttps://forum.vingrad
Code: |
function GetToken(aString, SepChar: string; TokenNum: Byte): string; { параметры: aString : полная строка
SepChar : единственный символ, служащий разделителем между словами (подстроками) TokenNum: номер требуемого слова (подстроки)) result : искомое слово или пустая строка, если количество слов
меньше значения 'TokenNum' } var Token: string; StrLen: Byte; TNum: Byte; TEnd: Byte; begin StrLen := Length(aString); TNum := 1; TEnd := StrLen; while ((TNum <= TokenNum) and (TEnd <> 0)) do begin TEnd := Pos(SepChar, aString); if TEnd <> 0then begin Token := Copy(aString, 1, TEnd - 1); Delete(aString, 1, TEnd); Inc(TNum); end else begin Token := aString; end; end; if TNum >= TokenNum then begin GetToken1 := Token; end else begin GetToken1 := ''; end; end;
function NumToken(aString, SepChar: string): Byte; { parameters: aString : полная строка
SepChar : единственный символ, служащий разделителем между словами (подстроками) result : количество найденных слов (подстрок) } var RChar: Char; StrLen: Byte; TNum: Byte; TEnd: Byte; begin if SepChar = '#'then begin RChar := '*' end else begin RChar := '#' end; StrLen := Length(aString); TNum := 0; TEnd := StrLen; while TEnd <> 0do begin Inc(TNum); TEnd := Pos(SepChar, aString); if TEnd <> 0then begin aString[TEnd] := RChar; end; end; Result := TNum; end; |
https://delphiworld.narod
DelphiWorld 6.0
Code: |
function CopyColumn(const s_string: string; c_fence: char; i_index: integer): string; var i, i_left: integer; begin result := EmptyStr; if i_index = 0then begin exit; end; i_left := 0; for i := 1to Length(s_string) do begin if s_string[i] = c_fence then begin Dec(i_index); if i_index = 0then begin result := Copy(s_string, i_left + 1, i - i_left - 1); exit; end else begin i_left := i; end; end; end; Dec(i_index); if i_index = 0then begin result := Copy(s_string, i_left + 1, Length(s_string)); end; end; |
https://delphiworld.narod
DelphiWorld 6.0
Code: |
{ **** UBPFD *********** by delphibase.endimus **** >> Получение N-го слова из строки
Зависимости: System Автор: Gua, Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра., ICQ:141585495, Simferopol Copyright: Gua Дата: 02 мая 2002 г. ***************************************************** }
{ Str: Строка Smb: Разгранечительный символ WordNmbr: Номер нужного сова }
function GetWord(Str, Smb: string; WordNmbr: Byte): string; var SWord: string; StrLen, N: Byte; begin
StrLen := SizeOf(Str); N := 1;
while ((WordNmbr >= N) and (StrLen <> 0)) do begin StrLen := Pos(Smb, str); if StrLen <> 0then begin SWord := Copy(Str, 1, StrLen - 1); Delete(Str, 1, StrLen); Inc(N); end else SWord := Str; end;
if WordNmbr <= N then Result := SWord else Result := ''; end; //Пример использования:
GetWord('Здесь ваш текст',' ',3); // Возвращает -> 'текст'
|
- Подробности
- Родительская категория: Работа со строками
- Категория: Слова
Словарь уникальных слов.
Алгоритм составления словаря всех уникальных слов встречающихся в текстовом файле.
По результатам тестирования: обработка файла объемом 3 Мб (уникальных слов ~63 тысячи)
занимает около 3 секунд. (Можно, конечно, и еще ускорить, но уж лениво сильно ;)
Демо пример:
Unit1.pas |
unit Unit1;
interface
uses |
Unit1.dfm |
object Form1: TForm1
|
Project2.dpr |
program Project2;
uses |
Dictionary.pas |
//////////////////////////////////////////////////////////////////////////////// |
- Подробности
- Родительская категория: Работа со строками
- Категория: Слова
Code: |
unit StreamFile;
interface
uses SysUtils;
procedure AssignStreamFile(var F: Text; Filename: string);
implementation
const BufferSize = 128;
type TStreamBuffer = array[1..High(Integer)] of Char; TStreamBufferPointer = ^TStreamBuffer; TStreamFileRecord = record case Integer of 1: ( Filehandle: Integer; Buffer: TStreamBufferPointer; BufferOffset: Integer; ReadCount: Integer; ); 2: ( Dummy: array[1..32] of Char ) end;
function StreamFileOpen(var F: TTextRec): Integer; var Status: Integer; begin with TStreamFileRecord(F.UserData) do begin GetMem(Buffer, BufferSize); case F.Mode of fmInput: FileHandle := FileOpen(StrPas(F.Name), fmShareDenyNone); fmOutput: FileHandle := FileCreate(StrPas(F.Name)); fmInOut: begin FileHandle := FileOpen(StrPas(F.Name), fmShareDenyNone or fmOpenWrite or fmOpenRead); if FileHandle <> -1then status := FileSeek(FileHandle, 0, 2); { Перемещаемся в конец файла. } F.Mode := fmOutput; end; end; BufferOffset := 0; ReadCount := 0; F.BufEnd := 0; { В этом месте подразумеваем что мы достигли конца файла (eof). } if FileHandle = -1then Result := -1 else Result := 0; end; end;
function StreamFileInOut(var F: TTextRec): Integer;
procedureRead(var Data: TStreamFileRecord); procedure CopyData; begin while (F.BufEnd < Sizeof(F.Buffer) - 2) and (Data.BufferOffset <= Data.ReadCount) and (Data.Buffer[Data.BufferOffset] <> #10) do begin F.Buffer[F.BufEnd] := Data.Buffer^[Data.BufferOffset]; Inc(Data.BufferOffset); Inc(F.BufEnd); end; if Data.Buffer[Data.BufferOffset] = #10then begin F.Buffer[F.BufEnd] := #13; Inc(F.BufEnd); F.Buffer[F.BufEnd] := #10; Inc(F.BufEnd); Inc(Data.BufferOffset); end; end;
begin F.BufEnd := 0; F.BufPos := 0; F.Buffer := ''; repeat begin if (Data.ReadCount = 0) or (Data.BufferOffset > Data.ReadCount) then begin Data.BufferOffset := 1; Data.ReadCount := FileRead(Data.FileHandle, Data.Buffer^, BufferSize); end; CopyData; enduntil (Data.ReadCount = 0) or (F.BufEnd >= Sizeof(F.Buffer) - 2); Result := 0; end;
procedureWrite(var Data: TStreamFileRecord); var Status: Integer; Destination: Integer; II: Integer; begin with TStreamFileRecord(F.UserData) do begin Destination := 0; for II := 0to F.BufPos - 1do begin if F.Buffer[II] <> #13then begin Inc(Destination); Buffer^[Destination] := F.Buffer[II]; end; end; Status := FileWrite(FileHandle, Buffer^, Destination); F.BufPos := 0; Result := 0; end; end; begin case F.Mode of fmInput: Read(TStreamFileRecord(F.UserData)); fmOutput: Write(TStreamFileRecord(F.UserData)); end; end;
function StreamFileFlush(var F: TTextRec): Integer; begin Result := 0; end;
function StreamFileClose(var F: TTextRec): Integer; begin with TStreamFileRecord(F.UserData) do begin FreeMem(Buffer); FileClose(FileHandle); end; Result := 0; end;
procedure AssignStreamFile(var F: Text; Filename: string); begin with TTextRec(F) do begin Mode := fmClosed; BufPtr := @Buffer; BufSize := Sizeof(Buffer); OpenFunc := @StreamFileOpen; InOutFunc := @StreamFileInOut; FlushFunc := @StreamFileFlush; CloseFunc := @StreamFileClose; StrPLCopy(Name, FileName, Sizeof(Name) - 1); end; end; end. |
Взято из Советов по Delphi от Валентина Озерова
Сборник Kuliba
- Подробности
- Родительская категория: Работа со строками
- Категория: Справочные материалы, общие вопросы
Страница 19 из 21