- •Київський національний університет імені Тараса Шевченка
- •Гриф надано Міністерством освіти і науки України (лист № 1.4/18-г-1523 від 20.09.07)
- •Основи алгоритмізації
- •1.1. Поняття алгоритму
- •1.2. Класифікація внутрішніх структур алгоритмів
- •1. Ввести а,b.
- •3. Вивести значення s.
- •4. Кінець.
- •6. Закінчити роботу.
- •1. Ввести число n.
- •6. Перехід до п.3.
- •7. Друк к.
- •8. Кінець.
- •1.3. Складність алгоритмів
- •1.4. Складність задач
- •Завдання для самостійної роботи
- •Форма Бекуса – Наура
- •Завдання для самостійної роботи
- •Void main(){
- •3.2. Структура с-програми
- •3.3. Описувачі
- •3.4. Основні операції мови с
- •If(!inword)
- •Void main()
- •Int rozmir;
- •3.5. Оператори мови с
- •3.5.1. Прості оператори
- •3.5.2. Умовний оператор
- •3.5.3. Оператор циклу for
- •3.5.4. Оператори do-while, while
- •3.5.5. Оператор continue
- •3.5.6. Оператор-перемикач switch
- •3.5.7. Оператор break
- •3.5.8. Оператор goto
- •If(error(I,j,k)) goto exit;
- •3.5.9. Оператор return
- •3.6. Директиви препроцесору та вказівки компілятору
- •3.6.1. Директива препроцесору #define
- •1. Макровизначення:
- •3.6.3. Директива #include
- •3.6.4. Директиви умовної компіляції #if, #elif, #else, #endif
- •3.6.5. Директива #line
- •If(!cond)
- •3.7. Описувачі з модифікаторами
- •3.7.1. Моделі пам'яті
- •3.7.2. Модифікатори типу доступу в пам'яті
- •Int huge*near X;
- •3.7.3. Модифікатори const, volatile, cdecl, pascal, interrupt
- •Volatile int t;
- •Void interrupt timer()
- •Void wait(int interval)
- •Завдання для самостійної роботи
- •Принципи типізації даних
- •4.1. Прості типи даних
- •4.2. Похідні типи
- •4.3. Еквівалентність типів
- •4.4. Успадкування атрибутів
- •4.5. Перераховні типи
- •4.6. Логічні типи
- •4.7. Символьні типи
- •4.8. Числові типи
- •4.9. Структурні типи даних
- •4.9.1. Масиви
- •4.9.2. Структури
- •Int year;
- •4.10. Деякі особливості типів даних c
- •4.10.1. Базові типи даних
- •4.10.2. Перетворення типів
- •Int atoi(char s[]) /*char* s*/
- •4.10.3. Засіб typedef
- •Int curs;
- •4.10.4. Покажчики та масиви
- •Void * p;
- •Int array[12];
- •Void f(int a[])
- •Int f(char * s)
- •Наведемо деякі приклади розв'язання задач.
- •Int shift; /*відступ*/
- •Int count[n]; /*кількість монет даного типу (коефіцієнти ai)*/
- •Int coin;
- •Int sum; /*монета, яку міняємо*/
- •Int maxcoin; /*індекс по масиву cost[] монети максимальної вартості, допустимої при даному розміні.*/
- •If(count[I])
- •If(maxcoin)
- •Int* ctranspon (int *a,int n,int m)
- •Void dobutok(int* a, int* b, int** c, int n, int m)
- •Int n,m,I,size;
- •Int main()
- •4.10.5. Структури та об'єднання
- •Розглянемо деякі приклади розв'язання задач.
- •Int hashfunc(key); int eqkey(key, key);
- •Void freeval(val); void setval(val, val);
- •Void freekey(key); void setkey(key, key);
- •Int hashfunc(key key){
- •Val val; /*значення*/
- •Void set(key key, val val){
- •Void printcell(struct cell *ptr){
- •Void main(void)
- •Завдання для самостійної роботи
- •Зображення чисел у комп'ютері
- •Int main(void)
- •5.1. Системи числення
- •5.2. Правила переведення чисел з однієї системи числення в іншу
- •5.3. Правило визначення точності зображення
- •5.4. Двійкова арифметика
- •5.4.1. Додавання двійкових чисел
- •5.4.2. Зображення від'ємних чисел
- •XXXXXXXX 00000001 00000000.
- •5.4.3. Віднімання двійкових чисел
- •5.4.4. Множення двійкових чисел
- •5.4.5. Ділення двійкових чисел
- •5.5. Ознака переповнення розрядної сітки при арифметичних операціях
- •5.6. Зображення цілих чисел
- •5.7. Зображення дійсних чисел
- •5.8. Керування машинним зображенням чисел та особливості виконання арифметичних операцій
- •Завдання для самостійної роботи
- •Реалізація концепції структурного програмування
- •6.1. Оголошення та визначення функцій
- •Int d;} people;
- •6.2. Формальні та фактичні параметри
- •Void swap(int a,int b)
- •Void swap(int a,int*b)
- •6.3. Функції зі змінною кількістю параметрів
- •Void sum(char *msg,...)
- •6.5. Параметри функції main
- •6.6. Лiтернi покажчики та функцiї
- •Void strcpy(char*s,char*t)
- •Void f(void)
- •6.8. Класи пам'яті
- •Розглянемо деякі приклади розв'язання задач.
- •I, power(2,I),power(-3,I));
- •Void main() { choturukyt b; tochka *a; float s; long n,in; srand(time(null));
- •6.9. Введення–виведення с. Файли та потоки
- •6.9.1. Функції введення–виведення верхнього рівня
- •6.9.2. Функції введення–виведення консольного термінала та порту
- •Int main(void)
- •6.9.3. Функції введення–виведення нижнього рівня
- •Int main(void)
- •Int handle;
- •Розглянемо приклади розв'язання задач.
- •Void main(void)
- •Void main(argc,argv)
- •If(c& masks[I])
- •If (цей рядок довший за найдовший з попередніх)
- •Int max; /*максимальна довжина*/
- •Int len; /*довжиною цього рядка*/
- •Int nwords; /*кількість слів у рядку*/
- •If(!*s) /*рядок закінчився*/
- •Int ctr; /*кількість входжень слова*/
- •If(!strcmp(word,w[I].Wrd)){
- •If(alert){
- •Void main() { float X,y,z,t,s; int I,j,flag,n,k; m1: clrscr();
- •InitBase (void){
- •Int key, /*новий ключ*/
- •InitBase();
- •Завдання для самостійної роботи
- •7.1. Елементи концепції обєктно-орієнтованого програмування
- •Int year;
- •Int year;
- •7.3. Опис протоколу класу
- •7.4.1. Коментарі
- •7.4.2. Прототипи функцій
- •Void f();
- •7.4.5. Перевантаження функцій
- •Int Name (int first)
- •Int Name (unsigned first)
- •Int Name (int first,char*second)
- •7.4.6. Значення формальних параметрів за умовчанням
- •7.4.7. Посилання й покажчики
- •Void increment(int& X)
- •Int anotherint;
- •7.4.10. Покажчик на void
- •Void*void_ptr;
- •Void swap(void*&item1,void*&item2)
- •7.4.11. Зв'язування зі збереженням типів
- •7.4.12. Про структури та об'єднання
- •7.5. Функції-члени класу
- •X *this;
- •Int year;
- •7.6. Конструктори та деструктори
- •7.6.1. Поняття про конструктори
- •Int*data;
- •Int size;
- •7.6.3. Конструктор копіювання
- •Int data[large];
- •Inline Large1 Large1::fast(const Large1 & b)
- •7.7. Глобальні та локальні об'єкти
- •Void main(void)
- •7.8. Статична пам'ять і класи
- •Int statpol::I;
- •Vоid draw()
- •Int large;
- •Int bigwant;
- •Void f() {
- •Void g(int a)
- •7.9. Успадкування
- •7.9.1. Синтаксична реалізація успадкування
- •7.9.2. Правила доступу до полів даних
- •Void f(void)
- •Void g(void){}//...}
- •7.9.3. Конструктори та деструктори в похідних класах
- •7.9.4. Використання заміщуючих функцій-членів
- •Void Display (void); //замiщувальна функцiя
- •Void Region::Display(void)
- •Void Display(void);};
- •Void Population::Display(void)
- •7.9.5. Похідні класи й покажчики
- •7.9.6. Ієрархія типів
- •XyValue(int_x,int_y):X(_x),y(_y)
- •XyData(int_x,int_y)
- •7.9.7. Множинне успадкування
- •Void SetLoc(int_x,int_y);};
- •Int data;
- •7.10. Віртуальні функції та класи
- •7.10.1. Віртуальні функції
- •Int value;
- •Virtual int GetValue();
- •Int Value::GetValue(){return value;}
- •7.10.2. Чисті віртуальні функції. Абстрактні класи
- •Virtual void f1(void);
- •Virtual void f2(void);//...}
- •Int index;
- •7.10.3. Віртуальні деструктори
- •7.10.4. Посилання як засіб для реалізації поліморфізму
- •7.10.5. Дещо про механізм віртуальних функцій
- •Virtual int method1(float r);
- •Int data;
- •Void func(void){//тіло}};
- •Virtual public CocaCola {
- •Int size;
- •Void ShowValue(void)
- •Void ShowValues(void);};
- •Void Two::ShowValues(void)
- •7.11.2. Дружні функції
- •Void Show(One &c1,Two &c2)
- •Void Show(One &c1);
- •Void Two::Show(One &c1)
- •7.12. Перевантаження операцій
- •7.12.1. Загальний підхід
- •Void main()
- •7.12.2. Перетворення типів
- •X::operator т();
- •7.12.3. Перевантаження операції індексування масиву
- •Int znach;
- •7.12.4. Перевантаження операції виклику функції
- •Int operator()(void);
- •Int FuncClass::operator()(void)
- •Vidnosh*vec;
- •7.12.5. Перевантаження операції доступу до члена класу
- •7.12.6. Перевантаження операцій інкремента й декремента
- •Int index;
- •Void*operator new(size_t)
- •Void*operator new(size_t);
- •8.1. Функціональні шаблони
- •8.1.1. Визначення й використання шаблонів функцій
- •Void func(t t)
- •Int main(void)
- •8.1.2. Перевантаження шаблонів функції
- •Int main(void)
- •8.1.3. Cпецiалiзованi функцiї шаблона
- •Int main(void){
- •8.2. Шаблони класів
- •8.2.1. Визначення шаблонів класу
- •Void push(t t);
- •Int numitems;
- •8.2.2. Константи й типи як параметри шаблона
- •8.2.3. Використання шаблонних класів
- •Int main(void)
- •8.2.4. Спеціалізація шаблонів класу
- •Void add(t item);
- •Int main(void)
- •IArray.Add(i1);
- •Int main(void)
- •IList.Add(i1);
- •Завдання для самостійної роботи
- •Автоматна технологія програмування
- •If(!stop)printf("не входити");
- •Завдання для самостійної роботи
- •Список літератури
- •Передмова 3
Void main() { choturukyt b; tochka *a; float s; long n,in; srand(time(null));
m1: clrscr(); printf("Введіть кількість точок (N>4):"); scanf("%ld",&n); printf("Введіть інтервал (IN>0) від 0 до"); scanf("%ld",&in);
if(n<4||in<=0) { highvideo(); cputs("\nУвага! Помилка при введенні даних!"); normvideo(); getch(); goto m1; }
if((A=(tochka*)malloc(n*sizeof(tochka)))==NULL) { highvideo(); cputs("\nПомилка при виділенні пам’яті!"); normvideo(); getch(); return; }
zapov(A,n,in); clrscr(); if((s=poshyk(A,n,&B))!=0) { puts("Точки чотирикутника:"); printf("Перша: \t\tx %9.3f\ty %9.3f\n",B.t1.x,B.t1.y); printf("Друга: \t\tx %9.3f\ty %9.3f\n",B.t2.x,B.t2.y); printf("Третя: \t\tx %9.3f\ty %9.3f\n",B.t3.x,B.t3.y); printf("Четверта: \tx %9.3f\ty %9.3f\n",B.t4.x,B.t4.y); printf("\nПлоща цього чотирикутника: %.3f\n\n",s); } else puts("Таких чотирикутників немає!\n");
highvideo(); cputs("Для виходу натисніть Esc..."); putchar('\n'); cputs("Для повторення натисніть Enter..."); normvideo();
free(A);
m2: switch(getch()) { case 13: goto m1; case 27: return; default: goto m2; } }
6.9. Введення–виведення с. Файли та потоки
Як приклад реалізації концепції процедурного програмування можна розглянути систему введення–виведення С. Ця система є набором відповідних функцій, об'єднаних у бібліотеку stdio.h.
Для користувача файл, відкритий на зовнішньому рівні, є послідовністю байтів, що зчитуються та записуються. Щоб підкреслити цю особливість, використовується термін потік. Коли програма починає виконуватись, відкриваються п'ять стандартних потоків: stdin (пов'язаний зі стандартним пристроєм введення), stdout (виведення), stderr (пристрій помилок), stdprn (принтер), stdaux (порт). Ці потоки мають відповідно дескриптори 0, 1, 2, 3, 4.
Стандартні імена можна легко перепризначити:
FILE *f;
stdin=f;
Усі функції введення–виведення можна поділити на три класи:
верхнього рівня;
консольного термінала та порту;
нижнього рівня.
Є також функції для роботи з послідовним портом (com). Умовно їх можна зарахувати до другої групи.
6.9.1. Функції введення–виведення верхнього рівня
Функції верхнього рівня характеризуються буферизацією операцій зчитування та запису. Якщо проводиться операція запису у файл, то інформація з буферу записується у файл при заповненні буфера, закритті файла та за деяких інших умов. Інформація зчитується з буфера, до якого потрапляє нова порція інформації. Буферизація здійснюється автоматично. Вона дозволяє пришвидшити виконання програми за рахунок зменшення кількості звертань до зовнішніх пристроїв, що працюють відносно повільно. До функцій верхнього рівня належать:
clearerr() – скидання прапорців помилок;
fclose() – закриття потоку;
fcloseall() – закриття всіх відкритих файлів;
fdopen() – створення потоку для файла, відкритого раніше на нижньому рівні з використанням дескриптора;
feof() – перевірка на кінець потоку;
ferror() – перевірка прапорців помилок;
flush() – скидання буфера потоку;
fgetc() – читання символу з потоку;
fileno() – отримання дескриптора файла, пов'язаного з потоком;
fgetchar() – макрос читання зі stdin (аналог fgetc(stdin));
fgets() – читання рядка з потоку;
flushall() – скидання всіх буферів;
fopen() – відкривання файла;
fprintf() – форматоване виведення в потік;
fputc() – запис символу в потік;
fputchar() – макрос запису символу у stdout;
fputs() – запис рядка в потік; символ нового рядка не дописується;
fread() – неформатоване читання;
freopen() – повторне відкривання в новому режимі;
printf() – форматоване виведення у stdout;
scanf() – форматоване введення зі stdin;
fscanf() – форматоване читання з потоку;
fseek() – позиціювання файлового покажчика;
fwrite() – неформатований запис у потік;
getc() – читає символ з потоку та переставляє файловий покажчик на наступну позицію;
getchar() – макрос читання зі stdin (аналог getc(stdin));
gets() – читання рядка зі stdin;
getw() – читання слова з потоку (цілого типу int);
putc() – макрос запису символу в потік;
putchar() – макрос запису у stdout;
puts() – записує рядок з нуль-символом у stdout і дописує символ нового рядка;
putw() – запис слова в потік;
rewind() – установлення файлового покажчика на початок файла;
setbuf() – установлює буфер для відкритого потоку;
setvbuf() – установлює буфер із низкою додаткових параметрів;
sprintf() – форматоване виведення в рядок;
sscanf() – форматоване введення з рядка;
tempnam() – генерує ім'я тимчасового файла в каталозі;
tmpfile() – створює тимчасовий файл;
ungetc() – повертає символ у потік;
vfprintf(), vsprintf(), vfscanf(), vscanf(), vsscanf() – аналоги відповідних описаних вище функцій, але приймають як параметри покажчик на список аргументів – адрес змінних, що виводяться чи яким присвоюються значення, що вводяться.
Розглянемо деякі функції.
Функція printf(control, arg1, arg2,...) визначає формат і друкує свої аргументи в стандартне виведення під керуванням рядка control. Керуючий рядок містить два типи об'єктів: звичайні символи, що просто копіюються у вихідний потік, і специфікації перетворень, кожна з яких викликає перетворення та друк чергового аргументу printf.
Продемонструємо вплив задання різних специфікацій на друк "hello, world" (12 символів).
:%10s: : hello, world:
:%10-s: : hello, world:
:%20s: : hello, world:
:%-20s: : hello, world:
:%20.10s: : hello, world:
:%-20.10s: : hello, world:
:%.10s: : hello, world:
Функція scanf використовується для введення даних та є аналогом printf. Функція scanf(control,arg1,arg2,...) читає символи зі стандартного введення, інтерпретує їх відповідно до формату, зазначеного в аргументі control, і розміщує результати в інші аргументи. Наприклад, звертання
int 1;
float x;
char name[50];
scanf("&d%f%s",&i,&x,name);
з рядком при введенні
25 54.32e-1 alpha
приводить до присвоювання i значення 25, x – значення 5.432 і name – рядка "alpha", який закінчується символом '\0'. Ці три поля введення можна розділювати довільною кількістю пропусків, табуляцій і символів нових рядків. Виклик функції
int i;
float x;
char name[50];
scanf("%2d %f%*d%2s",&i,&x,name);
із введенням
56789 0123 45a72
присвоїть i значення 56, x – 789.0, пропустить 0123 і помістить у name рядок "45". При наступному звертанні до будь-якої процедури введення розгляд почнеться з літери а. У наведених вище фрагментах програм name є покажчиком і, отже, перед ним не потрібно поміщати знак &.
Аргументи функції scanf мають бути покажчиками. Найрозповсюдженіша помилка полягає в написанні scanf("%d",n); замість scanf("%d",&n);
Функції sscanf і sprintf здійснюють аналогічні перетворення, але оперують із рядком, а не файлом:
sprintf(string,control,arg1,arg2,...)
sscanf(string,control,arg1,arg2,...)
Функція sprintf перетворює свої аргументи arg1, arg2 і т. д. відповідно до формату, зазначеного в control, але розміщує результати у string, а не в стандартне виведення. Звичайно, рядок string має бути достатньо великим, щоб вмістити результат. Наприклад, якщо name – символьний масив, а n – ціле, то
sprintf(name,"temp%d",n);
створює в name рядок вигляду tempnnn, де nnn – значення n.
Функція sscanf виконує зворотні перетворення – вона переглядає рядок string відповідно до формату в аргументі control і поміщає результуючі значення в аргументи arg1, arg2 і т. д. Ці аргументи мають бути покажчиками. У результаті виклику
sscanf(name,"temp%d",&n);
змінна n одержує значення рядка цифр, що йдуть за темр у name.
Аналогічними є функції fprintf() та fscanf(), що працюють із файлами. Вони мають першим параметром змінні типу FILE*.
Функції getc(), getchar(), gets(), getw() зчитують відповідно символ, рядок, слово з потоку; putc(), putchar(), puts(), putw() – записують.
Перед використанням файла його необхідно відкрити за допомогою функції fopen зі стандартної бібліотеки. Функція fopen використовує зовнішнє ім'я файла, проводить деякі обслуговуючі дії й повертає внутрішнє ім'я, що має використовуватися при читанні з файла чи записах у нього. Це внутрішнє ім'я, що називається покажчиком файла, фактично є покажчиком на структуру, що містить певну інформацію про файл (місце розміщення буфера, поточна позиція символу в буфері, спосіб використання файла, читання чи запис тощо). Користувач може й не знати всіх технічних деталей. Наприклад:
FILE *fopen(),*fp;
Тут fp є покажчиком на FILE, а fopen повертає покажчик на FILE. Зверніть увагу, що FILE є ім'ям типу (це реалізовано як typedef). Фактичне звертання до функції fopen у програмі має вигляд
fp=fopen(name,mode);
Першим аргументом функції fopen є ім'я файла, що задається у вигляді символьного рядка. Другий аргумент mode (режим) також є символьним рядком, що вказує, як файл буде використовуватися. Допустимими режимами є: читання ("r"), запис ("w") і дописування в кінець ("a"). Також можна використовувати "r+" – відкривання існуючого файла для читання та запису, "w+" – створення нового файла для запису й читання, "a+" – відкривання для дописування в кінець чи читання. Якщо файл існує, то він перезапишеться.
Якщо ви відкриєте для запису неіснуючий файл, то його буде створено (якщо це можливо). Відкривання існуючого файла для запису приводить до знищення його старого вмісту. Спроба читання неіснуючого файла є помилкою. Помилки можуть бути зумовлені й іншими причинами (напр., спробою читання з файла, якщо на це немає дозволу). За наявності помилки функція повертає нульове значення покажчика NULL (яке для зручності визначається у файлі stdio.h).
При роботі з уже відкритими файлами найпростішими є функції getc і putc. Функція getc повертає наступний символ з файла; їй потрібен покажчик файла, щоб знати, з якого файла читати. Таким чином, c=getc(fp) поміщає в "с" наступний символ з файла-потоку, зазначеного за допомогою fp, і EOF, якщо досягнуто кінець файла.
Функція putc putc(c,fp) поміщає символ "с" у файл fp і повертає "с". Подібно функціям getchar і putchar, getc і putc можуть бути макросами, а не функціями.
Функції getchar і putchar можуть бути визначені в терміналах getc, putc, stdin і stdout таким чином:
#define getchar()getc(stdin)
#define putchar(с)putc(c,stdout)
При роботі з файлами для форматного введення й виведення можна використовувати функції fscanf і fprintf. Вони ідентичні функціям scanf і printf, за винятком того, що першим аргументом є покажчик файла.
Розглянемо програму для конкатенації файлів. Схема, що тут використовується, зручна (аргументи в командному рядку обробляються послідовно). Якщо такі аргументи відсутні, то обробляється стандартне введення. Це дозволяє використовувати програму як самостійно, так і як частину більшої задачі.
#include <stdio.h>
main(argc, argv) /*cat: concatenate files*/
int argc;
char *argv[];
{
FILE *fp,*fopen();
if(argc==1) /*no args;copy standard input*/
filecopy(stdin);
else
while(--argc>0)
if((fp=fopen(*++argv,"r"))==NULL) {
printf("cat:can't open %\n",*argv);
break;
} else {
filecopy(fp);
fclose(fp);
}
}
filecopy(fp) /*copy file fp to standard output*/
FILE*fp;
{
int c;
while((c=getc(fp))!=EOF)
putc(c,stdout);
}
Функція fclose зворотна за дією стосовно fopen; вона розриває зв'язок між покажчиком файла й зовнішнім ім'ям, установлений функцією fopen, і вивільняє покажчик файла. Більшість операційних систем мають деякі обмеження на кількість одночасно відкритих файлів, якими може оперувати програма. Існує також інша причина для застосування функції fclose до вихідного файла – вона викликає звільнення буфера (за нормального завершення роботи програми функція fclose викликається автоматично для кожного відкритого файла).