Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Зубенко, Омельчук - Програмування. Поглиблений курс

.pdf
Скачиваний:
51
Добавлен:
07.03.2016
Размер:
4.72 Mб
Скачать

Розділ ІІІ. МОВИ ПРОГРАМУВАННЯ С ТА С++

автомата за символом / показана реакція програми на ситуацію. При переході в стан STOP автомат закінчує роботу.

Стан\Вхідний символ

A

 

 

 

 

B

 

 

EOF

ІN

ІN

/

g

 

 

OUT

/

g

STOP

OUT

 

 

 

 

STOP

ІN

/

,

m

++

OUT

/

g

 

 

g

 

 

 

Для подання станів вводиться змінна state, яка набуває одного зі значень ІN або OUT. Програма за допомогою перемикачів моделює пе- реходи автомата й реакцію на них згідно з таблицею переходів. Як тіль- ки черговий символ розпочинає нове слово (при переході від стану OUT у стан ІN), лічильник слів m збільшується на 1. Читання чергового символу зі вхідного потоку відбувається в усіх ситуаціях, тому виклик функції getchar() винесено за межі перемикачів у кінець тіла циклу.

Лістинг.

#include <stdio.h> #define ІN 1 #define OUT 0

/*count_word: обчислення кількості введених із клавіатури слів*/ long count_word(void)

{int ch, state=OUT, m=0;

ch=getchar();/*читання першого символу зі вхідного потоку*/ while (ch !=EOF)

{

if (ch==' ‘ || ch=='\n‘ || ch=='\t‘)/*прочитано порожній символ*/

switch (state){

case IN : state=OUT;break; case OUT:

}

else /*прочитано непорожній символ*/ switch (state){

case OUT : state=IN; m++;break; case IN:

}

ch=getchar();/*читання чергового символу зі вхідного потоку*/

}

return m;

}

void main (void) {printf("\n%ld", count_word());

}

391

ПРОГРАМУВАННЯ

Читання й запис рядків. У файлі <stdio.h> описані функції для зчи- тування з клавіатури й відображення на екран рядків символів:

char *gets(char *s); int puts(const char *s);

Перша функція читає з клавіатури рядок символів, включаючи про- біли й табуляції, поки не зустріне символ нового рядка, що замінюється нульовим символом (\0). Послідовність прочитаних символів запам'ято- вується в області пам'яті, що адресується аргументом s. Цією областю є зазвичай масив. Необхідно слідкувати, щоб пам'яті вистачало для збері- гання введеного рядка. Якщо введення успішне, то функція повертає s, у випадку кінця файла чи помилки нуль. Друга функція виводить на екран заданий рядок і символ нового рядка, а при успішному завер- шенні повертає ненульове додатне значення, інакше EOF.

Приклад 3.68. Застосування функцій gets та puts для введення з клавіатури й виведення на екран рядка:

#include<stdio.h> #define MAXLINE 128 int main()

{

char str[MAXLINE];

puts ("Введіть рядок:"); gets(str);

puts (str);

return 0;

}

Форматовані функції читання й запису. У <stdio.h> описані функції scanf та printf, що виконують форматоване введення й ви- ведення, тобто можуть читати й відображати дані в різних форматах:

int scanf (const char * restrict format, ...); int printf (const char * restrict format, ...);

Обидві функції мають змінну кількість параметрів, перший з яких форматний рядок є обов'язковим і захищеним від зовнішніх впливів кваліфікаторами типу const та restrict. Він керує всім процесом фо- рматування і введення-виведення інформації.

392

Розділ ІІІ. МОВИ ПРОГРАМУВАННЯ С ТА С++

Функція printf здійснює виведення на екран відформатованої ін- формації. Повертає кількість записаних символів або, у випадку поми- лки, – від'ємне значення. Форматний рядок містить два види елемен- тів: звичайні символи, що виводяться на екран, та специфікатори пе- ретворення, які викликають перетворення до відповідного вигляду й виведення інших параметрів згідно з порядком їхнього розташування

воператорі виклику функції. Форматний рядок може містити:

пробіли ‘ ', табуляції ‘\t', символи нового рядка ‘\n' та інші ке- рівні символи;

звичайні символи, але не ‘\' та ‘%', які просто виводяться;

специфікатори перетворення.

Останні мають вигляд:

%[<прапорці>][<ширина>][.<точність>][F|N|h|l|L] <специфікаторперетворення>

Прапорці (у довільному порядку):

-Текст, що виводиться, вирівнюється по лівому краю. Весь порож- ній простір, що залишився праворуч, заповнюється пробілами. За умовчанням текст вирівнюється по правому краю

+Числові значення друкуються зі знаком

пробіл

Перед додатними числовими

значеннями виводиться пробіл, а

0

перед від'ємними знак мінус

 

Числа мають доповнюватися ліворуч нулями до всієї ширини поля

#Указує на одну з таких форм виведення: для o першою цифрою має бути 0; для x чи X ненульовому результату повинні передувати 0x чи 0X; для e, E, f, g та G виведення має обов'язково містити десяткову точку; для g і G завершальні нулі не відкидаються

Ширина. Задає мінімальну ширину поля виведення. Перетворений аргумент друкується в полі, розмір якого не менше зазначеної ширини, а за потреби у полі більшого розміру. Якщо кількість символів аргументу менша за ширину поля, то поле доповнюється пробілами ліворуч (право- руч, якщо текст вирівняний по лівому краю). Однак, якщо значення ши- рини починається з 0, то доповнення здійснюється цифрами 0.

Як ширину поля можна вказати символ *, що приводить до вико- ристання значення наступного аргументу типу int у списку аргумен- тів як ширини поля.

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

393

ПРОГРАМУВАННЯ

чає кількість виведених дробових десяткових розрядів. Наприклад, %10.4f означає, що ширина поля буде не менше 10 символів, причому для дробових десяткових розрядів буде відведено чотири позиції.

Якщо модифікатор точності застосовується з форматами %g або %G, то визначає кількість значущих цифр.

При введенні рядків цей модифікатор визначає максимальну довжи- ну поля. Наприклад, %5.7s означає, що довжина виведеного рядка ста- новить мінімум п'ять і максимум сім символів. Якщо рядок довший ніж максимальна довжина поля, то кінцеві символи виводитися не будуть.

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

Якщо замість точності вказати символ *, то за її числове значення бу- де взято значення наступного аргументу типу int у списку аргументів.

Перетворення:

Символ

Опис

d, i

Десяткове ціле зі знаком

O

Беззнакове вісімкове число (без 0 ліворуч)

x, X

Беззнакове шістнадцяткове число (без 0x чи 0X ліворуч)

u

Беззнакове десяткове ціле

c

Символ

s

Рядок символів

f

Десяткове з плаваючою точкою

e, E

Експоненційне зображення відповідно з позначеннями e чи E

g, G

Залежно від того, яке виведення буде коротшим, використо-

 

вується %е (%E) чи %f

p

Виводить покажчик

n

Аргумент, що відповідає цьому специфікатору, має бути по-

 

кажчиком на цілочислову змінну. Специфікатор дозволяє збе-

 

регти у змінній кількість виведених символів

%

Виводиться символ %

Приклад 3.69. Програма, що демонструє можливості специфікато- рів перетворення функції printf ():

#include<stdio.h> #define pi 3.141592654

int main()

{

printf("%10s\n", "hello, world");

394

Розділ ІІІ. МОВИ ПРОГРАМУВАННЯ С ТА С++

printf("%20s\n", "hello, world"); printf("%-20s\n", "hello, world"); printf("%20.10s\n", "hello, world"); printf("%-20.10s\n", "hello, world"); printf("%.10s\n", "hello, world"); printf("%10f\n", pi); printf("%20f\n", pi); printf("%-20f\n", pi); printf("%20.10f\n", pi); printf("%-20.10f\n", pi); printf("%.10f\n", pi);

return 0;

}

У результаті виконання програми на екран будуть виведені рядки:

hello, world hello, world hello, world hello, wor hello, wor hello, wor

3.141593

3.141593

3.1415926540

3.1415926540

Функція scanf читає дані з клавіатури під керуванням форматного ря- дка, перетворює їх у внутрішню форму згідно зі специфікаторами фор- мату та присвоює по порядку аргументам, кожен з яких має бути вира- зом і задавати покажчик відповідного типу. Завершує роботу, коли виче- рпується форматний рядок. Повертає кількість перетворених і введених елементів або EOF при досягненні кінця файла чи у випадку помилки.

Форматний рядок має вигляд:

<форматний рядок>::=[<пробіл>] [<табуляція>] [<новий рядок>] \ [<літерал>] [<специфікатор-перетворення>]

<специфікатор-перетворення>::=%[*][<ширина>]

[N

| F]

[h | l | L] [<тип>]

 

 

<ширина>::=<число>

 

 

<тип>::=% | c | d | D | e | E | f | F | g | G |i |

 

 

|I | n | o | O | p | s | u | U | x | X | [

 

 

Форматний рядок може містити пробіли, символи табуляції й ново- го рядка, літерали без зовнішніх лапок і специфікатори перетворення.

395

ПРОГРАМУВАННЯ

Керують виведенням тільки специфікатори перетворення, решта еле- ментів є фільтрами вони пропускають із клавіатури лише свої коди, які читаються, але без наслідків, тобто фактично ігноруються.

Специфікатори й типи перетворень:

Специфікатори перетворень:

*Блокує присвоювання значення аргументу, що відповідає вхідному полю

[ширина]

Максимальна кількість символів вхідного поля, що врахову-

 

ються під час введення інформації. При цьому використову-

[N|F]

ється не більше зазначеної кількості символів

Указує адресу аргументу як near (близький) (N) чи far (дале-

[h|l|L]

кий) (F)

Тип даних аргументів: short для (h), long int, double

 

для (l), long double для (L)

Типи перетворень:

Код

Значення

%a

Значення з плаваючою точкою

%c

Символ

%d

Десяткове ціле число

%i

Ціле число як у десятковому, так і у вісімковому чи шістнадцят-

%e

ковому форматі

Число з плаваючою точкою

%f

Число з плаваючою точкою

%g

Число з плаваючою точкою

Вісімкове число

%s

Рядок

%x

Шістнадцяткове число

%p

Покажчик

%n

Ціле значення, що дорівнює кількості вже зчитаних символів

%u

Десяткове ціле число без знака

%[]

Набір символів, що скануються. Наприклад, %[XYZ] означає

 

сканувати лише X, Y та Z; %[A-Z] сканувати символи від A до Z

%%Перетворення відсутнє. Читається й запам'ятовується знак від- сотка

Приклад 3.70. Виведення на екран десяткового й шістнадцятко- вого подань введеного цілого:

#include<stdio.h>

int main()

396

Розділ ІІІ. МОВИ ПРОГРАМУВАННЯ С ТА С++

{

int i;

puts("Введіть десяткове ціле у форматі: i: ц…ц "); scanf("і: %d", &i); /*Без префікса "i:" число не буде прочи-

тане!*/

printf("\nДесяткове подання i:%d || Шістнадцяткове подання i: %x\n", i, i);

return 0;

}

Після введення числа 10 програма виведе на екран рядок символів:

Десяткове подання i: 10 || Шістнадцяткове подання i: 0xА

Форматовані читання з рядків і запис у рядки здійснюють функції

int sscanf (char *s, const char* restrict format, );

int sprintf (char* restrict s, const char* restrict format, );

Вони є аналогами відповідних функцій scanf та printf. Відмінність полягає тільки в тому, що стандартні вхідний і вихідний потоки в них замінені на рядок s, тобто символи читаються з рядка s і записуються в нього. При читанні досягнення кінця рядка рівноцінне ситуації з досягненням кінця файла.

3.8.3. ОБРОБКА ФАЙЛІВ

Потік зв'язується з конкретним файлом у процесі його відкриван- ня. Як тільки потік (файл) відкрито, можна проводити обмін інфор- мацією між ним і програмою. Файл від'єднується від певного потоку (розривається зв'язок між файлом і потоком) за допомогою операції закривання. Кожний потік має керівну структуру типу FІLE, що міс- тить усю необхідну інформацію для роботи з ним. Вона визначається за допомогою покажчика на структуру типу FІLE: FILE *fp;. Змінна fp зображує потік у подальшій роботі з файлом.

Опис типу FІLE, а також прототипи більшості функцій і констант файлової системи містяться в заголовному файлі <stdio.h>. Окрім типу FІLE, у ньому розташовані описи типів sіze_t, fpos_t, FІLE, sіze_t та fpos_t цілі без знака і визначаються кілька спеціальних макросів, зокрема такі, як NULL, EOF, FOPEN_MAX, SEEK_SET, SEEK_CUR

та SEEK_END. Макрос NULL визначає порожній (null) покажчик. Макрос

397

ПРОГРАМУВАННЯ

EOF, часто визначений як -1, є значенням, що повертають тоді, коли функція намагається виконати читання після закінчення файла. Кон- станта FOPEN_MAX визначає ціле значення, рівне максимальній кілько- сті одночасно відкритих файлів. Інші макроси використовуються ра- зом із функцією fseek, що реалізує прямий доступ до файла.

Розглянемо основні функції файлової системи. Їхні аналоги для об- робки широких символів можна знайти в [133].

Відкривання й закривання потоків. Відкриває потік і зв'язує йо-

го з файлом функція fopen:

FILE *fopen(const char *filename, const char *mode);

Якщо відкривання відбулося успішно, то функція повертає покаж- чик файла, інакше значення NULL. Параметр filename задає ім'я файла й може містити інформацію про шлях до нього у файловій сис- темі. Параметр mode визначає режим відкривання файла:

Режим

Двійковий

Текстовий

 

Семантика

 

«r»

«rb»

«rt»

Відкриває

існуючий

файл

«w»

«wb»

«wt»

для читання

 

 

Створює

новий

файл

для

 

 

 

запису. Перезаписує існую-

 

 

 

чий файл із таким самим

«a»

«ab»

«at»

іменем

 

 

 

Відкриває

існуючий

файл

 

 

 

для додавання в його кінець

«r+»

«r+b»

«r+t»

нової інформації

 

 

Відкриває

існуючий

файл

«w+»

«w+b»

«w+t»

для читання й запису

 

Створює

новий

файл

для

 

 

 

читання й запису. Перезапи-

 

 

 

сує існуючий файл із таким

«a+»

«a+b»

«a+t»

самим іменем

 

 

Відкриває

існуючий

файл

 

 

 

для додавання в його кінець

 

 

 

нової інформації. Якщо файл

 

 

 

не існує, то створюється но-

 

 

 

вий із таким самим іменем

Максимальна кількість одночасно відкритих файлів визначається FOPEN_MAX. Її точне значення залежить від компілятора, але має бути не менше 8.

Закриває відкритий потік функція int fclose(FILE *stream);

398

Розділ ІІІ. МОВИ ПРОГРАМУВАННЯ С ТА С++

Якщо потік, заданий параметром-покажчиком файла, був відкри- тий для запису, то перед закриванням у файл записуються дані, що містяться в буферах потоку. Після закривання файла його покажчик стає беззмістовним. Якщо закривання відбулося успішно, то функція повертає 0, інакше значення EOF.

Приклад 3.71. Відкривання й закривання файлів:

1) FILE *fp;

fp=fopen("file1.txt", "a+"); /*відкривання файла file1.txt для модифікації й доповнення*/

2) При відкриванні файла можливі помилкові ситуації. Наприклад, помилково записане ім'я файла, що відкривається для читання тощо. Тоді fopen повертає NULL:

if ((fp=fopen("file2.txt", "r")==NULL)

{perror("помилка при відкриванні файла file2.txt"); exit(0);}

3)fclose (fp); /*закривання файла file1.txt*/

4)if (fclose (fp))

{perror("помилка при закриванні файла file2.txt"); exit(0);}

Читання й запис символів у файл

int fputc(int c, FILE *stream); int fgetc(FILE *stream);

int ungetc (int c, FILE *stream);

Перша функція записує заданий символ c у потік stream. У випад- ку успіху повертає значення c, при помилці значення EOF. Друга чи- тає черговий символ із заданого потоку stream. У випадку успіху по- вертає значення символу, при помилці EOF. Функція ungetc повертає символ c у вхідний потік stream, щоб він міг бути повторно прочита- ним функціями fgetc, getc та getchar. Якщо повертається кілька сим- волів, то вони будуть доступними, як у стеку останнім повернутий є першим доступним.

Є також функції putc та getc, повністю аналогічні наведеним функці- ям. Їх включено до стандарту С99 для сумісності зі старими версіями C.

Читання й запис рядків у файл здійснюють функції

char *fgets(char *s, int n, FILE *stream); int fputs(const char *s, FILE *stream);

399

ПРОГРАМУВАННЯ

Перша послідовно читає із заданого потоку stream символи включ- но до символу нового рядка, але не більше n-1 символів. Прочитані символи розміщуються за адресою s. До кінця рядка приєднується символ нового рядка, якщо він прочитаний, а також нульовий сим- вол. У випадку успіху повертає значення s, при помилці нульовий покажчик. Друга записує в потік stream рядок символів, розташова- ний за адресою s. Функція передає символи, поки не зустріне нульо- вий символ. У випадку успіху повертає кількість записаних символів, при помилці EOF.

Приклад 3.72. Читання рядків довільного файла з виведенням їх на екран. Після завершення читання виводиться загальна кількість прочитаних рядків:

#include <stdio.h> #include <errno.h>

void main (void)

{

char string[256],file_name[128]; int line_number=0; FILE*fptr;

puts("Введіть ім'я файла"); gets(file_name); if((fptr=fopen(file_name, "r"))!=NULL)

{

for (;fgets(string,255,fptr)!=NULL;line_number++) fputs(string,stdout);

printf("\n Прочитано %d рядків файла

%s\n",line_number,file_name);

fclose(fptr);

}

else perror("\nПомилка при відкриванні файла");

}

Перевірка ознаки кінця файла здійснюється функцією

int feof (FILE *stream);

Повертає ненульове значення, якщо буферний покажчик потоку міститься за останнім байтом файла. Зазвичай це відбувається в ре- зультаті попередньої операції введення. Повертає 0, якщо буферний покажчик не міститься в кінці файла.

400

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]