Работа со строками
   
Разбиение строки на слова  
Как ввести строку ограниченной длины  
   
Нижеприведенный модуль для работы со строками содержит ряд функций для работы со строковыми переменными. Функции разбиты на несколько групп:

Функции проверки:
Функции, начинающиеся с Is... предназначены для проверки принадлежности символов строки к определенным группам. Все они возвращают логическое значение (True/False). Функция Is... проверяет, "является ли символ Ch..." Функции преобразования:
Функции сравнения строк.
Все эти функции возвращают результат типа strResult:
Type
  strResult = (strLess, strEqual, strMore);
При сравнении строк s1 и s2 результат будет таким:
 s1 = s2 : вернется strEqual
 s1 < s2 : вернется strLess
 s1 > s2 : вернется strMore
Функции поиска: Дополнительные функции:

Исходник: strings.pas



Различные возможные реализации функций разбиения строки на слова:

  1. Одна из самых простых реализаций: строка S разбивается на слова с учетом заданных разделителей delimiters, и слова заносятся в статический массив mas. Функция возвращает количество найденных в строке слов:
    Type
      TWords = Array[1 .. 100] Of String[100];
      TDelimiter = Set Of Char;
    
    Function GetWords(s: String; Var mas: TWords;
      delimiters: TDelimiter): Byte;
      Var i, p: Byte;
      Begin
    	{ Заменяем все разделители пробелами }
    	For i := 1 to Length(s) Do
    	  If s[i] In delimiters Then s[i] := #32;
    
    	{ удаляем лишние пробелы }
    	Repeat
    	  p := Pos('  ', s);
    	  If p > 0 Then Delete(s, p, 1)
    	Until p = 0;
    
    	If s[1] = ' ' Then Delete(s, 1, 1); { удаляем пробел в начале строки }
    	If s[Length(s)] = ' ' Then
    	  Delete(s, Length(s), 1); { удаляем пробел в конце строки }
    
    	i := 0;
    	Repeat { заполняем массив словами из строки }
    	  p := Pos(' ', s); Inc(i);
    	  If p > 0 Then
    		Begin
    		  mas[i] := Copy(s, 1, Pred(p)); Delete(s, 1, p)
    		End
    	  Else mas[i] := s
    	Until p = 0;
    	GetWords := i
      End;
    
    Var
      i, count: Word;
      words: TWords;
    
    { пример использования функции }
    Const
      s: String = ' That is   all folks ';
    Begin
      Count := GetWords(s, words, []);
      For i := 1 To Count Do
    	WriteLn(words[i]);
    End.
  2. Иногда может быть полезно (в том числе, и для экономии памяти, используемой программой) вернуть список, а не массив слов, содержащихся в строке. Для этого можно воспользоваться вот такой модификацией:
    Type
      TWordStr = String[100];
      TDelimiter = Set Of Char;
    
      PTItem = ^TItem;
      TItem = Record
    	Data: TWordStr;
    	next: PTItem;
      End;
      TWordList = Record
    	first, last: PTItem;
      End;
    
    Procedure InsertWord(Var L: TWordList; s: String);
    Var p: PTItem;
    Begin
      New(p);
      p^.Data := s;
      p^.next := nil;
    
      If L.first = nil Then L.first := p
      Else L.last^.next := p;
      L.last := p
    End;
    
    Function GetWords(s: String;
    		 Var L: TWordList; delimiters: TDelimiter): Byte;
    Var i, p: Byte;
    Begin
      { Заменяем все разделители пробелами }
      For i := 1 to Length(s) Do
    	If s[i] In delimiters Then s[i] := #32;
    
      { удаляем лишние пробелы }
      Repeat
    	p := Pos('  ', s);
    	If p > 0 Then Delete(s, p, 1)
      Until p = 0;
    
      If s[1] = ' ' Then Delete(s, 1, 1); { удаляем пробел в начале ... }
      If s[Length(s)] = ' ' Then
    	Delete(s, Length(s), 1); { ... и в конце строки }
    
      i := 0;
      Repeat { заполняем список словами из строки }
    	p := Pos(' ', s); Inc(i);
    	If p > 0 Then Begin
    	  InsertWord(L, Copy(s, 1, Pred(p)));
    	  Delete(s, 1, p)
    	End
    	Else InsertWord(L, s)
      Until p = 0;
      GetWords := i
    End;
    
    Var
      i, count: Word;
      L: TWordList;
    
    { пример использования функции }
    Const
      s: String = ' That is - all folks;;. ';
    var
      p: ptitem;
    Begin
      Count := GetWords(s, L, ['-', ';', '.']);
      WriteLn(Count, ' words found ...');
    
      p := L.first;
      While p <> nil Do Begin
    	WriteLn(p^.Data);
    	p := p^.next;
      End;
    End.
  3. Это - довольно простой способ (информация о найденных словах снова хранится в массиве, но НЕ в виде самих слов, а в виде <начало слова в строке, длина слова>). Использование такого варианта "разбиения" дает возможность легко обрабатывать исходную строку, оставляя все разделители на прежних местах:
    const
      delimiter = [#32, ',', '.', '!', ':'];
    type
      wrd_info = record
        start, len: byte;
      end;
    
    function get_words(s: string;
             var words: array of wrd_info): integer;
    var
      count: integer;
    
      i, curr_len: byte;
    
    begin
      count := -1; i := 1;
      while i <= length(s) do begin
    
        while (s[i] in delimiter) and (i <= length(s)) do inc(i);
    
        curr_len := 0;
        while not (s[i] in delimiter) and (i <= length(s)) do begin
          inc(i); inc(curr_len);
        end;
    
        if curr_len > 0 then begin
          inc(count);
          with words[count] do begin
            start := i - curr_len;
            len := curr_len
          end;
        end;
    
      end;
      get_words := count + 1;
    end;
    
    
    const
      max_word = 255;
    var
      words: array[1 .. max_word] of wrd_info;
      i, n: integer;
    
    const
      s: string = 'thats,,, all :: folks !!! bye...';
    
    begin
      n := get_words(s, words);
      writeln('words:');
      for i := 1 to n do
        writeln(copy(s, words[i].start, words[i].len));
    end.


Как написать функцию для ввода строки с ограниченной длиной ?

Приведенная ниже функция позволяет пользователю ввести строку длиной до max_len символов. При попытке ввода большего числа символов они просто игнорируются. При вводе строки можно по-прежнему пользоваться клавишей BackSpace для удаления последнего введенного символа.
uses crt;
function get_str(max_len: byte): string;
  var s: string; ch: char;
  begin
    s := '';
    repeat
      ch := readkey;
      if length(s) <= max_len then
        case ch of
          #8: begin
                if length(s) > 0 then begin
                  write(#8,#32,#8);
                  delete(s, length(s), 1)
                end
              end
          else
            if length(s) <> max_len then
              begin s := s + ch; write(ch) end
        end;
    until ch = #13;
    writeln;
    get_str := s
  end;
Пример использования функции:
var
  s: string;

begin
  write('string = '); s := get_str(5);
  writeln('res = ', s);
end.




Free Web Hosting