REFERATUA.ORG.UA — База українських рефератів




показують зміну станів залежно від останнього прочитаного символу. Кожну стрілку відмічено дробом: угорі вказано символ, унизу – його обробку. Символ  позначає довільний символ, відмінний від '(' ,  – відмінний від '(' та '*',  – від '*' та ')'.

Початковим станом тексту природньо вважати out. Копіювання тексту з вилученням коментарів можна імітувати пересуванням по діаграмі та виконанням дій, указаних на стрілках. На кожному кроці імітації читається черговий символ тексту і згідно діаграми за ним та поточним станом визначаються дії та зміна стану.

За наведеними таблицею чи діаграмою неважко побудувати програму копіювання тексту з вилученням коментарів. У програмі переписано зміст таблиці за допомогою case-операторів. Нехай змінна ch зберігає останній прочитаний символ, а g є ім' ям тексту-копії. Означимо тип-перелік станів:

type States=(out, bgn, incm, bgend)

та змінну q цього типу. Спочатку q:=out. А далі

whilenot eof(f) do

begin

read(f, ch);

case q of

out: case ch of

'(': q:=bgn

else write(g, ch)

end;

bgn: case ch of

'(': write(g, '(');

'*': q:=incm

else

begin

write(g, '(', ch); q:=out

end;

end;

incm: case ch of

'*': q:=bgend

end;

bgend: case ch of

'*': ;

')': q:=out

else q:=incm

end;

end; {case q of}

end; {while not eof(f) }

Як бачимо, виконання наведеного циклу відповідає описаній вище імітації діаграми. Оформлення програми залишаємо вправою.

7. Використання рядків для виведення в текст

Приклад9. Редактор Word символом chr(13) задає розбиття текстів не на рядки, а на абзаци. З точки зору редактора ДОС або Турбо Паскаль такий абзац є рядком, причому, як правило, дуже довгим, і читати його незручно. Напишемо програму копіювання тексту з довгими рядками в текст із рядками довжини не більше ніж, наприклад, 80.

Уточнення. Пропуски, кінці рядків і символи табуляції будемо називати пропусками. Можна вважати, що послідовності символів, відмінних від пропусків, у тексті, тобто слова, мають довжину не більше 80. Слова в тексті відокремлюються пропусками в довільній кількості. У новому тексті між словами рядка повинен бути один пропуск, тобто текст має ущільнюватися.

У загальному вигляді розв' язання задачі полягає в тім, що з тексту по одному "витягуються слова" й записуються в новий текст.

Якщо читання слова задати функцією getlex, яка повертає ознаку наявності слова, а запис слова – процедурою putlex, то головним у програмі буде цикл вигляду

while getlex do putlex.

Отже, прочитане слово треба записати в новий текст. Але замість цього запишемо його в допоміжний рядок довжини 80, який назвемо "рядок слів".

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

Наведений алгоритм уточнюється далі у вигляді процедури putlex.

Для того, щоб "витягнути" слово з тексту, треба прочитати пропуски й накопичити в рядку-слові символи-не пропуски, що йдуть поспіль до наступного пропуска або до кінця тексту.

Серед пропусків, що читаються, можуть бути кінці рядків. Перший із них означає, що треба переписати накопичений рядок слів у новий текст, а всі інші – що записати порожній рядок. І тільки після цього записувати нове слово з початку рядка слів. Таким чином, читаючи пропуски, треба підраховувати кінці рядків.

Нехай str – це ім' я типу string[80]. Читання чергового слова уточнимо у вигляді наступної функції getlex. Символами-пропусками у ній вважаються символи табуляції chr(9), переведення рядка chr(10), нового рядка chr(13) і власне пропуск chr(32). Її останній параметр nume зберігає кількість кінців рядків, що передували знайденому слову. Ця кількість використовується на початку виконання процедури putlex.

function getlex(var f : text; var lex : str; var nume : integer) : boolean;

const empsym : setof char=[chr(9), chr(10), chr(13), chr(32)];

var c : char; inlex : boolean;

begin

lex:=''; inlex:=false; nume:=0;

whilenot eof(f) andnot inlex do

begin

if eoln(f) then

begin inc(nume); readln(f) end

else

begin read(f, c); inlex:=not (c in empsym) end;

end;

while inlex do

begin

lex:=lex+c;

ifnot eof(f) then

begin

if eoln(f) then inlex:=false

else begin read(f, c); inlex:=not (c in empsym) end;

end

else inlex:=false

end;

getlex:=(lex<>'');

end;

Запис накопиченого рядка слів (глобальна змінна з ім' ям buff) у текст задамо такою процедурою:

procedure outbuff(var f : text);

begin

writeln(f, buff); buff:=''; bp:=1;

end;

Як уже зазначалося, запис слова в рядок слів задається процедурою putlex:

procedure putlex(var f : text; lex : str; nume : integer);

var llx, k : integer;

begin

if nume > 0 then

outbuff(f);

for k:=1 to nume-1 do

writeln(f);

llx:=length(lex);

if (bp>1) and (bp+llx>mx) then

outbuff(f)

else

if buff<>'' then

begin

buff:=buff+' '; bp:=bp+1;

end;

buff:=buff+lex; bp:=bp+llx;

end;

Нарешті, програма копіювання тексту з перетворенням рядків має вигляд:

program f80;

const mx=80;

type str=string[mx];

var f, g : text;

const buff : str=''; bp : integer=1;

var lex : str; nume : integer;

function getlex(var f : text; var lex : str; var nume : integer):boolean;

...

end;

procedure outbuff(var f : text);

...

end;

procedure putlex(var f : text; lex : str; nume : integer);

...

end;

begin

assign(f, 'in.txt'); assign(g, 'out.txt');

reset(f); rewrite(g);

while getlex(f, lex, nume) do

putlex(g, lex, nume);

if buff<>'' then outbuff(g);

close(f); close(g);

end.


 
Загрузка...