Доступ до файлів: vis, версія 3

Дві перші версії програми vis читали тільки стандартний ввід і записували вихідні дані тільки в стандартний висновок, при цьому і введення і виведення були успадковані від оболонки Прийшов час зробити наступний крок – змінити vis так, щоб вона могла звернутися до файлу по його імені, тоді

$ vis file1 file2 ..

переглядала б вказані файли, а не пристрій стандартного вводу Якщо ж імена файлів не вказані, то vis повинна надходити, як раніше, тобто читати свій стандартний ввід

Питання в тому, як прочитати файли, тобто як звязати імена файлів з операторами введення, які і здійснюють зчитування даних

Є кілька простих правил Перш ніж файл можна буде прочитати або записати в нього дані, його требавідкрити за допомогою стандартної бібліотечної функції fopen Функція fopen отримує імя файлу (наприклад, temp або / etc / passwd), виконує деякі службові дії та погодження з ядром, після чого повертає внут реннее імя, яке і буде використовуватися при подальших операціях з файлом

Це внутрішня імя насправді є покажчиком (покажчик файлу) На структуру, що містить інформацію про фото, таку як місце розташування буфера, позиція поточного символу в буфері, читається файл або записується і тд Одне з описів, отриманих завдяки включенню , відноситься до структури під назвою FILE Оголошення покажчика файлу виглядає наступним чином:

FILE *fp

Такий запис означає, що fp являє собою покажчик на FILE Функція fopen повертає покажчик на FILE таке оголошення типу для fopen в

Виклик fopen в програмі виглядає так:

char  *name, *mode

fp  = fopen(name,  mode)

Перший аргумент функції – це імя файлу, символьний рядок Другий аргумент (теж символьний рядок) вказує, як саме передбачається використовувати файл дозволені такі режими, як читання (r), запис (w) і додавання (a)

Якщо файл, що відкривається для запису або додавання, не існує, то він створюється (якщо можливо) Якщо для запису відкривається існуючий файл, то його старе вміст стирається Спроба прочитати неіснуючий файл призводить до помилки – так само, як і спроба

прочитати або записати файл, для якого у користувача немає прав доступу У випадку помилки функція fopen повертає недійсне значення покажчика NULL (зазвичай визначається як (char *) 0 в )

Файл відкрито, тепер треба якось прочитати або записати його Сущест яття кілька способів зробити це, найпростішим є використання getc і putc Функція getc витягує з файлу наступний символ:

c = getc(fp)

в змінну c поміщається наступний символ з файлу, на який вказує fp коли досягнуть кінець файлу, повертається EOF Функція putc влаштована аналогічно:

putc(c, fp)

поміщає символ c у файл fp і повертає c У випадку помилки getc і

putc повертають EOF

Коли запускається програма, три файли вже відкриті і на них існують покажчики Це файли стандартного введення, стандартного виводу і стандартного виводу помилок відповідні покажчики називаються stdin, stdout і stderr Ці покажчики файлів оголошені в

; вони можуть використовуватися скрізь, де можуть існувати обєкти типу FILE * Це константи, а не змінні, тому присвоювати їм значення не можна

Функція getchar () еквівалентна getc (stdin), а putchar (c) –

putc(c,stdout)

Насправді всі чотири «функції», згадані вище, визначені в як макроси, вони виконуються швидше, тому що не викликаються для кожного символу окремо (як функція) Деякі інші визначення з наведені в табл 63

Таблиця 63 Деякі описи

Визначення Сенс

stdin стандартний ввід

stdout стандартний висновок

stderr стандартний висновок помилок

EOF кінець файлу зазвичай -1

NULL недійсний покажчик зазвичай 0

FILE використовується для оголошення покажчиків файлів

BUFSIZ звичайний розмір буфера введення-виведення (часто 512 або 1024)

getc (fp) повертає один символ з потоку fp getchar () getc (stdin)

putc (c, fp) поміщає символ c у потік fp

Таблиця 63 (продовження)

Визначення

Сенс

putchar(c) feof(fp) ferror(fp) fileno(fp)

putc(c, stdout)

НЕ нуль, якщо в потоці fp досягнуто кінець файлу не нуль, якщо в потоці fp виявлена ​​помилка файловий дескриптор потоку fp, див розділ 7

Зробимо ще кілька попередніх зауважень і приступимо до третьої версії vis Якщо в командному рядку є аргументи, то вони обробляються по порядку Якщо аргументи не задані, обробляється стандартний ввід

/ * Vis: зробити видимими недруковані символи (версія 3) * /

#include &ltstdioh&gt

#include &ltctypeh&gt

int strip = 0 / * 1 => видалити спеціальні символи * / char * progname / * Program name for error message * /

main(argc,  argv) int  argc

char  *argv[]

{

int i FILE  *fp

progname = argv[0]

while  (argc &gt  1  &amp&amp  argv[1][0]  == –) { switch  (argv[1][1])  {

case s: / *-s: видалити дивні символи * /

strip = 1 break

default:

fprintf(stderr, &quot%s:  unknown  arg  %s\n&quot,  argv[0], argv[1]) exit(1)

} argc–– argv++

}

if (argc  == 1) vis(stdin)

else

for  (i = 1  i &lt argc i++)

if ((fp=fopen(argv[i],  &quotr&quot)) == NULL)  {

fprintf(stderr, &quot%s: cant open  %s\n&quot,  progname,  argv[i]) exit(1)

} else { vis(fp) fclose(fp)

} exit(0)

}

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

Після того як оброблені всі необовязкові параметри, argc і argv коригуються так, що залишилася частина програми не залежить від наявності таких аргументів Незважаючи на те що vis розпізнає тільки одиночний параметр, програма написана як цикл для того, щоб показати, як можна організувати обробку аргументів У главі 1 згадувалося, що UNIX-програми обробляють необовязкові аргументи Ще однією причиною для цього, крім схильності до анар хии, служить те, що розбір будь-якій комбінації параметрів виконується виключно просто У деяких системах є функція ge-topt (3), з її допомогою намагалися якось упорядкувати ситуацію варто вивчити її, перш ніж братися за написання своєї власної

Функція vis виводить один файл:

vis (fp) / * зробити символи видимими в FILE * fp * / FILE * fp

{

int c

while  ((c  =  getc(fp))  =  EOF) if  (isascii(c)  &amp&amp

(isprint(c) ||  c==\n || c==\t  ||  c==  )) putchar(c)

else  if  (strip) printf(&quot\\%03o&quot,  c)

}

Функція fprintf практично ідентична printf, відмінність лише в тому, що в аргументі – файловому покажчику – вказується файл для запису

Функція fclose обриває звязок між покажчиком файлу і зовнішнім імям, встановлену fopen, і покажчик звільняється для нового файлу Оскільки кількість файлів, які система може відкривати одночасно (близько 20), обмежена, краще звільняти файли, які більше не знадобляться Зазвичай висновок, здійснюваний ка кой-то зі стандартних бібліотечних функцій типу printf, putc і т д, буферизується таким чином, що запис виконується великими порціями, що збільшує продуктивність (Винятком є ​​вивід на термінал, зазвичай здійснюваний у міру надходження або, принаймні, по введенню символу нового рядка (порядково)) Виклик fclose для файла виводу закриває будь буферізованние висновок Коли програма викликає exit або повертається з main, відбувається автоматичне звернення до fclose для кожного відкритого файлу

Так само як stdin і stdout, програмі присвоюється stderr Вихідні дані, записані на stderr, зявляться на терміналі користувача,

навіть якщо стандартний висновок буде перенаправлений Програма vis виводить діагностичні повідомлення на stderr, а не на stdout, тому якщо з якоїсь причини неможливо отримати доступ до одного з файлів, повідомлення про це зявиться на терміналі, а не зникне в конвеєрі або файлі виводу (Стандартний висновок помилок був винайдений в деякій мірі саме тому, що помилки почали исче зать в конвеєрах)

Умова виходу з програми вибрано, можна сказати, випадковим чином Це відбувається, якщо vis не може відкрити файл із вхідними даними такий вибір виглядає розумним для програми, найчастіше що використовується інтерактивно і отримує один файл вводу Однак якщо хочете, можете вибрати й іншу конструкцію

Вправа 65Напишіть програму printable, яка виводила б імя кожного файла-аргументу, який містить тільки символи, що друкуються якщо ж у файлі зустрічається якийсь незримий символ, його імя не виводиться Така програма корисна в наступних випадках:

$ pr  `printable *`  | lpr

Додайте параметр-v, щоб змінити зміст перевірки на зворотний, як в grep Як програмі слід чинити, якщо імена файлів не вказані Який код повинна повертати printable ~

Джерело: Керниган Б, Пайк Р, UNIX Програмне оточення – Пер з англ – СПб: Символ-Плюс, 2003 – 416 с, Мул

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*