IPB
ЛогинПароль:

> Внимание! Действует предмодерация

Подраздел FAQ (ЧАВО, ЧАстые ВОпросы) предназначен для размещения готовых рабочих программ, реализаций алгоритмов. Это нечто вроде справочника, он наполнялся в течение 2000х годов. Ваши вопросы, особенно просьбы решить задачу, не пройдут предмодерацию. Те, кто наполнял раздел, уже не заходят на форум, а с теми, кто на форуме сейчас, лучше начинать общение в других разделах. В частности, решение задач — здесь.

 
 Ответить  Открыть новую тему 
> Строки
сообщение
Сообщение #1


Ищущий истину
******

Группа: Пользователи
Сообщений: 4 825
Пол: Мужской
Реальное имя: Олег

Репутация: -  45  +


Строки. Краткая теория.

В Паскале определены два типа строк:
  • Тип String
  • тип PChar
I. String

Стандартная строка (string) в Паскале, представляет из себя массив, первый элемент которого содержит длину строки, а начиная со второго элемента начинается полезная информация. Поскольку нумерация начинается с 0, то первый элемент строки, содержащий длину строки, имеет индекс 0.

Если Вы попытаетесь осуществить следующее присвоение:
var
s:string;
I:byte;
begin
readln(s);
i:=s[0];
end.

то компилятор выдаст сообщение об ошибке (несовместимость типов), потому что
все элементы строки - символы (Char)

Для определения длины строки можно использовать или стандартную процедуру Length(stroka) или так:
var
dlinna_stroki:byte
s:string;
begin
readln(s); {вводим строку}
dlinna_stroki:=Ord(s[0]);
end.


Второй способ менее нагляден, но полезен если Вы забыли стандартные процедуры.

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

II. PChar
Для обеспечения поддержки строк, длиннее 255 символов, в TP7 был введен новый тип - PChar. Он имеет следующую структуру:
Type
PChar = ^Char;


Т.е. представляет собой указатель, но в отличие от обычных указателей, он трактуется необычным образом: считается, что он указывает на цепочку символов, заканчивающуюся символом с кодом #0.

Тип PChar совместим с одномерным символьным массивом с нулевой левой границей (array[0..max]).

Переменные типа PChar индексируются, т.е. к элементам длинной строки можно обратиться по их индексу, как к элементам обычной строки.

СТРОКИ. ЧаВо.
  • После посимвольного ввода строки, не получается вывести ее на экран. В чем дело?
    При посимвольном вводе строки, Вы забыли указать длину получившейся строки
    s[0]:=chr(dlinna)

    Или иначе, при вводе:
    {...}
    {ввод очередного символа}
    {...}
    Inc(S[0]);
  • Почему не получается индексировать длинную строку?
    Включите расширенный синтаксис директивой {$X+} или в настройках компилятора
  • Есть какие-нибудь процедуры для работы с длинными строками?
    Да, есть. В модуле strings
  • Как вывести длинную строку на экран?
    Процедурой Writeln, при включенно расширенном синтаксисе.
  • Сколько занимает в памяти строка?
    Для обычных строк, если не указана длина строки, то 256 байт.
    Если, при описании переменной, указана длина строки явно (string[8]), то столько, сколько указано +1 байт на нулевой элемент (хранение длинны строки).
    Для PChar размер в памяти равен количеству элементов до символа #0 +1 байт.
  • Как перевернуть строку?
    (с использованием второй строки):
    var
    s,f: string;
    i,j: byte;
    begin
    readln(s); j:=1;
    for i:=length(s) downto 1 do begin
    f[j]:=s[i]; inc(j);
    end;
    f[0]:=chr(j);
    writeln(f);
    end.


    (from APAL с использованием одной строки и одной переменной типа Char):
    var
    s:string;
    f:Char
    i:byte;
    begin
    readln(s);
    for i:=1 to Length(s) div 2 do begin
    f:=s[i];
    s[i]:=s[Length(s)-i+1];
    s[Length(s)-i+1]:=f;
    end;
    writeln(s);
    end.


--------------------
Помогая друг другу, мы справимся с любыми трудностями!
"Не опускать крылья!" (С)
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


Бывалый
***

Группа: Пользователи
Сообщений: 253
Пол: Мужской

Репутация: -  4  +


GetWords(s:string; var mas:TArray)
процедура возвращает массив mas, элементами которого являются слова строки s; под понятием слово подразумевается набор символов идущих подряд и не разграничиваемых знаком пробела (' ')
program WordsToArray;
uses crt;
type TArray=array[1..100]of string;

{ функция заполняет возвращает массив mas словами из строки s }
procedure GetWords(s:string; var mas:TArray);
var i,j:shortint;
begin
while pos(' ',s)<>0 do delete(s,pos(' ',s),1);
if s[1]=' ' then delete(s,1,1);
if s[length(s)]=' ' then delete(s,length(s),1); { удаляем лишние пробелы }

i:=1;
for j:=1 to length(s) do
if s[j]<>' ' then mas[i]:=mas[i]+s[j] else if i<>high(mas) then inc(i);
{ заполняем массив словами из строки }
end;

var s:string;
mas:TArray;i:shortint;
begin
clrscr;
write('> ');
readln(s);
GetWords(s,mas);
for i:=1 to high(mas) do if mas[i]<>'' then writeln(i,' - ',mas[i]);
end.


--------------------
Я не буду жить с этой злобой внутри / Я не буду частью смертельной цепи / Я не буду потребителем твоих идей / Я не буду никогда убивать зверей (Unconform)
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


Гость






Для удобства использования процедуру GetWords можно определить как функцию, которая возвращает количество найденных слов в строке (в переменной delimiters должны храниться символы, которые нужно считать разделителями слов):

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);			{ Здесь 2 пробела !!! }
		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.


Иногда может быть полезно вернуть список, а не массив слов, содержащихся в строке. Для этого можно воспользоваться вот такой модификацией:
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);			{ Здесь 2 пробела !!! }
		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;

{ пример использования функции }
const
	s: string = ' That is - all folks;;. ';
var
	i, count: Word;
	L: TWordList;
	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.


Другие способы разбиения строк на слова собраны вот в этой теме: Разбиение на слова. Все способы.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4


Ищущий истину
******

Группа: Пользователи
Сообщений: 4 825
Пол: Мужской
Реальное имя: Олег

Репутация: -  45  +


Модуль для работы со строками


Внимание: материал готовится!


--------------------
Помогая друг другу, мы справимся с любыми трудностями!
"Не опускать крылья!" (С)
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5


Ищущий истину
******

Группа: Пользователи
Сообщений: 4 825
Пол: Мужской
Реальное имя: Олег

Репутация: -  45  +


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

Внимание: Материал готовится!


--------------------
Помогая друг другу, мы справимся с любыми трудностями!
"Не опускать крылья!" (С)
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #6


Perl. Just code it!
******

Группа: Пользователи
Сообщений: 4 100
Пол: Мужской
Реальное имя: Андрей

Репутация: -  44  +


Стандартные функции и процедуры языка Паскаль для работы со строками и символами

Символы

Chr(x : byte) : Char - Возвращает символ ASCII кода х
Ord(c : Char) : Byte - Возвращает ASCII-код символа c
UpCase(c : Char) : Char - Переводит символы 'a'..'z' в верхний регистр
Pred(c : Char) : Char - Выдает предшествующий c символ
Succ(c : Char) : Char - Выдает последующий за c символ

Строки

Length(s : String) : Byte - Возвращает длину строки s
ConCat(s1, s2, s3 ... sn : String) : String - Возвращает конкатинацию (слияние) строк s1...sn
Copy(s : String; start, len : Integer) : String - Возвращает подстроку длиной len, начинающуюуся с позиции start строки s
Delete(VAR s : String; start, len : Integer) - Удалает подстроку длиной len начиная с позиции start строки s
Insert(VAR s : String; SubS : String; start : Integer ) - Вставляет в s подстроку SubS, начиная с позиции start
Pos(SubS, s : string) : byte - Ищет вхождение подстроки SubS в s и возвращает номер первого символа SubS в s, или 0, если s не соержит SubS

Процедуры преобразования

Str(X :F :n; s : string) - Преобразует числовое значение X в строковое s, возможно создание формата для х
Val(S : String; var X; errCode : integer) - Преобразует строку цифр S в числовое значение X, при неудачном преобразовании errCode содержит номер позиции символа в строке, который не удалось преобразовать (то есть он не является цифрои или десятичной точкой)

Сообщение отредактировано: klem4 -


--------------------
perl -e 'print for (map{chr(hex)}("4861707079204E6577205965617221"=~/(.{2})/g)), "\n";'
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7


Perl. Just code it!
******

Группа: Пользователи
Сообщений: 4 100
Пол: Мужской
Реальное имя: Андрей

Репутация: -  44  +


Имитация стандартных функций Паскаля для работы со строками

Функция POS

function _Pos(const subS, s: String): Integer;
var
  i, j, LenS, LenSb: Integer;
  find: Boolean;
begin

  i := 1;

  find := false;

  LenS  := Length(s);
  LenSb := Length(subS);

  while (i <= LenS) and not(find) do begin

    while (i <= LenS) and (s[i] <> subS[1]) do
     inc(i);

    if (i <= LenS) and ( i + LenSb - 1 <= LenS) then begin

      j := 0;

      while (j < LenSb) and (s[i + j] = subS[j + 1]) do
       inc(j);

      find := (j > LenSb - 1);

    end;

    if not(find) then inc(i);

  end;

  if find then _Pos := i else _Pos := 0;

end;


Функция COPY

function _Copy(const s: String; start, len: Word): String;
var
  result: String;
  LenS, i: Word;
begin


  if (start <= 0) or (len <= 0) then result := '' else begin

    result := '';

    LenS := Length(s);

    if start + len - 1 > LenS then
     len := LenS - start + 1;

    for i := start to start + len - 1 do
     result := result + s[i];

  end;

  _Copy := result;
end;


Функция INSERT

procedure _Insert(var s: String; const subS: String; start: Word);
var
  result: String;
  i: Integer;
begin

  if (start <= 0) or (start >= 255) then result := s else begin

    result := '';

    for i := 1 to start - 1 do
     result := result + s[i];

    result := result + subS;

    for i := start to Length(s) do
     result := result + s[i];

  end;

  s := result;
end;


Функция DELETE

procedure _Delete(var s: String; start, len: Word);
var
  i: Integer;
begin

  if (start <= 0) or (start >= 255) or (len <= 0) then exit;

  if start + len - 1 > Length(s) then
   len := Length(s) - start + 1;

  for i := start to Length(s) - len do
   s[i] := s[i + len];

  dec(s[0], len);

end;




--------------------
perl -e 'print for (map{chr(hex)}("4861707079204E6577205965617221"=~/(.{2})/g)), "\n";'
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #8


Perl. Just code it!
******

Группа: Пользователи
Сообщений: 4 100
Пол: Мужской
Реальное имя: Андрей

Репутация: -  44  +


Сколько раз слово w встречается в строке s ?

function Count(Const s, w: String; start: Byte): Byte;
const
  limits = ['.', ',', ';', '!', '?', ' '];
var
  p: Byte;
begin
  p := Pos(w, Copy(s, start, 255));
  if (start > length(s)) or (p = 0) then Count := 0
   else if (((start + p - 2) = 0) or (s[ start + p - 2] in limits))
    and (((start + p + length(w) - 2) = Length(s)) or (s[start + p + length(w) - 1] in limits))
     then Count := 1 + Count(s, w, start + p + length(w) - 2) else Count := 0 + Count(s, w, start + p + length(w) - 2);
end;


пример

function Count(Const s, w: String; start: Byte): Byte;
begin
 // ...
end;

begin
  clrscr;
  writeln(Count('mila mila mama ramu s milom milamila_mila milamilamila lalala mila', 'mila', 1));
  readln;
end.


Сообщение отредактировано: klem4 -


--------------------
perl -e 'print for (map{chr(hex)}("4861707079204E6577205965617221"=~/(.{2})/g)), "\n";'
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 



- Текстовая версия 3.04.2025 9:33
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name