Главная страница

программирование на паскале2. Учебное пособие по курсу Высокоуровневые методы информатики и программирования для студентов Гуманитарноприкладного института


Скачать 0.89 Mb.
НазваниеУчебное пособие по курсу Высокоуровневые методы информатики и программирования для студентов Гуманитарноприкладного института
Анкорпрограммирование на паскале2.doc
Дата25.05.2018
Размер0.89 Mb.
Формат файлаdoc
Имя файлапрограммирование на паскале2.doc
ТипУчебное пособие
#19648
страница5 из 10
1   2   3   4   5   6   7   8   9   10

Часть . Обработка символьной информации и документов сложной структуры

3.1. Обработка символьной информации

3.1.1. Символьный тип


Здесь мы углубим знания, полученные в части I пособия. Символьные (или литерные) переменные - это переменные типа char. Они принимают значения на множестве символов данной ЭВМ. Пример описания символьной переменной А:

var A: char;

Все символы упорядочены, имеют свой номер, зависящий от системы кодирования, так что символьный тип является порядковым типом. В средах программирования Turbo (Borland) Pascal (ориентированных на шестнадцатиразрядные персональные ЭВМ типа IBM PC и операционную систему MS DOS) используется система кодирования ASCII, в которой код символа занимает 1 байт. В версиях среды программирования Delphi для 32-разрядных персональных компьютеров имеется также символьный тип widechar, основанный на системе кодирования Unicode, в которой на код символа отводится 2 байта. Тип char для этих компьютеров поддерживается однобайтовой таблицей ANSI. Первые 256 кодов таблицы Unicode совпадают с таблицей ANSI.

К символьным переменным (как и к переменным любого порядкового типа) применимы встроенные функции ORD (определение порядкового номера, т. е. кода, символа), SUCC (определение следующего символа) и PRED (определение предшествующего символа); функция CHR по коду определяет символ.

В дальнейшем также потребуется функция UPCASE(CH). Это функция типа CHAR; возвращает символ CH в верхнем регистре, если он определен для него, либо сам символ CH, если для него нет верхнего регистра. Например, UPCASE('a') вернет А, в то время как UPCASE('2') вернет 2.

Cимвольная константа - это соответствующий символ, заключенный в апострофы. Оператор А:='A' означает, что символьной переменной с именем А присваивается значение символа А.

Для обозначения символьных констант используется также значок #, действие которого эквивалентно функции CHR. Например, #97 - символ, код которого равен 97 (символ a), #90 - символ, код которого равен 90 (символ Z). Особенно удобно такое обозначение для специальных символов; например, #27 соответствует клавише Esc, #10 -сдвигу курсора на одну строку вниз, #13 - перемещению курсора на левую границу окна; последовательность символов #13#10 соответствует нажатию клавиши Enter.

Рассмотрим массивы символов. Например,

Var L,LP: array[1..10] of char;

Допустимо присваивать значение массиву символов одним оператором, например: L:='ABC '; LP:='1234567890';L:=LP; размеры массивов в левой и правой частях должны совпадать. Разрешено использовать имя массива символов без указания индексов в операторе вывода. Ввод массивов осуществляется только поэлементно.

Над массивами символов определены операции сравнения. Сравнение массивов осуществляется как сравнение последовательностей битов (каждый символ заменяется своим кодом). Допустимо сравнивать только массивы одинаковой длины.

Применительно к массивам символов знак + означает конкатенацию (сцепление) массивов. Оператор L:=L1+L2 показывает, что массив символов L получен присоединением справа к массиву L1 массива L2.

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

3.1.2.Строковые типы


Строковые типы позволяют работать с последовательностью символов переменной длины как с единой конструкцией, причем подсчет текущей длины последовательности осуществляется средой программирования.

Сначала рассмотрим строковый тип string в Турбо Паскале.

Переменная типа string принимает значения на множестве строк символов переменной длины (каждый символ имеет тип char), при описании указывается максимальная длина. Например:

Const M=20;

Var LS: string[М]; {M-максимальная длина строки} (1)

Если максимальная длина строки при описании не указана (отсутствует вместе с квадратными скобками), то по умолчанию она считается равной 255.

Для хранения строки требуется (M+1) байт: нулевой байт используется для хранения текущей длины строки, байты с 1-го по М-й -для хранения символов строки. Допустимо в программе обращаться к любому элементу строки, в том числе к нулевому: LS[i] - i-й элемент строки LS, i=0,1,2,...,M. Выражение ORD(LS[0]) дает текущую длину строки; кроме того, для определения текущей длины строки в имеется встроенная функция length.

Для переменных типа string ввод, вывод, присваивание выполняются не поэлементно, а одним оператором, т.е. допустимы операторы READ(LS);WRITE(LS); LS:='123'. При задании исходных данных для ввода строка ограничивается либо нажатием клавиши "ENTER", либо значением максимальной длины, определенной при описании строки. Длина строки в правой части оператора присваивания может быть произвольной (если она больше максимальной, то происходит отбрасывание "лишних" символов справа). В таких операторах, как, например, ввод и присваивание, где строка рассматривается как единое целое, длина строки (т. е. содержание ее нулевого байта) определяется автоматически. При работе с отдельными элементами строки за длиной строки должен следить программист (см. пример 2).

Для строк определены операции сравнения. Они сравниваются посимвольно, слева направо. Большей считается строка, в которой больше код первого слева несовпадающего символа. Если строки имеют разную длину, то короткая строка дополняется справа символами CHR(0). Напомним, что, в отличие от строк, массивы символов можно сравнивать, только если они имеют одинаковую длину.

Пример1. Вычислить количество слов в строке. Под словом понимается группа символов, не содержащая пробелов. Слова могут разделяться одним или несколькими пробелами.

В приведенной программе мы подсчитываем число "концов слов", т. е. число пар символов "непробел-пробел". Алгоритм (блок-схема на рис.16) предусматривает последовательный в цикле просмотр пар рядом стоящих символов строки, номер первого символа пары меняется от 1 до n-1. n – текущая длина строки. После последнего слова пробел может не стоять – эта ситуация учитывается условным оператором в конце программы.

Таблица 10. Состав данных программы примера 1.

Имя

Смысл

Тип

Структура

Исходные данные

pr

заданная строка

строка

Выходные данные

k

количество слов

целый

простая переменная

Промежуточные данные

i

номер первого символа пары

целый

простая переменная

n

текущая длина строки

целый

простая переменная

program nwd;

var pr:string; {исходная последовательность символов}

n,i,k:integer;{n-длина последовательности, k-число слов,

i-cчетчик символов}

BEGIN readln(pr);

n:=length(pr); k:=0;

for i:=1 to n-1 do

if (pr[i]<>' ') and (pr[i+1]=' ') then k:=k+1;

if pr[n]<>' ' then k:=k+1;

writeln(' ЧИСЛО СЛОВ РАВНО ',k)

END.





Пример 2. Удалить из текста все заглавные латинские буквы.

program dlt;{удаляет из стpоки s заглавные латинские буквы}

Var s :String; n: Integer;{текущая длина стpоки}

i,j: Integer;{счетчики элементов стpоки}

Begin Writeln(' Введите стpоку текста ');

Readln(s); n:=Length(s); i:=1;

Repeat

while (i<=n) and not ((s[i]>='A') and (s[i]<='Z')) do i:=i+1;

{по окончании цикла while i-номеp пеpвой слева заглавной буквы}

If i<=n Then

Begin

If i

For j:=i to n-1 do {все символы, начиная с (i+1)-го,}

s[j]:=s[j+1]; {сдвигаются на одну позицию влево}

s[0]:=CHR(n-1); {необходимо изменить длину стpоки}

{Object Pascal: вместо предыдущего оператора SetLength(s,n-1)}

n:=n-1;

End;

Until i>n;

WriteLn(' Измененная стpока'); Writeln(s);

End.

Объектный Паскаль, как более мощный алгоритмический язык, по сравнению с Турбо Паскалем имеет расширенный набор строковых типов. Данные типа string (эквивалентное название AnsiString) могут содержать до 231 символов типа char. Тип ShortString эквивалентен типу string Турбо Паскаля. Тип WideString соответствует строкам максимальной длины до 230 символов типа widechar. Объектный Паскаль с целью увеличения надежности программ не разрешает менять нулевой байт строки и предлагает для изменения длины строки применять процедуру SetLength(строка, новая_длина_строки) – см. комментарии примера 2.

3.1.3. Подпрограммы, работающие со строками


Рассмотрим лишь некоторые подпрограммы. Они имеются во всех рассматриваемых версиях Паскаля.

Функции

CONCAT(S1 ,S2,...,SN)-функция типа STRING; возвращает строку, представляющую собой сцепление (конкатенацию) строк-параметров S1,S2,...,SN. Конкатенацию строк можно также получить с помощью операции +.

COPY(ST,INDEX,COUNT)-функция типа STRING; копирует из строки ST COUNT символов, начиная с символа с номером INDEX.

LENGTH(ST)-функция типа INTEGER; возвращает длину строки ST.

POS(SUBST,ST)-функция типа INTEGER; отыскивает в строке ST первое вхождение подстроки SUBST и возвращает номер позиции, с которой она начинается; если подстрока не найдена, возвращает нуль.

Процедуры

DELETE(ST,INDEX,COUNT)-удаление COUNT символов из строки ST, начиная с символа с номером INDEX.

INSERT(SUBST, ST, INDEX) - вставка подстроки SUBST в строку ST, начиная с символа с номером INDEX.

STR(X[:WIDTH[:DECIMALS]],ST) -преобразование значения типа REAL или INTEGER в строку символов ST так, как это делает процедура WRITELN перед выводом; параметры WIDTH и DECIMALS, если они присутствуют, задают формат преобразования (WIDTH - длину числа, DECIMALS - длину дробной части; параметр DECIMAL имеет смысл указывать только для вещественных чисел).

VAL(ST, X, CODE) - преобразование строки ST во внутреннее представление целого или вещественного числа Х; параметр CODE содержит нуль, если преобразование прошло успешно, в противном случае он содержит номер символа в строке ST, где обнаружен ошибочный символ; пробелы перед числом в строке ST должны отсутствовать.

Одной из практически важных задач, решаемых с помощью строковых типов, является задача обработки данных сложной структуры. Эти данные часто собраны в таблицу. Строка таблицы соотвествует некоторому объекту исследования: товару, человеку, предприятию. Строка, несмотря на то, что состоит из символов, содержит смысловые данные разного типа; например, наименование товара имеет символьный тип, его стоимость – вещественный, и т. д.

Для обработки такой строки необходимо выделить ее смысловые поля-подстроки (с помощью функции COPY), перевести некоторые поля из символьного представления в числовое (с помощью процедуры VAL). Затем, возможно, потребуется проанализировать символьные поля с помощью функции POS и подготовить строку выходных данных с помощью STR и CONCAT.

Ниже рассматривается пример такой задачи.

Пример. Сведения об игрушках представлены в виде таблицы:

N

название игpушки

миним. возраст

максим.

возраст

цена

(руб.)

1

Конструктор "Юность-3"

4

10

70

2

LEGO (конструктор)

3

7

200

3

Кукла

2

5

50














2 с.

29 символов

8 симв.

8 симв.

8 симв.

Последняя строка таблицы не относится к исходным данным, в ней задается ширина столбцов в символах без учета разделителей между столбцами.

Определить самый дорогой конструктор для детей в возрасте до семи лет и его стоимость.

Program Primer3_1_3;

VAR N:Integer;{число строк таблицы}

TABL:String[60];{строка таблицы–содержимое столбцов +5 разделителей}

nu:String[2]; {подстрока-номер игрушки}

name:String[29]; {подстрока-название игрушки}

MinAge,MaxAge,Rub:String[8]; {подстроки: мин. и макс. возраст,цена}

max:Real; {максимальная стоимость конструктора}

MaxAR,RubR:Real;{макс.возраст и стоимость в веществен. представлении}

namemax:String[29];{название конструктора с максимальной ценой}

i {счетчик игрушек},

C {номер ошибочного символа при преобразовании строки в число} :Integer;

BEGIN

Writeln(' Введите число наименований игpушек');

ReadLn(N);

max:=0;

Writeln('Вводите сведения об игpушках в виде таблицы');

Writeln(

'┌─┬─────────────┬─────┬─────┬────┐');

Writeln(

'|N | название игpушки | миним. | макс. | стои- |');

Writeln(

'| | | возpаст |возpаст |мость |’);

Writeln(

'├─┼─────────────┼─────┼─────┼────┤');

For i:=1 to N Do

BEGIN

Readln(TABL);

name:=Copy(TABL,5,29); {выделение подстрок названия}

MaxAge:=Copy(TABL,44,8); {и максимального возраста}

Val(MaxAge,MaxAR,C); {преобразование строка - число }

If C<>0 Then

Writeln(' ошибка в',C,'-й позиции MaxAge')

Else

Begin

If ((Pos('констpуктоp',name)>0) or {входит ли в название}

(Pos('Констpуктоp',name)>0)) and {слово "конструктор"}

(MaxAR<=7) Then

Begin

Rub:=Copy(Tabl,53,8); {выделение подстроки цены}

Val(Rub,RubR,C); {преобразование строка-число}

If C<>0 Then

Writeln(' ошибка в',C,'-й позиции Rub')

Else

Begin

If RubR>max Then {определение текущего значения}

BEGIN {максимальной цены}

max:=RubR;

namemax:=name{запомнили конмтруктор с макс. ценой}

END;

End

End

End

END;

If max=0 Then

WriteLn(' Констpуктоpов для детей до семи лет нет')

Else

BEGIN

WriteLn('Cамый доpогой констpуктоp для детей до семи лет');

STR(max:6:2,Rub);{перевод max в строку}

WriteLn(CONCAT(namemax, ' стоит ',Rub, ‘ рублей’);

END;

END.

При обработке таблиц большого объема эта программа имеет, по крайней мере, два недостатка:

  1. количество строк таблицы задается вводом (но ручной подсчет количества строк таблицы – это достаточно большой труд);

  2. ввод данных происходит с экрана, хотя, конечно, лучше хранить данные в файле на внешнем носителе и осуществлять ввод из файла.

Эти недостатки можно устранить, используя тип файл (см. §3.3).
1   2   3   4   5   6   7   8   9   10


написать администратору сайта