| Назва: | Ідея буферизації |
| Тип: | Реферати |
| Мова: | Українська |
| Розмiр: | 14,19 KB |
| Скачувань: | 8 |
Приклад 15.1. Розглянемо програму
program GreatBufferManager;
var f : text; Hugebuf : array[1..2]of char;
x, y : char; s : string[4];
begin
assign(f, 'huge.dat'); settextbuf(f, hugebuf, 4);
x:='x'; y:='y';
reset(f); readln(f, s);
writeln('x=', x, '; y=', y);
readln;
end.
Якщо першим рядком тексту в файлі huge.dat є 'qwer', то за виконання цієї програми на екрані з' явиться зовсім не очікуване
x=x; y=y,
а на перший погляд досить дивне
x=e; y=r.
Справа в тім, що змінні x і y фізично розташовані безпосередньо за масивом Hugebuf, і читання чотирьох символів рядка файла в цей буфер призводить до заповнення не тільки масиву, а й змінних за ним. Якщо зробити рядок у файлі трошки довшим, то, запевняємо читача, результати будуть ще несподіванішими. Але не захоплюйтесь, це може стати небезпечним для програми GreatBufferManager.
При виведенні в текст символи накопичуються у внутрішньому буфері, який скидається в зовнішній буфер у разі заповнення або виконання процедури writeln чи close. Можна також задати примусове скидання внутрішнього буфера тексту f викликом процедури FLUSH(f). Його варто записувати для періодичного виконання, а також після всіх виведень у файл. Підкреслимо, що за виклику процедури flush лише скидається внутрішній буфер у зовнішній. Скидання зовнішнього буфера при цьому відбувається лише у випадку його заповнення.
Якщо в кінці роботи з файлом не указати викликів flush чи close, то зміст внутрішнього буфера так і не потрапить у зовнішній буфер і у файл.
Приклад 2. Здається, наступна програма задає копіювання текстів:
program wrongcpy;
var f, g : text; c : char;
begin
assign(f, ...); assign(g, ...); reset(f); rewrite(g);
while not eof(f) do
begin read(f, c); write(g, c) end;
{тут не вистачає close(g) ! Хоча й close(f) не завадить...}
end.
Спробуйте цю програму запустити, і побачите, що якщо початковий файл - пісня, то файл-"копія" - теж пісня, але недоспівана. А все тому, що "кінець пісні" так і залишається у внутрішньому буфері.
Змінну під внутрішній буфер варто означати глобальною в програмі. Якщо означити та зв' язати файлову змінну в програмі, а її внутрішній буфер означити у підпрограмі, то по закінченні виклику підпрограми файлова змінна буде доступною, а її буфер - ні. Спроба скидання з такого буфера по закінченні програми може призвести до непередбачених наслідків. Але якщо вся робота з файлом, від assign до close, описана в підпрограмі, то й буфер цілком природньо означити в ній же.
Приклад 3. Розглянемо програму з процедурою spoilbuf, тобто "зіпсувати буфер", за виклику якої змінюється буфер, що залишається в локальній пам' яті після закінчення попередньої процедури fillbuf.
program foolish;
var f : text;
procedure fillbuf;
var buf : array[1..5]of char;
begin
settextbuf(f, buf); rewrite(f); write(f, 'abcdefgh');
end;
procedure spoilbuf;
begin end;
begin
assign(f, 'boo.dat'); fillbuf; spoilbuf;
close(f)
end.
При виконанні виклику fillbuf символи abcde заповнюють внутрішній буфер і скидаються в зовнішній. Потім, уже при виконанні close(f) вони з' являються у файлі boo.dat. Але символи fgh залишаються у внутрішньому буфері після закінчення fillbuf і псуються під час виконання spoilbuf. Зіпсований буфер скидається при закриванні файла f, і потім замість fgh ми бачимо у файлі щось зовсім на них не схоже.
Задачі
15.1. Написати процедуру копіювання текстів із власними внутрішніми буферами розміром у 16 блоків, тобто 8192 байти, або 8K.
15.2. Написати процедуру побайтового порівняння текстів із власними внутрішніми буферами.
3. Буферизація екрана та клавіатури
Екран і клавіатура є текстами, зв' язаними з файловими змінними output і input. Для роботи з ними також уживаються буфери.
Спочатку розглянемо екран. З ним зв' язаний буфер, але символи, потрапивши в нього, одразу копіюються на екран. Якби цього не було, інформація на екрані з' являлася би з небажаними затримками.
При виконанні процедури WRITE за значенням її кожного аргумента обчислюється стала, тобто послідовність символів, які через буфер одразу виводяться на екран. Насправді, виклик
write(E1, E2, … , EN )
виконується як послідовність викликів
write ( E1 ); write ( E2 ); … ; write ( EN ).
Виконання writeln відрізняється тим, що в буфер екрана "додається eol", і курсор переводиться в наступний рядок.
Організація роботи з клавіатурою набагато складніше. Символи, утворені натисканням клавіш, накопичуються в буфері клавіатури. Він уміщає 15 символів. У цьому можна переконатися, запустивши програму
uses crt;
begin delay(16000) end.
program GreatBufferManager;
var f : text; Hugebuf : array[1..2]of char;
x, y : char; s : string[4];
begin
assign(f, 'huge.dat'); settextbuf(f, hugebuf, 4);
x:='x'; y:='y';
reset(f); readln(f, s);
writeln('x=', x, '; y=', y);
readln;
end.
Якщо першим рядком тексту в файлі huge.dat є 'qwer', то за виконання цієї програми на екрані з' явиться зовсім не очікуване
x=x; y=y,
а на перший погляд досить дивне
x=e; y=r.
Справа в тім, що змінні x і y фізично розташовані безпосередньо за масивом Hugebuf, і читання чотирьох символів рядка файла в цей буфер призводить до заповнення не тільки масиву, а й змінних за ним. Якщо зробити рядок у файлі трошки довшим, то, запевняємо читача, результати будуть ще несподіванішими. Але не захоплюйтесь, це може стати небезпечним для програми GreatBufferManager.
При виведенні в текст символи накопичуються у внутрішньому буфері, який скидається в зовнішній буфер у разі заповнення або виконання процедури writeln чи close. Можна також задати примусове скидання внутрішнього буфера тексту f викликом процедури FLUSH(f). Його варто записувати для періодичного виконання, а також після всіх виведень у файл. Підкреслимо, що за виклику процедури flush лише скидається внутрішній буфер у зовнішній. Скидання зовнішнього буфера при цьому відбувається лише у випадку його заповнення.
Якщо в кінці роботи з файлом не указати викликів flush чи close, то зміст внутрішнього буфера так і не потрапить у зовнішній буфер і у файл.
Приклад 2. Здається, наступна програма задає копіювання текстів:
program wrongcpy;
var f, g : text; c : char;
begin
assign(f, ...); assign(g, ...); reset(f); rewrite(g);
while not eof(f) do
begin read(f, c); write(g, c) end;
{тут не вистачає close(g) ! Хоча й close(f) не завадить...}
end.
Спробуйте цю програму запустити, і побачите, що якщо початковий файл - пісня, то файл-"копія" - теж пісня, але недоспівана. А все тому, що "кінець пісні" так і залишається у внутрішньому буфері.
Змінну під внутрішній буфер варто означати глобальною в програмі. Якщо означити та зв' язати файлову змінну в програмі, а її внутрішній буфер означити у підпрограмі, то по закінченні виклику підпрограми файлова змінна буде доступною, а її буфер - ні. Спроба скидання з такого буфера по закінченні програми може призвести до непередбачених наслідків. Але якщо вся робота з файлом, від assign до close, описана в підпрограмі, то й буфер цілком природньо означити в ній же.
Приклад 3. Розглянемо програму з процедурою spoilbuf, тобто "зіпсувати буфер", за виклику якої змінюється буфер, що залишається в локальній пам' яті після закінчення попередньої процедури fillbuf.
program foolish;
var f : text;
procedure fillbuf;
var buf : array[1..5]of char;
begin
settextbuf(f, buf); rewrite(f); write(f, 'abcdefgh');
end;
procedure spoilbuf;
begin end;
begin
assign(f, 'boo.dat'); fillbuf; spoilbuf;
close(f)
end.
При виконанні виклику fillbuf символи abcde заповнюють внутрішній буфер і скидаються в зовнішній. Потім, уже при виконанні close(f) вони з' являються у файлі boo.dat. Але символи fgh залишаються у внутрішньому буфері після закінчення fillbuf і псуються під час виконання spoilbuf. Зіпсований буфер скидається при закриванні файла f, і потім замість fgh ми бачимо у файлі щось зовсім на них не схоже.
Задачі
15.1. Написати процедуру копіювання текстів із власними внутрішніми буферами розміром у 16 блоків, тобто 8192 байти, або 8K.
15.2. Написати процедуру побайтового порівняння текстів із власними внутрішніми буферами.
3. Буферизація екрана та клавіатури
Екран і клавіатура є текстами, зв' язаними з файловими змінними output і input. Для роботи з ними також уживаються буфери.
Спочатку розглянемо екран. З ним зв' язаний буфер, але символи, потрапивши в нього, одразу копіюються на екран. Якби цього не було, інформація на екрані з' являлася би з небажаними затримками.
При виконанні процедури WRITE за значенням її кожного аргумента обчислюється стала, тобто послідовність символів, які через буфер одразу виводяться на екран. Насправді, виклик
write(E1, E2, … , EN )
виконується як послідовність викликів
write ( E1 ); write ( E2 ); … ; write ( EN ).
Виконання writeln відрізняється тим, що в буфер екрана "додається eol", і курсор переводиться в наступний рядок.
Організація роботи з клавіатурою набагато складніше. Символи, утворені натисканням клавіш, накопичуються в буфері клавіатури. Він уміщає 15 символів. У цьому можна переконатися, запустивши програму
uses crt;
begin delay(16000) end.
Новости загрузка новостей...