Пятница, 14.06.2024, 05:25
Информатика и математика в Плесской школе
Приветствую Вас Гость | RSS
Меню сайта
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0
Форма входа

Разрезка строки 

Перед изучением данной темы советую скачать и изучить презентацию "Строки в Паскале" (Часть 2) опубликованную на "Учительском портале" http://www.uchportal.ru/load/18-1-0-52840

    В различных задачах, в том числе и задачах С4 ЕГЭ по информатике,  очень часто требуется обработать строку вводимую с клавиатуры. Для этого ее нужно разрезать на  отдельные слова.  Существует много способов реализации данной задачи. Я рассмотрю лишь некоторые, на мой взгляд, самые интересные и простые для понимания алгоритмы. 
    Для удобства будем рассматривать строку символов как массив символов. Это упрощает понимание алгоритмов работы со строками.  В принципе записи S:String[6]; и  S:array[1..6]of char;  можно считать равнозначными. Хотя на самом деле это не совсем так. Длина строки в Паскале 255 символов, а массив можно сделать намного больше. И второе, на мой взгляд, главное отличие: строка при выводе и выводе  рассматривается как единое целое, а массив необходимо вводить и выводить при помощи цикла. А вот обработка символьного массива и строки очень похожи.  

S[i]:='A'; //присваивание
If (S[i]='A') then … ;  //проверка условий

Практически, так же как и с элементом одномерного массива. В приведенных мною решениях задач я буду делать упор на такой способ решения, по минимуму используя специальные функции обработки строк. Хотя в некоторых случаях использование таких функций может сделать алгоритм более простым.
    Задача 1.  Вводится строка (с клавиатуры или из файла), представляющая Фамилия Имя Отчество (разделены пробелом). Составить программу присваивающую Фамилия Имя Отчество трем различным переменным.
Ее решение мы будем рассматривать далее.
    Слова в данной задаче разделены пробелами. Поэтому все показанные далее способы сводятся к одной идее. Разбираем строку по буквам (различные виды циклов), Забираем символы из строки, пока не встретился пробел. Если очередной символ пробел, то   переходим к следующему слову. И так далее. Изначально мы будем использовать три переменные: S – собственно сама строка, которую будем резать, S1,S2,S3 – переменные куда поместим фамилию, имя, отчество.
    Рассмотрим алгоритм формирования новой строки с использованием цикла пока. Буквально: 
берем первую букву;
пока очередной символ не пробел,
                    выполняем: 
                      в S1 запоминаем очередной символ и
                      номер символа увеличиваем на 1.

Тоже самое на Паскале:                 
i:=1;
while (s[i]<>' ') do begin
                       s1:=s1+s[i];
                       i:=i+1;
                     end;


    Рассмотрим пример разрезки строки на три части с использованием трех последовательно соединенных циклов пока. Необходимо помнить, что в конце строки пробела нет, поэтому в последнем цикле сравниваем порядковый номер буквы с длинной строки. Иногда бывает выгоднее приписать к существующей строке в конце пробел:
             S:=S+'  '; 
В некоторых учебниках такой способ называют метод барьерных элементов. 
program n1_1;
uses crt;
var     s,s1,s2,s3:string;
    i,j,k:integer;
begin
 clrscr;
 readln(s);
 i:=1;
 while (s[i]<>' ') do begin
                        s1:=s1+s[i]; i:=i+1;
                      end;
 i:=i+1;
 while (s[i]<>' ') do begin
                        s2:=s2+s[i]; i:=i+1;
                      end;
 i:=i+1;
 while (i<length(s)+1) do begin
                        s3:=s3+s[i]; i:=i+1;
                      end;


 writeln(s1);  writeln(s2);  writeln(s3);
end.

    Решение  задачи  можно упростить, заменив третий цикл на функцию COPY. Так как мы нашли номер последнего пробела, и нет смысла перебирать остатки строки. 
program n1_2;
uses crt;
var     s,s1,s2,s3:string;
    i,j,k:integer;
begin
 clrscr;
 readln(s);
 i:=1;
 while (s[i]<>' ') do begin
                        s1:=s1+s[i]; i:=i+1;
                      end;
 i:=i+1;
 while (s[i]<>' ') do begin
                        s2:=s2+s[i]; i:=i+1;
                      end;
 i:=i+1;
 s3:=copy(s,i,length(s));
 writeln(s1);  writeln(s2);  writeln(s3);
end.

    Тоже самое можно осуществить, используя цикл с постусловием:
program n1_3;
uses crt;
var     s,s1,s2,s3:string;
    i,j,k:integer;
begin
 clrscr;
 readln(s);
 i:=1;
 repeat  s1:=s1+s[i]; i:=i+1; until (s[i]=' ');
 i:=i+1;
 repeat  s2:=s2+s[i]; i:=i+1; until (s[i]=' ');
 i:=i+1;
 s3:=copy(s,i,length(s));
 writeln(s1);  writeln(s2);  writeln(s3);
end.

    Решение задачи можно свести к одному циклу, используя цикл  с параметром. Идея решения в следующем: заводим переменную k. Которая будет хранить номер слова, являясь по сути дела переключателем. Перед циклом присваиваем k значение 1 и перебирая символы в строке переносим их в переменную S1. Как только встретится пробел, номер слова увеличиваем на 1 (переключаем переключатель на второе слово) и начинаем заполнять S2. И так далее.
program n1_4;
uses crt;
var     s,s1,s2,s3:string;
    i,j,k:integer;
begin
 clrscr;
 readln(s);
 k:=1;
 for i:=1 to length(s)do 
                  begin
                    if (k=1) And (s[i]<>' ') then s1:=s1+s[i];
                    if (k=2) And (s[i]<>' ') then s2:=s2+s[i];
                    if (k=3) And (s[i]<>' ') then s3:=s3+s[i];
                    if s[i]=' ' then k:=k+1;
                   end;
 writeln(s1);  writeln(s2);  writeln(s3);

end.

    В данном случае применение функций обработки строк сводит алгоритм к линейному (не всегда). Идея заключается в следующем: ищем первый пробел (функция вхождения подстроки в строку) копируем (COPY) фрагмент строки от начала до первого пробела в S1. Удаляем (delete) часть строки от начала до первого пробела включительно и повторяем те же самые операции для S2. Для S3 останется последнее слово.
program n1_5;
uses crt;
var  s,s1,s2,s3:string;
    i,j,k:integer;
    ch:char;
begin
 clrscr;
  readln(s);
    i := Pos(' ', s);
    s1 := Copy(s,1,i-1);
    delete(s,1,i);
    i := Pos(' ', s);
    s2 := Copy(s,1,i-1);
    delete(s,1,i);
    s3:=s;
 writeln(s1);  writeln(s2);  writeln(s3);

end.

    Иногда бывает полезно сымитировать ввод строки.  При этом нет необходимости резать строку на части. Так как элементы строки изначально присваиваются трем различным переменным. Идея была подсмотрена на сайте «РЕШУ ЕГЭ» (http://решуегэ.рф , http://reshuege.ru) Автор сайта  - Гущин Д. Д.
program n1_6;
uses crt;
var  s,s1,s2,s3:string;
    i,j,k:integer;
    ch:char;
begin
 clrscr;
  repeat
   read(ch);
   s1:=s1+ch;
  until ch=' ';
 repeat
  read(ch);
  s2:=s2+ch;
 until ch=' ' ;
readln(s3);
 writeln(s1);  writeln(s2);  writeln(s3);
end.

Очень часто при решении задач на разрезку строки количество слов в строке заранее неизвестно. В этом случае можно завести массив строк длинной 255 ячеек. Даже если слова в строке будут состоять из одной буквы, то мы все равно целиком не заполним этот массив словами, так как строка не может превышать 255 символов, а слова нужно разделить пробелами. Ячейки массива являются переменными строкового типа, поэтому в них можно хранить целиковые слова. Идея алгоритма: Перебираем строку от первой до последней буквы. Начиная с первой ячейки, заполняем ее символами из строки, если встретится пробел, переходим к следующей ячейке и так далее пока строка не кончится. 
program n1_7;
uses crt;
var a:array[1..255] of string;
    s:string;
    i,k:integer;
begin
 clrscr;
 readln(s);
 k:=1;
 for i:=1 to length(s)do begin
                          if (s[i]<>' ') then a[k]:=a[k]+s[i];
                          if s[i]=' ' then k:=k+1;
                         end;
 for i:=1 to k do writeln(a[i]);
end.


    Если необходимости запоминать все слова нет, то можно обойтись без массива. Слова будут храниться в переменной А, и каждое следующее слово будет затирать предыдущее. В место, где полностью сформировано слово (у меня стоит просто вывод на экран) можно вставить процедуру, которая что-то с этой переменной в зависимости от условия задачи будет делать. 
program n1_8;
uses crt;
var s,a:string;
    i,k:integer;
begin
 clrscr;
 readln(s);
 a:='';
 s:=s+' ';
 for i:=1 to length(s)do begin
                          if (s[i]<>' ') then a:=a+s[i];
                          if s[i]=' ' then begin
                                              writeln(a);
                                              a:='';
                                           end;
                         end;

end.

Поиск
Календарь
«  Июнь 2024  »
ПнВтСрЧтПтСбВс
     12
3456789
10111213141516
17181920212223
24252627282930
Архив записей
Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz
  • Учительский портал
    Copyright MyCorp © 2024