Учебная работа. Реферат: Тип STRING
Тип STRING
Тип STRING — это строковый тип в Паскале. Строчкой именуется последовательность знаков. Строковыми константами вы уже не один раз воспользовались — это последовательность всех знаков, заключенная в апострофы; допускаются и пустые строчки, они записываются так: ». Строковые переменные и типизированные константы описываются в виде
STRING
либо
STRING [ максимальная длина ]
Если наибольшая длина не задана, то по дефлоту она берется равной 255. Наибольшая длина при описании строковых данных задается целочисленным постоянным выражением и никогда не может превосходить 255. Это ограничение обосновано самой структурой типа STRING : практически строчка — это массив ARRAY [ Byte ] OF Char, при этом в 0-м знаке закодирована текущая длина строчки. Строковые переменные могут иметь всякую длину от 0 до наибольшей. В программке строчки можно применять и как единый структурированный объект (чуток позднее мы познакомимся с различными способностями обработки строк), и как массив знаков, т.е. обращаться к элементам строк следует так же, как к элементам массивов. Для строк определены последующие операции :
— строке можно присвоить строчку;
— строчки можно вводить процедурой READLN;
— строчки можно выводить процедурой WRITE[LN];
— для строк определена операция сцепления +, при всем этом 2-ая строчка дописывается справа к первой и длина результата становится равной сумме длин операндов (если она не превосходит 255).
Запишем программку, выполняющую простые операции со строчками:
TYPE ShortString = STRING[80];
VAR s1,s2 : ShortString; s3 : STRING;
BEGIN WRITE(‘Введите 1-ю строчку ‘); READLN(s1);
WRITE(‘Введите 2-ю строчку ‘); READLN(s2);
WRITELN(‘Вы ввели ‘,s1,’ и ‘,s2); WRITELN(‘s1+s2=’,s1+s2);
s3:=s1+s1+s1; WRITELN(‘s1,повторенная 3 раза ‘,s3);
END.
Обратите внимание, что при вводе строк постоянно употребляется READLN, но не READ. Процедура READ в отличие от READLN считывает только знаки до знака конца строчки (кнопка Enter), который остается в буфере клавиатуры. Таковым образом, пользуясь процедурой READ можно ввести лишь одну строчку; все строчки, вводимые вослед за первой, станут пустыми. к примеру, программка
VAR s1,s2 : STRING;
BEGIN WRITE(‘Введите 1-ю строчку ‘); READ(s1);
WRITE(‘Введите 2-ю строчку ‘); READ(s2);
WRITELN(‘Вы ввели «‘,s1,'» и «‘,s2,'»‘);
END.
при входном потоке abcdef Enter 123456 Enter выведет : Вы ввели «abcdef» и «». Запишем сейчас программку, которая вводит некую строчку, подменяет в ней все числа на пробелы и дописывает в конец строчки знаки «???»:
VAR s : STRING; L,i : Byte;
BEGIN WRITE(‘Введите строчку ‘); READLN(s);
L:=ORD(s[0]);
FOR i:=1 TO L DO IF s[i] IN [‘0′..’9′] THEN s[i]:=’ ‘;
FOR i:=L+1 TO L+3 DO s[i]:=’?’;
WRITELN(‘Вот что вышло : ‘,s);
END.
Наша программка заменила числа, но никаких «?» не добавила. Дело в том, что, обращаясь к элементам строчки, нереально поменять текущую длину строчки. 2-ой цикл нашей программки сработал верно, записав знаки «?» в надлежащие элементы строчки, но длина строчки осталась прежней, и процедура WRITELN вывела лишь знаки с 1-го по L-й. Чтоб решить задачку корректно, мы могли бы добавить в программку один оператор INC(s[0],3); но, естественно, лучше всего просто записать: s:=s+’???’; .
Для обработки строк в Паскале существует несколько обычных функций и процедур :
1. FUNCTION Length(S: String): Integer; — возвращает длину строчки.
2. FUNCTION Concat(S1[,S2,…,Sn]: String): String; — возвращает строчку, полученную сцеплением аргументов, может употребляться заместо операции «+».
3. FUNCTION Pos(Substr: String; S: String): Byte; — возвращает номер первого слева знака строчки S, начиная с которого строчка Substr заходит в S, если Substr не заходит в S, то
4. FUNCTION Copy(S: String; Index: Integer; Count: Integer): String; — возвращает подстроку строчки S, которая начинается с знака с номером Index и имеет длину Count.
5. PROCEDURE Delete(VAR S: String; Index: Integer; Count:Integer); — удаляет из строчки S подстроку, начинающуюся с знака с номером Index и имеющую длину Count.
6. PROCEDURE Insert(Substr: String; VAR S: String; Index: Integer); — вставляет в строчку S подстроку Substr начиная с знака с номером Index.
Из вышеизложенного понятно, что процедуры и функции могут иметь характеристики типа STRING (что логично), но также допустимы функции типа STRING, хотя это и не скалярный тип. Еще две обычные процедуры предусмотрены для перевода строчки в число и числа в строчку:
7. PROCEDURE Val(S: STRING;VAR V; VAR Code: Integer); — конвертирует строчку S в число V (если это может быть); V — неважно какая переменная арифметического типа, переменная Code возвращает 0, если преобразование прошло удачно, либо номер первого неверного знака строчки.
8. PROCEDURE Str(X [: Width [: Decimals ]];VAR S:STRING); — конвертирует случайное арифметическое выражение X в строчку S, характеристики Width и Decimals разрешают форматировать строчку и имеют таковой же смысл, как и в процедуре WRITE[LN] .
сейчас, зная функцию Val, вы сможете организовать надежный ввод числовых данных в хоть какой собственной программке. Представим, что программка обязана вводить вещественное
VAR F : Real; … BEGIN WRITE(‘Введите F ‘); READ(F);
Если юзер верно введет число, то все будет в порядке, но если он неверно нажмет не ту кнопку (к примеру, запятую заместо точки и т.п.), то произойдет аварийное прерывание, программка закончится, и на дисплее покажется сообщение «Run-time error …». Программки, таковым образом реагирующие на неправильный ввод, — нехорошие! Не плохая программка должна обрабатывать нажатие фактически всех кнопок в всех композициях. Мы полностью способны написать такую программку :
VAR F : Real; S : STRING; Code : Integer; …
BEGIN REPEAT
WRITE(‘Введите F ‘); READLN(S);
Val(S,F,Code); IF Code=0 THEN Break;
WRITELN(‘Ошибка ввода!’);
UNTIL FALSE;
Решим нередко встречающуюся задачку о распаковке текста: дана строчка, содержащая текст на российском языке (либо на любом другом языке, в том числе и искусственном — вы увидите, что это не принципно); необходимо выделить слова, находящиеся в этом тексте. Хотя эта задачка и тривиальна, ее решение не настолько элементарно и просит подготовительной разработки метода. Поначалу уясним, что такое текст. Текстом будем именовать последовательность слов, разбитых хоть каким количеством «пробелов». слова — это последовательности букв языка (в нашем случае — российских букв), «пробелы» — любые знаки, не являющиеся знаками. Итак, наш текст в общем случае имеет вид : *X*X…*X* , где X — слово, * — «пробел». Можно предложить последующий метод распаковки:
1) удалим оканчивающие пробелы, опосля чего же текст воспримет постоянный вид *X*X…*X;
2) удалим фаворитные пробелы;
3) выделим 1-ое слово и удалим его из текста.
Опосля выполнения пт 2 и 3 мы получили одно слово и текст стал короче на одно слово, сохранив при всем этом свою структуру. Разумеется, что пункты 2 и 3 следует делать до того времени, пока текст не пуст. Запишем программку, реализующую этот метод.
VAR s : STRING; i : Byte;
CONST Letters : SET OF Char = [‘а’..’п’,’р’..’я’,’А’..’Я’]; {это алфавит}
BEGIN WRITE(‘Введите текст ‘); READLN(s);
{ удалим оканчивающие пробелы, тут есть 1 ОШИБКА! }
WHILE NOT(s[Length(s)] IN Letters) DO Delete(s,Length(s),1);
WRITELN(‘слова текста :’);
{ организуем цикл ПО (то есть программное обеспечение — комплект программ для компьютеров и вычислительных устройств) СЛОВАМ }
WHILE s<>» DO BEGIN
{ удалим фаворитные пробелы }
WHILE NOT(s[1] IN Letters) DO Delete(s,1,1);
{ найдем границу первого слова, тут есть 1 ОШИБКА! }
i:=1; WHILE s[i] IN Letters DO INC(i);
{ i — номер первого пробела }
Dec(i);
{ выведем слово }
WRITELN(Copy(s,1,i));
{ удалим слово из текста }
Delete(s,1,i);
END;
END.
На 1-ый взор наша программка работает верно (мы ввели фразу на российском языке и получили все слова из нее), но тестирование программки непременно обязано включать все предельные, либо особые, случаи. Введем, к примеру, строчку, не содержащую никаких слов, и программка зациклится! Это итог ошибки в первом цикле: если в тексте нет букв, все знаки из него будут удалены, длина строчки станет равной нулю, и в предстоящем станет проверяться знак с номером 0, который равен #0 и, естественно, не является буковкой. Еще одна ошибка подобного рода может произойти при выделении крайнего слова: мы увеличиваем индекс i, пока i-й знак — буковка, и в конце концов дойдем до конца строчки. Но переменная s постоянно содержит 255 знаков, знаки с номерами Length(s)+1, Length(s)+2 и т.д. есть, и нет никаких гарантий, что они не являются русскими знаками. В этом случае мы можем получить крайнее слово с «хвостом». Исправим нашу программку:
VAR s : STRING; i : Byte;
CONST Letters : SET OF Char = [‘а’..’п’,’р’..’я’,’А’..’Я’]; {это алфавит}
BEGIN WRITE(‘Введите текст ‘); READLN(s);
{ удалим оканчивающие пробелы }
WHILE NOT(s[Length(s)] IN Letters)AND(s<>») DO Delete(s,Length(s),1);
IF s=» THEN BEGIN WRITELN(‘текст пуст’); Halt; END;
WRITELN(‘Слова текста :’);
{ организуем цикл ПО (то есть программное обеспечение — комплект программ для компьютеров и вычислительных устройств) СЛОВАМ }
WHILE s<>» DO BEGIN
{ удалим фаворитные пробелы }
WHILE NOT(s[1] IN Letters) DO Delete(s,1,1);
{ найдем границу первого слова }
i:=1; WHILE (s[i] IN Letters)AND(i<=Length(s)) DO INC(i);
{ i — номер первого пробела }
Dec(i);
{ выведем слово }
WRITELN(Copy(s,1,i));
{ удалим слово из текста }
Delete(s,1,i);
END;
END.
Сейчас запишем то же самое, используя функции и процедуры :
VAR s : STRING; i : Byte;
CONST Letters : SET OF Char = [‘а’..’п’,’р’..’я’,’А’..’Я’]; {это алфавит}
PROCEDURE DelTail(VAR s:STRING);
BEGIN WHILE NOT(s[Length(s)] IN Letters)AND(s<>») DO Delete(s,Length(s),1); END;
PROCEDURE DelLead(VAR s:STRING);
BEGIN WHILE NOT(s[1] IN Letters) DO Delete(s,1,1); END;
FUNCTION MakeWord(s:STRING; VAR Bound:Byte):STRING;
BEGIN Bound:=1;
WHILE (s[Bound] IN Letters)AND(Bound<=Length(s)) DO INC(Bound);
Dec(Bound); MakeWord:=Copy(s,1,i); END;
BEGIN WRITE(‘Введите текст ‘); READLN(s);
{ удалим оканчивающие пробелы }
DelTail(s);
IF s=» THEN BEGIN WRITELN(‘текст пуст’); Halt; END;
WRITELN(‘Слова текста :’);
{ организуем цикл ПО (то есть программное обеспечение — комплект программ для компьютеров и вычислительных устройств) СЛОВАМ }
WHILE s<>» DO BEGIN
{ удалим фаворитные пробелы } DelLead(s);
{ выведем слово } WRITELN(MakeWord(s,i));
{ удалим слово из текста } Delete(s,1,i);
END;
END.
]]>