Смекни!
smekni.com

Паскаль обробка текстів (стр. 2 из 4)

Тепер розглянемо читання числових послідовностей, записаних у текстах. Найбільш природним є таке подання послідовності вхідних даних, у якому кінець послідовності визначається кінцем файла. У цьому випадку читання описується за допомогою функції eof у циклі вигляду

whilenot eof(f) do

begin

read(f, v);

обробка значення змінної v

end.

З виклику eof(f) повертається значення true, якщо доступним є кінець файла. За такої організації читання слід забезпечити, щоб між останньою числовою сталою та кінцем файла не було порожніх символів. Якщо цього не зробити, то в системі Турбо Паскаль буде прочитано зайве нульове значення.

Якщо файл порожній, то перше ж виконання виклику eof(f) породжує true, і тіло циклу не виконується жодного разу. Змінна v залишається зі старим значенням. А якщо значення їй не було присвоєно, то можливі непередбачувані помилки.

Звернімо увагу, що читання в циклі відбувається після того, як із виклику функції eof повернулося значення false, тобто кожному читанню передує перевірка, чи не є файл прочитаним. Ми радимо завжди записувати програми так, що при їх виконанні спочатку перевіряється, що з файла можна читати, і лише тоді читається.

Приклад 3. У тексті записано дійсні числа, розділені порожніми символами. Обчислити їх середнє арифметичне.

Кількість чисел нічим не обмежена, тому скористаємося циклом із перевіркою ознаки кінця тексту. За порожнього тексту друкується 0:

n:=0; A:=0;

whilenot eof(f) do

begin

read(f, x); n:=n+1;

A:=A+x; {}

end;

if n>0 then A:=A/n;

writeln(A).

Зауважимо, що сума чисел у тексті може бути непредставною навіть у типі real, хоча їх середнє не більше максимального з них. Середнє арифметичне варто обчислювати інакше.

Отже, замість оператора A:=A+x у циклі напишемо оператор

A:=(n-1)/n*A+x/n,

що виконується за n>0, і вилучимо оператор if n>0 then A:=A/n. -

Задачі

3.* Яких значень набудуть дійсні змінні a, b, c, d і який символ стане доступним після виконання викликів

а) read(f, a, b, c, d),

б) readln(f, a, b); read(f, c, d),

в) readln(f, a, b); readln(f, c); readln(f, d),

якщо з доступного символу в тексті починається послідовність

1[13][10] -2.9 +13[13][10]2000 777[13][10][26]

4.* Написати програму підрахунку кількості рядків у тексті.

5.* Результат лижника в перегонах задається трійкою цілих у одному рядку тексту: його стартовим номером та кількістю хвилин і секунд. Кількість рядків із результатами необмежена. Після кожного результату треба вивести на екран поточну десятку найкращих (якщо результатів менше, то подати наявні).

6. Є два тексти, у кожному рядку яких записано натуральне число, і послідовності цих чисел неспадні. Записати в третій текст неспадну послідовність чисел, що є результатом злиття двох заданих. Числа у вихідному тексті вивести по 10 на рядок (останній рядок може бути неповним). Наприклад, за заданих послідовностей (2, 2, 4, 6), (1, 3, 6, 7) у текстах створюється послідовність (1, 2, 2, 3, 4, 6, 6, 7).

4. Особливості читання символів і рядків із тексту

При виконанні виклику read(f, X) за змінної X типу char їй присвоюється доступний символ тексту, яким би він не був, а доступним стає наступний за ним. Виключенням є випадок, коли доступний кінець файла: значенням X стає символ chr(26), і він же залишається доступним. Отже, при читанні символів пропуски, табуляції та кінці рядків обробляються так само, як і всі інші символи.

Приклад. Розглянемо виконання такої програми:

program eofad;

const eo=chr(26);

var f : text; ch : char;

begin

assign(f, 'eofad.dat'); rewrite(f);

writeln(f, 'abc', eo, 'qq'); {запис 6 символів у файл}

close(f);

reset(f);

whilenot eof(f) do {у тексті є доступний символ, і він не є chr(26)}

begin

read(f, ch); {доступний символ файла читається в змінну ch}

write(ch)

end;

close(f);

readln;

end.

За її виконання на екрані буде надруковано лише abc. Справа в тім, що після того, як прочитано символ c, доступним стає chr(26). Далі виконується виклик eof(f), з нього повертається значення true, і виконання циклу закінчується. -

Якщо X рядкового типу, то при виконанні виклику read(f, X) символи до найближчого eol читаються та присвоюються елементам X; доступним стає eol, тобто chr(13) в системі Турбо Паскаль. Якщо символів тексту до eol більше, ніж уміщається в X, то X заповнюється до кінця, і доступним стає перший символ за тими, що прочитано в X.

Якщо перед читанням рядка X доступний eol, то він залишається доступним, а значенням X стає порожній рядок. Ось чому ми рекомендуємо не застосовувати процедуру read при читанні рядків.

Особливо небезпечним є застосування read при введенні рядків у циклі. Якщо після введення рядка доступним символом стане eol, то за подальших уведень рядків вони одержуватимуть значення '' (порожній рядок), eol залишиться доступним і виконання програми може "зациклитися". Наприклад, при виконанні циклу вигляду

whilenot eof(f) do

begin

read (f, x); { ???}

обробка x

end,

де x – змінна-рядок, читаються лише символи першого рядка тексту, після чого кінець рядка залишається доступним "назавжди". Цикл собі виконується, комп’ ютер "висить", а користувач програми починає нервувати й лаятися.

Коли при читанні рядка доступний кінець тексту, він аналогічно залишається доступним, а змінній-рядку присвоюється значення '' (порожній рядок).

Читання символів і рядків за процедурою readln аналогічне процедурі read, але після читання символів решта рядка тексту пропускається, тобто доступним стає символ, наступний за найближчим eol. Радимо задавати читання рядків за допомогою процедури readln.

Список імен змінних у виклику може бути порожнім; у такому разі при виклику readln(f) пропускається поточний рядок тексту.

Приклад 4. Нехай діють означення

f : text; c1, c2 : char; s1, s2 : string[4],

а eol явно позначає кінець рядка в тексті, з яким зв’ язано f:

t r u e eol
f a l s e eol
eol

Після виклику

read (f, c1, c2, s1, s2 )

змінні набудуть значень: c1=' ', c2='t', s1='rue' та s2=''; доступним буде перший із указаних eol. Якщо далі виконати read(f, c1, c2), то значеннями с1 і c2 будуть chr(13) і chr(10), а доступним стане символ f.

За такого самого тексту виклик

readln (f, s1, c1, c2, s2 )

надає змінним значень s1=' tru', c1='e', c2=chr(13), s2=chr(10)+'fal'. Символи 's' і 'e' пропускаються, і доступним стає третій eol, тобто chr(13). -

Задачі

7.* Указати значення, одержані пpи читанні тексту f змінними

var c, c1 : char; i : integer; r : real; s, s1, s2 : string,

пpи виконанні послідовності опеpатоpів

read( f, c, i, r, s );

readln( f, s1 ); readln( f, s2 );

readln( f, c1 ),

якщо текст, починаючи від доступного символу, містить послідовність символів:

eol 1 2 . 1 eol l e s s o n eol x eol y eol eol

Указати також доступний символ тексту після читання.

5. Читання тексту з рядками обмеженої довжини

У багатьох текстах довжина рядків неоднакова, але обмежена, як правило, числом, що не перевищує 255 – максимальну довжину рядків типу string. Використання змінних цього типу дозволяє дуже просто описувати читання текстів.

Алгоритми розв’ язання задач із обробки таких текстів часто мають загальний вигляд

whilenot eof(f) do

begin

readln(f, s); {s має тип string}

обробка рядка s;

end.

Приклад 5. Написати процедуру копіювання тексту за умови, що рядки тексту мають довжину не більше 80, а рядки порожні або такі, що містять лише пpопуски, не копіюються.

Після читання чергового рядка початкового тексту треба визначити, чи є в ньому хоча б один символ, відмінний від пропусків. Тільки в цьому випадку він копіюється в текст g:

procedure cpnonemp( var f, g : text);

var s : string[80];

k : integer; emp : boolean;

begin

whilenot eof(f) do

begin

readln(f, s); k:=1; emp:= true;

while (k<= length(s)) and emp do

if s[k]<>' ' then emp:= false

else k:=k+1;

ifnot emp then writeln(g, s)

end

end;

Задача

9. На вхід програми подається послідовність груп рядків тексту. Групи відділяються рядком із першим символом '='. За останньою групою такого рядка може не бути. Група може бути порожньою. Рядки в групах непорожні й містять числа, відокремлені пропусками в довільній кількості. Всі рядки разом із наступними повідомленнями треба виводити в інший текст. Якщо в рядку 3 числа, то слід визначити, чи задають вони довжини сторін трикутника, і надрукувати повідомлення "трикутник" або "не трикутник". За іншої кількості чисел треба повідомити: "помилкові дані" (див. задачу 12.17). Для кожної групи слід надрукувати слова "кількість рядків: " і число її рядків, що задають трикутники, та рядок, яким група відокремлена від наступної. Для останньої групи такий рядок не друкується. Наприклад, за послідовності рядків

2 3 4

1 3 5

=123=

=

1

1 2 3 4

= = =

треба надрукувати в іншому тексті

2 3 4

трикутник

1 3 5

не трикутник

кількість трикутників: 1

=123=

кількість трикутників: 0

=

1

помилкові дані

1 2 3 4

помилкові дані

кількість трикутників: 0

6. Посимвольне читання тексту

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