Основи C

[ виправити ] текст може містити помилки, будь ласка перевіряйте перш ніж використовувати.

скачати

Кафедра: Автоматика та Інформаційні Технології

ОСНОВИ З

ЗМІСТ

Введення

Глава 1. Основи мови Сі

1.1. Алфавіт

1.2. Основні конструкції Сі

1.3. Введення-виведення.

1.3.1. Висновок

1.3.2. Введення

1.4. Базові типи даних мови Сі

1.4.1. Ідентифікатори.

1.4.2. Типізовані константи

1.4.3. Змінні

1.4.3.1. Цілі типи

1.4.3.2. Речові типи

1.4.3.3. Символьні типи

1.4.4. Тип даних рядок

1.4.5. Структури

1.4.5.1. Масиви

1.4.5.2. Записи

1.4.6 Область видимості та час життя змінних

1.5. Основні оператори

1.6. Препроцесор

1.7. Програми. Функції

1.8. Покажчики

1.9. Покажчики та функції

1.10. Файли

1.11. Додаткові функції Сі

1.11.1. Функції перетворення

Функції перетворення символьних рядків: atoi (), atof (). 37С.

1.11.3. Функції, що працюють з рядками

1.12. Особливості програмування на мові Сі

1.12.1. Модулі. Багатомодульні програмування

1.12.2. Моделі пам'яті

1.12.3. Програмування в DOS і Windows

1.12.4. Використання мови асемблера в програмах на Сі

Глава 2. Приклади використання мови Сі

2.1. Сортування

2.2. Рекурсивні алгоритми

2.3. Завдання "Ханойські вежі"

Глава 3. Основи С + +

3.1. Відмінності С + + від Сі

3.2. Об'єктно-орієнтоване програмування в С + +

3.2.1. Класи

3.2.2. Перевантаження функцій

3.2.3. Конструктори

3.2.4. Деструктори

3.2.5. Конструктори з параметрами

3.2.6. Введення в спадкування

3.2.7. Віртуальні функції

3.2.8. Покажчики на об'єкти

Глава 4. Основи програмування на мові С + + Builder

4.1. Характеристика С + + Builder

4.2. Компоненти VCL. Властивості. Події. Методи

4.2.1. Типи компонент

4.2.2. Ієрархія класів VCL

4.3. Структура файлів в С + + Builder

4.4. Візуальні компоненти (VCL)

4.5. Програми, управління подіями, виключення

4.6. Стратегія налагодження Windows-програм

4.7. Використання компонентів VCL у розробці програм

4.8. Графічні компоненти.

4.9. Мультимедіа

4.10. Спрайтові графіка

4.11. Об'єктна технологія OLE2

4.12. Бібліотеки DLL.

4.13. Розробка візуальних компонент

4.14. Введення в програмування CGI

3.15. Програмування баз даних.

3.16. Пакети

Висновок

Література

Додаток N 1

Зміст

Введення

У 1804 році французький винахідник Жозеф Марі Жаккар створив "програмно-керований" ткацький верстат. Для керування верстатом використовувалися перфокарти, з'єднані один з одним у вигляді стрічки. Дерев'яні шпильки "читає пристрої" верстата по розташуванню отворів у перфокарті визначали, які нитки слід підняти, а які опустити для отримання потрібного візерунка.

У 1890 році в США винахідником Германом Холлеритом розроблена електромеханічна лічильна машина - табулятор, керована перфокартами, була використана для складання таблиць з результатами перепису населення США. Заснована Холлеритом фірма з виробництва табуляторів згодом перетворилася на корпорацію International Business Machines (IBM).

У 1936 році двадцятип'ятирічний студент Кембріджського університету англієць Алан Тьюринг опублікував статтю "Про вичіслімих числах", в якій розглядалося гіпотетичне пристрій ("машина Тьюринга"), придатний для вирішення будь-якої дозволеної математичної або логічного завдання, - прообраз програмованого комп'ютера.

В1941 році німецький інженер Конрад Цузе побудував діючий комп'ютер Z3, в якому використовувалася двійкова система числення. Програми записувалися на перфострічці.

У 1945 році у вищому технічному училищі Пенсільванського університету (США) фізик Джон Мочлі і інженер Проспер Екерт побудували повністю електронну машину "ЕНІАК". Для завдання програми було необхідно вручну встановити тисячі перемикачів і увіткнути сотні штекерів у гнізда контактній панелі.

1 червня 1945 був розісланий звіт американського математика угорського походження Джона фон Неймана "Попередній звіт про машину Едвак", що містить концепцію зберігання команд комп'ютера в його власної внутрішньої пам'яті.

21 червня 1948 в Манчестерському університеті (Великобританія) на машині "Марк-1" виконана перша в світі зберігається в пам'яті машини програма - пошук найбільшого сомножителя заданого числа.

У 1949 році під керівництвом Моріса Уїлкса створений комп'ютер "ЕДСАК". Проектувальники "ЕДСАК" ввели систему мнемонічних позначень, де кожна машинна команда уважали однією заголовною буквою, й автоматизували настройку підпрограм на певне місце в пам'яті. Моріс Уїлкс назвав мнемонічний схему і бібліотеку підпрограм збирає системою (assembly system) - звідси слово "асемблер".

У 1949 році у Філадельфії (США) під керівництвом Джона Мочлі створений "Короткий код" - перший примітивний інтерпретатор мови програмування.

У 1951 році у фірмі Remington Rand американська программістка Грейс Хоппер розробила першу транслює програму. Хоппер назвала її компілятором (compiler - компонувальник).

У 1957 році на 20-му поверсі штаб-квартири фірми IBM на Медісон-авеню в Нью-Йорку народився мова Фортран (FORmula TRANslation - трансляція формул). Групою розробників керував 30-річний математик Джон Бекус. Фортран - перший з "справжніх" мов високого рівня.

У 1972 році 31-річний фахівець з системного програмування з фірми Bell Labs Денніс Рітчі розробив мову програмування Сі.

У 1984 році французький математик і саксофоніст Філіп Кан засновує фірму Borland International.

Далі з'явився діалект мови Сі фірми B orland.

Спочатку Сі був розроблений як мова для програмування в операційній системі Unix.

Незабаром він став поширюватися для програмістів-практиків. В кінці 70-х були розроблені транслятори Сі для МікроЕОМ для операційною системою Ср / M.

Після появи IBM PC стали з'являтися і компілятори Сі (для цього комп'ютера їх зараз більше 20).

У 1983 р. Американський інститут стандартів (ANSI) сформував Технічний Комітет X3J11, для створення стандарту мови Сі. З'явився на ринку мова Сі + + корпорації Borland підкоряється більшості вимог стандарту.

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

Серед безлічі переваг мови Сі потрібно відзначити основні:

- Універсальність (використовується майже на всіх існуючих ЕОМ);

- Компактність і універсальність коду;

- Швидкість виконання програм;

- Гнучкість мови;

- Високу структурованість.


Глава 1. Основи мови Сі


  1. Алфавіт


Алфавіт мови складається з наступних символів:

Великі і малі латинські букви AZ, az і символ підкреслення. Цифр від 0 до 9. Спеціальних символів + - * / => <. ;,: [] {} () # $.

Символи пробіл, табуляція, переклад рядка, повернення каретки називаються пробільними.

Програма на C + + являє собою послідовність ACSII-символів, що представляють собою її вихідний текст.


1.2. Основні конструкції Сі


Розглянемо просту програму друку на екрані фрази "Привіт від ЕОМ"

# Include <stdio.h>

main ()

/ / Програма

{

printf ("Привіт від ЕОМ \ n");

}

Розглянемо структуру програми


C і-програма





# Директиви препроцесора







Main









Оператори











Функція 1 ()









Оператори







Функція n ()









Оператори





Описи




Присвоювання




Функції




Управління




Порожні


Команда # include підключає файл stdio.h до нашої програми. У файлі міститься відомості про функції введення-виведення.

Файл з ім'ям stdio.h містить інформацію про введення-виведення.

Символ # вказує, що перш ніж транслювати програму необхідно включити в неї функції з файлу stdio.h - це так звана препроцесорна обробка, яка здійснює деяку попередню обробку тексту програми перед початком компіляції.

Рядок main () містить назву функції, з якою завжди починається програма. Порожні дужки означають, що ця функції, але вона без параметрів.

Після символів / / стоять коментарі (для одного рядка), (коментарями також називаються символи, що стоять між / * і * /).

Фігурні дужки {} відзначають початок і кінець тіла програми або функції. Вони також застосовуються для об'єднання кількох операторів програми в блок.

У рядку printf ("Привіт від ЕОМ \ n") міститься стандартна функція друку Сі. Рядок символів, укладена в дужки (аргумент), є інформацією, що передається функції printf () з нашої головної функції main (). Коли виконання функції буде завершено, управління повернеться назад у вихідну програму. Символ \ n - позначає переклад рядка на новий рядок після друку.

Розглянемо наступний приклад - написати програму перекладу метрів в сантиметри.

# Include <stdio.h>

# Include <conio.h>

main ()

{

int I;

int J;

int C;

printf ("M? \ n");

scanf ("% d", & I);

J = 100 * I;

printf ("У% d М міститься% d cm \ n ", I, J);

C = getch ();

}

У даній програмі визначено дві цілочисельні змінні I і J.

Введена функція scanf ("% d", & I); яка дозволяє вводити десяткове число з клавіатури і значення привласнити змінній I, далі по команді J = 100 * I; йде вичісленіе4.

Наступний рядок printf ("У% d М міститься% d cm \ n", I, J); друкує фразу. На місце першого% d (d-ціла змінна) ставиться значення I, на місце другого% d ставиться значення J.

Функція getch () дозволяє затримати зображення на екрані і вимагає будь-якого символу, щоб закінчити роботу.

Розглянемо ще приклад. Напишемо функцію і викличемо її з нашої програми.

# Include <stdio.h>

# Include <conio.h>

supervisor ()

{

printf ("Ви мене викликали? \ n");

}

main ()

{

char C;

printf ("Я викликаю функцію supervisor. \ n ");

supervisor ();

printf ("Так. Подивіться, хто з студентів спить і розбудіть їх. \ n");

C = getch ();

}

Спочатку описуємо функцію supervisor (), а потім звертаємося до неї в основній програмі по команді supervisor ();. У результаті отримуємо діалог:

- Я викликаю функцію supervisor.

- Ви мене викликали?

- Так. Подивіться, хто з студентів спить, і розбудіть їх.


1.3 Введення-виведення


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

- Виділяти місце для зберігання даних;

- Вводити вихідних даних;

- Обробляти вихідні дані за алгоритмом;

- Виводити вихідні дані.

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

1.3.1. Висновок

Виведено на екран, принтер, вінчестер (гнучкі диски), порт. Розглянемо функції виводу на екран.

Функція printf призначена для цієї мети. Формат: printf (<формат> [, аргумент1 ],...).

Формат - це рядок в подвійних лапках, яка виводиться на екран. Перед висновком printf замінює всі об'єкти в рядку відповідно до специфікацій аргументу. Наприклад, printf ("У% d М міститься% d cm \ n", I, J);% d у рядку формату - це специфікація аргументу.

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

% D, що використовується в специфікації, говорить про те, що очікується деяке ціле число. Ось кілька інших общеіспользуемих специфікацій формату:

-% D ціле число;

-% U ціле число без знака;

-% Ld довге ціле число;

-% P значення покажчика;

-% F число з плаваючою точкою;

-% E число з плаваючою крапкою в експоненційної формі;

-% C Символи;

-% S рядок;

-% X ціле в шістнадцятковому форматі.

Можна задати ширину поля, наприклад% 6d-поле шириною 6.

Значення буде надруковано зрушеним вправо (попереду пробіли), так що загальна ширина поля дорівнює 6.

Для формату дійсних чисел можна вказати дробову частину, наприклад% 8.4f - поле шириною 8, десяткова частина 4.

В кінці рядка формату можна поставити знаки:

\ N переклад рядка;.

\ F (переклад формату або очищення екрана)

\ T (табуляція)

\ B (забій <-)

\ Xhhh (вставка символу c кодом ASCII hhh, де hhh містить від 1 до 3 16-ковий цифр)

Для висновку можна використовувати функції: puts і putchar.

Функція puts виводить рядок на екран. Наприклад:

# Include <stdio.h>

main ()

{

puts ("Привіт, студент");

}

Функція putchar виводить на екран один символ.


1.3.2 Введення

Введення в Сі в основному здійснюється з клавіатури, з файлу і порту.

Функція scanf аналогічна printf. Її формат: scanf (<формату> [, аргумент1 ],...). У scanf використовуються ті ж специфікатор формату, що і у функції printf. Необхідно відзначити, що scanf має одну особливість: аргументи, наступні за рядком формату, повинні бути адресами, а не значеннями (це не поширюється на символьні змінні). Раніше в прикладах ми бачили, що при введенні цілого числа записувалася функція наступним чином:

scanf ("% d", & a);

&-Операція адреси, яка передає scanf адреси.

При введенні декількох змінних через кому можна використовувати кому всередині формату. Приклад:

scanf ("% d,% d", & a, & b);

Тепер можна вводити, наприклад 23,56.

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

# Include <stdio.h>

main ()

{

char name [60];

printf ("Як вас кличуть: ");

gets (name);

printf ("Привіт,% s \ n", name);

}

Функція gets читає все, що набирається до тих пір, поки не натиснутий Enter.

У С + + введення-виведення може здійснюватися не тільки за допомогою функцій, але і за допомогою операцій. Операція виводу <<операція введення>>.

Формат виводу на екран: cout <<вираз.

Формат введення з клавіатури: cin <<змінна.

При використанні операцій введення-виведення необхідно включити в програму файл iostream.h.

Приклад:

# Include <iostream.h>

main ()

{

int i;

cout <<"Ціле число?: ";

cin>> i;

cout <<"Квадрат числа: "<<i * i <<" \ n ";

return 0;

}

Можливе введення-виведення декількох величин (через пробіл).

1.4 Базові типи даних Мови Сі


1.4.1 Ідентифікатори

Імена, які присвоюються константам, типами даних, змінним і функцій називаються ідентифікаторами. У Сі наступні правила створення ідентифікаторів: повинні починатися з букви (a. .. z, A. .. Z) або з підкреслення (_), інша частина ідентифікатора повинна складатися з літер, підкреслень і / або цифр (0 ... 9 ).


1.4.2 Типізовані константи

У Сі використовуються константи, які представляють собою ім'я, що привласнюється будь-якої величини. Ідентифікатор імені може бути будь-якої довжини, але розпізнаються перші 32 символу. Ідентифікатор починається з латинської букви або символу підкреслення, наступні символи можуть бути цифри, латинські літери і символи підкреслення.

Компілятор Сі розглядає літери верхнього та нижнього регістру як різні символи.

Типізовані константи бувають: цілі, з плаваючою комою, символьні константи і символьні рядки.

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

Опис констант починається з ключового слова const, далі тип і значення, наприклад const int Nalog = 2.


1.4.3 Змінні

Змінна - це пойменована величина, значення якої може змінюватися під час виконання програми. Змінна належить до певного типу.

1.4.3.1 Цілі типи

Цілі числа представляються цілими типами. Цілий тип - це узагальнений тип, представлення якого залежить від операційної системи і типу процесора.

Розглянемо основні типи цілих чисел:


Цілий тип

Розмір

Short int

16 бітове ціле

Int

16 бітове ціле

Unsigned long

32 бітове ціле без знаку

Long

32 бітове ціле


Розглянемо простий приклад.

# Include <stdio.h>

# Include <conio.h>

main ()

{

const int Nalog = 2;

int Stavka;

int Symma;

int C;

Stavka = 300;

Symma = Stavka * Nalog;

printf ("Symma naloga =% d \ n", Symma);

C = getch ();

}

У прикладі оголошені одна константа і дві змінні цілого типу.


1.4.3.2 Речові типи

Для зберігання чисел з дробовою частиною використовується дійсний тип.

У C + + існують такі основні типи дійсних чисел:

Речовий тип

Розмір

Float

32 бітове плаваюче число

Double

64 бітове плаваюче число

Long double

80 бітове плаваюче число


Розглянемо наступний приклад.

# Include <stdio.h>

main ()

{

const float Nalog = 0.7;

int Stavka;

float Symma;

Stavka = 325;

Symma = Stavka * Nalog;

printf ("Symma naloga =% 8.4f \ n", Symma);

}

У даному прикладі дійсний тип представлений змінною Symma.


1.4.3.3 Символьні типи

Символьний тип-Char призначений для зберігання одного символу, тому його розмір - один байт.


Символьний тип

Розмір

Unsigner char

8 біт без знака

Char

8 біт


Розглянемо приклад:

# Include <stdio.h>

main ()

{

char A;

char B;

char C;

A = 'D';

B = '!';

printf ("A =% c B =% c \ n", A, B);

C = '*';

printf ("C =% c \ n", C);

}

У даному прикладі змінної A присвоєно значення 'D', змінної B значення '!', А змінній З присвоєно значення символу '*'.


1.4.4 Тип даних рядок

Для представлення рядка символів в Сі використовують масиви типу char.

Розглянемо приклад.

# Include <stdio.h>

# Include <string.h>

main ()

{

char A [256]; / * довжина може бути до 256 символів * /

char B [11];

char C [24];

strcpy (A, "IBM PC Pentium");

strcpy (B, "Windows 95");

strcpy (C ,""); / * очищення змінної * / printf ("A =% s ​​\ n", A);

printf ("B =% s ​​\ n", B);

strcpy (C, B);

printf ("C =% s ​​\ n", C);

}

У даному прикладі представлені три рядки символів A, B, C.

По команді, наприклад, strcpy (A, "IBM PC Pentium"); в рядок A вміщується текст IBM PC Pentium.

Крім розглянутого прикладу, для визначення рядків можна використовувати покажчик на символи. Приклад:

# Include <stdio.h>

# Include <string.h>

main ()

{

char * msg;

msg = "Привіт, студент";

puts (msg);

}

Зірочка перед msg означає, що msg є покажчиком на символ - тобто msg може зберігати адресу символу. Однак, при цьому пам'ять для розміщення символів не виділяється.

Команда msg = "Привіт, студент" привласнює початковий адресу цього рядка - (адреса символу П) змінної msg. Команда puts (msg) друкує символи до тих пір, поки вона не зустріне нульовий символ, що позначає кінець рядка ..


1.4.5 Структури

Розміщена в пам'яті сукупність пов'язаних між собою даних представляє структуру. У Сі розглядаються наступні структури: масиви, записи та їх комбінації.


1.4.5.1 Масиви

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

Розглянемо приклад.

# Include <stdio.h>

main ()

{

int B [3];

B [0] = 0;

B [1] = 10; B [2] = 20; B [3] = 30;

printf ("B [0] =% d \ n", B [0]);

printf ("B [1] =% d \ n", B [1]);

printf ("B [2] =% d \ n", B [2]);

printf ("B [3] =% d \ n", B [3]);

}

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

Існують багатовимірні масиви, наприклад:

int A [3] [2];

Масив A-двовимірний масив (складається з чотирьох рядків і трьох стовпців):

char A [3] [3] [3] [3];

Масив A - чотиривимірний масив.

Розглянемо приклад роботи з двовимірним масивом.

# Include <stdio.h>

main ()

{

float B [4] [3];

B [0] [0] = 0;

B [1] [1] = 1.1;

B [2] [1] = 1.2; B [3] [1] = 1.3;

B [1] [2] = 2.1;

B [2] [2] = 2.2;

B [3] [2] = 2.3;

printf ("B [1,1] =% 4.2f B [2,1] =% 4.2f B [3,1] =% 4.2f \ n", B [1] [1], B [2] [ 1], B [3] [1]);

printf ("B [1,2] =% 4.2f B [2,2] =% 4.2f B [3,2] =% 4.2f \ n", B [1] [2], B [2] [ 2], B [3] [2]);

}


1.4.5.2 Записи

На відміну від масивів запис дозволяє зберігати дані різних типів. Запис починається після ключового слова struct. Розглянемо приклад - у запису зберігається інформація про студентів: прізвище, рік народження, номер групи.

# Include <stdio.h>

# Include <string.h>

typedef struct A {

char Fio [31];

int God;

int Gruppa;

};

main ()

{

struct AB;

strcpy (B. Fio, "Ivanow GI"); B. God = 1977;

B. Gruppa = 384;

printf ("Fio =% s ​​\ n", B. Fio);

printf ("God =% d \ n", B. God);

printf ("Gruppa =% d \ n", B. Gruppa);

}

У розглянутому прикладі запис має наступну структуру:

struct A {/ * A ім'я запису} * /

char Fio [31]; / * 1 поле запису * /

int God; / * 2 полі запису * /

int Gruppa; / * 3 полі запису * /

}

Далі можемо ввести структуру B аналогічну A по команді

struct AB;

Далі можемо в поля поміщати конкретні дані, але ми повинні уточнити, що поля належать змінної B нотацією з точкою (B. Fio: = "Ivanow GI", і т.д.).

За допомогою ключа typedef структурам дається ім'я.

Приклад можна переписати таким чином.

# Include <stdio.h>

# Include <string.h>

typedef struct {

char Fio [31];

int God;

int Gruppa;

} A;

main ()

{

AB;

strcpy (B. Fio, "Ivanow GI");

B. God = 1977;

B. Gruppa = 384;

printf ("Fio =% s ​​\ n", B. Fio);

printf ("God =% d \ n", B. God);

printf ("Gruppa =% d \ n", B. Gruppa);

}

У прикладі ми розглянули один запис, але в реальному житті в групі не може бути одного студента, тому ми можемо поєднати масив і запис і створити масив записів. Розглянемо приклад.

# Include <stdio.h>

# Include <string.h>

typedef struct A {

char Fio [31];

int God;

int Gruppa;};

main ()

{

A WGruppa [12];

strcpy (WGruppa [1]. Fio, "Ivanow GI");

WGruppa [1]. God = 1977;

WGruppa [1]. Gruppa = 384;

strcpy (WGruppa [2]. Fio, "Petrow RG");

WGruppa [2]. God = 1978;

WGruppa [2]. Gruppa = 384;

printf ("Fio1 =% s ​​\ n", WGruppa [1]. Fio);

printf ("God1 =% d \ n", WGruppa [1]. God);

printf ("Gruppa1 =% d \ n", WGruppa [1]. Gruppa);

printf ("Fio2 =% s ​​\ n", WGruppa [2]. Fio);

printf ("God2 =% d \ n", WGruppa [2]. God);

printf ("Gruppa2 =% d \ n", WGruppa [2]. Gruppa);

}

Спочатку ми визначили структуру A, а потім використовували її при оголошенні структури WGruppa, як масиву складається з 12 записів структури B.

Тепер для адресації ми повинні вказати номер елемента масиву і ім'я поля.

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

# Include <stdio.h>

# Include <string.h>

typedef struct Adress {

char City [31];

char Street_Nd_Kw [61];};

typedef struct A {

char Fio [31];

int God;

int Gruppa;

Adress D_addr;};

main ()

{

A WGruppa [12];

strcpy (WGruppa [1]. Fio, "Ivanow GI");

WGruppa [1]. God = 1977;

WGruppa [1]. Gruppa = 384;

strcpy (WGruppa [1]. D_addr.City, "Shadrinsk"); strcpy (WGruppa [1]. D_addr.Street_Nd_Kw, "Lenina 10 kw.1");

strcpy (WGruppa [2]. Fio, "Petrow RG");

WGruppa [2]. God = 1978;

WGruppa [2]. Gruppa = 384;

strcpy (WGruppa [2]. D_addr.City, "Kataisk"); strcpy (WGruppa [2]. D_addr.Street_Nd_Kw, "Akulowa 1 kw.2");

printf ("Fio1 =% s ​​\ n", WGruppa [1]. Fio);

printf ("God1 =% d \ n", WGruppa [1]. God);

printf ("Gruppa1 =% d \ n", WGruppa [1]. Gruppa);

printf ("City =% s ​​\ n", WGruppa [1]. D_addr.City);

printf ("Street =% s ​​\ n", WGruppa [1]. D_addr.Street_Nd_Kw);

printf ("Fio2 =% s ​​\ n", WGruppa [2]. Fio);

printf ("God2 =% d \ n", WGruppa [2]. God);

printf ("Gruppa2 =% d \ n", WGruppa [2]. Gruppa);

printf ("City =% s ​​\ n", WGruppa [2]. D_addr.City);

printf ("Street =% s ​​\ n", WGruppa [2]. D_addr.Street_Nd_Kw);

}


1.4.6 Область видимості та час життя змінних

По області видимості змінні в Сі можна розділити на три групи:

  1. Змінна, визначена в усіх модулях (файлах) програми. Така змінна визначається за допомогою ключового слова extern. Ця змінна буде видно у всіх точках програми. Така змінна є глобальної для всієї програми.

  2. Змінна, визначена в одному з модулів (файлі) перед текстами всіх функцій. Така мінлива буде глобальною для даного модуля, тобто може бути використана в усіх точках даного модуля.

  3. Змінна певна в даній функції. Ця змінна може бути використана тільки в межах даної функції. Таку змінну ми будемо називати локальною.

За часом життя всі змінні можна розділити на дві групи:

  1. Змінні живуть протягом роботи програми.

  2. Змінні знищуються після виходу з функції.

Глобальні змінні ставляться до першого типу за часом життя. Локальні змінні знищуються по виходу з функції. У тому випадку, коли ми хочемо зробити локальну змінну долгоживущей використовується слово static. Локальні змінні мають такий тип живуть починаючи з моменту першого виклику функції та до завершення програми. Однак у сенсі видимості ці змінні залишаються локальними. Запис static int i = 0; означає, що змінна ініціалізується нулем при першому вході у функцію, але при наступних входах у функцію її значення зберігається в залежності від тих дій, які над нею були зроблені.

Сучасні компілятори Сі транслюють програму так, щоб максимально оптимізувати її роботу. Одним із засобів оптимізації це зберігання змінних, коли це можливо в регістрах, замість елементів пам'яті. У тих випадках коли ви хочете заборонити, щоб дана змінна зберігалася в регістрах використовується модифікатор volatile. Така необхідність може виникнути, якщо передбачається можливість зміну змінної в результаті зовнішнього впливу (наприклад переривання).

І останнє зауваження. Динамічно виділена пам'ять, де б ви її не виділяли живе до тих пір, поки ви її не звільнили.


1.5 Основні оператори


Операція присвоювання.

Найзагальнішою операцією є присвоювання, наприклад, з = a / b. У Сі присвоювання позначається знаком рівності =, при цьому значення праворуч від знаку рівності присвоюється змінної ліворуч. Можливо, застосовувати також послідовні привласнення, наприклад: з = a = b.

Арифметичні оператори.

У Сі виконуються наступні групи арифметичних операцій:

1.Бінарние: додавання (+), віднімання (-), множення (*), ділення (/), цілочисельне ділення (%) (для типу int отримання залишку).

2.Унарние: унарний плюс (+), унарний мінус (-), адресація (&), непряма адресація (*), визначення розміру пам'яті типу (sizeof).

3.Логіческіе: і (&&), або (!!), НЕ (!=).

4.Отношенія:

a) дорівнює (==), не дорівнює (!>);

б) менше ніж (<), більше ніж (>), менше або дорівнює (<=), більше або дорівнює (>=);

5.Пріращенія (+ +) і зменшення (--). Наприклад, i + + позначає, що i = i +1, а i - позначає i = i-1.

6.Побітовие операції - дозволяють робити операції над бітами.

7.Комбінірованние операції. У Турбо-Сі існують скорочення при написанні виразів, що містять численні операції:

a = a + b; скорочується до a + b =;

a = a - b; скорочується до a -= b;

a = a * b; скорочується до a *= b;

a = a / b; скорочується до a / = b;

a = a% b; скорочується до a% = b;

8.Адресние операції:

1. Операція визначення адреси (&) 2. Операція звернення за адресою (*).

Операція & повертає адресу даної змінної; якщо Х є змінною типу int, то & Х є адресою (розташування в пам'яті) цієї змінної. З іншого боку, якщо msg є покажчиком на тип char, то * msg є символом, на який вказує msg. Розглянемо приклад:

# Include <stdio.h>

main ()

{

int X;

char * msg;

X = 6 + 1;

msg = "Привіт \ n";

printf ("X =% d & X =% p \ n", X, & X);

printf ("* msg =% c msg =% p \ n", * msg, msg);

}

При друку в першій функції друкується два значення: значення X 7 і адреса X (призначуваний компілятором). У другій функції також друкується два значення: символ, на який вказує msg (П), і значення msg, яке є адресою цього символу (також призначений компілятором).

Старшинство операцій в Сі відповідає старшинством операцій в математиці.

Оператор кома.

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

char X, Y;

(X = Y, Y = getch ())

присвоює змінної X значення Y, потім зчитує символ, що вводиться з клавіатури, і запам'ятовує його в Y. Результатом всього виразу, в результаті, буде значення введеного з клавіатури символу.

Оператори управління.

Оператор If ... дає можливість в залежності від умови виконувати ту чи іншу гілку програми. Синтаксис оператора наступний:

If умова вираз1 else вираз2;

Умова повинно давати результат у вигляді логічного значення істинності або хибності. Вираз1 буде виконуватися якщо умова істинна. Вираз2 буде виконуватися якщо умова помилкова.

Існує скорочений варіант оператора:

If умова вираз1

Приклад. Визначити, чи є введене число днем тижня, тобто чи входить число в діапазон від 1 до 7.

# Include <stdio.h>

int A;

main ()

{

printf ("?");

scanf ("% d", & A);

if ((A <1) | | (A> 7))

printf ("Error% d \ n", A);

else printf ("OK% d \ n", A);

}

Вираз умови (A <1) | | (A> 7) буде давати TRUE, якщо виконується A <1 або A> 7 - у цьому випадку виконується гілка printf ('Error', A);, інакше гілка printf ('OK' , A);.

Існує інший варіант запису оператора If ... Приклад:

# Include <stdio.h>

main ()

{

int y, t;

printf ("?");

scanf ("% d", & t);

y = (t> 0)? t * 10: t-10; / * if t> 0 y = t * 10 else y = t-10; * /

printf ("OK% d \ n", y);

}

У даному варіанті вид оператора показаний в коментарях.

Оператор switch ... case використовується у випадку, коли необхідно аналізувати змінну і залежно від її значення виробляти ті чи інші дії. Розглянемо приклад. З клавіатури вводяться літери латинського алфавіти. У залежності від букви провести ті чи інші дії.

# Include <stdio.h>

char A;

main ()

{

printf ("?");

scanf ("% c", & A);

switch (A) {

case 'c': printf ("smoll% c \ n", A); break; / * вихід з блоку * /

case 'F':

case 'G': printf ("big% c \ n", A);

break;

default: printf ("Error% c \ n", A);

}

}

У даному прикладі якщо введений символ с, то виконується printf ("smoll% c \ n", A);, якщо вводиться заголовні букви F або G, то виконується printf ("big% c \ n", A);, якщо не один з розглянутих символів не вводиться, то виконується printf ("Error% c \ n", A);.

Для повторення деякої безлічі команд кілька разів можна використовувати оператор do ... while. Розглянемо приклад.

# Include <stdio.h>

main ()

{

int A;

do {

printf ("Zifra?");

scanf ("% d", & A);

printf ("Error% d \ n", A);

} While (! (A == 9));

printf ("OK% d \ n", A);

}

З клавіатури вводиться число. Виконується оператор printf ("Error% d \ n", A);. Далі йде аналіз - одно число 9 чи ні, якщо не дорівнює, знову виконується тіло циклу:

printf ("Zifra?");

scanf ("% d", & A);

printf ("Error% d \ n", A).

Якщо число дорівнює 9, то виконується оператор printf ("OK% d \ n", A); і робота циклу закінчується.

Головною особливістю оператора do ... while є той факт, що тіло циклу, укладену між операторами do і while виконується хоча б один раз, тобто спочатку виконується тіло циклу, а потім йде аналіз умови.

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

Оператор while ... на відміну від do ... while спочатку аналізує умова, а потім виконує тіло циклу.

Приклад.

# Include <stdio.h>

main ()

{

int A;

A = 0;

while (A! = 9)

{

printf ("Zifra?");

scanf ("% d", & A);

printf ("Error% d \ n", A);

}

printf ("OK% d \ n", A);

}

У даному прикладі ініціалізований мінлива A: = 0;. Це зроблено, тому що спочатку йде аналіз дорівнює вона 9 чи ні. Якщо не дорівнює, то виконується тіло циклу. Сенс розглянутого оператора полягає в наступному:

«Поки істинно умова виконуй тіло циклу».

Оператор for ... використовується, коли відомо скільки разів необхідно виконати тіло циклу, але цей оператор горазда гнучкіше порівняно з Паскалем. Розглянемо приклад.

# Include <stdio.h>

int A;

main ()

{

for (A = 1; A <= 5; A + +) / * A + + означає A = A-1 * /

printf ("Zifra% d \ n", A);

}

У цьому прикладі A зберігає стан лічильника циклу. Спочатку A: = 1. Виконується оператор printf ("Zifra% d \ n", A). Далі значення A збільшується на одиницю. Йде аналіз A <= 5 чи ні. Якщо A більше 5, то цикл закінчує роботу. Якщо ні, то знову виконується оператор printf ("Zifra% d \ n", A).

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

# Include <stdio.h>

int A;

main ()

{

for (A = 5; A> = 1; A -) / * A - означає A = A-1 * /

printf ("Zifra% d \ n", A);

}

Існує безліч модифікацій оператора for ..., наприклад:

- Порожній оператор - для тимчасової затримки:

for (n = 1; n <= 10000; n + +)

/ * Порожній оператор * /

- Використання різного кроку:

for (n = 1; n <= 230; n = n +10)

- Зміна змінних:

for (x = 2; n * n <= 476; n = 5 * x + +)

Розглянемо приклад, в якому не започатковано дві змінні і кожна з яких, змінюється після ітерації циклу:

# Include <stdio.h>

# Define f 30

# Define n 19

main ()

{

int y, t;

for (y = 1, t = f; y <= 16; y + +, t + = n) / * t + = n означає t = t + n * / printf ("% 3d% 7d \ n", y, t);

}

Далі розглянемо, оператори розгалуження (оператори переходу з однієї частини програми в іншу).

Оператор goto дозволяє передавати управління на будь-який рядок програми. Для цієї мети використовується мітка. Приклад.

# Include <iostream.h>

# Include <stdio.h>

main ()

{

char A;

label_1: / * мітка * / printf ("? \ n");

cin>> A;

if (A! = 'y') goto label_1;}

Для переривання циклу по деякому умові можна використовувати оператор break. Приклад.

# Include <stdio.h>

# Include <iostream.h>

char A;

int I;

main ()

{

for (I = 1; I <= 10; I + +)

{

printf ("? \ n");

cin>> A;

i (A == 'y') break;

}

}

Для переривання ітерації циклу і переходу до наступної ітерації використовується оператор Continue. Приклад.

# Include <stdio.h>

# Include <iostream.h>

char A;

int I;

main ()

{

for (I = 1; I <= 10; I + +)

{

printf ("? \ n");

cin>> A;

if (A == 'y') continue;

printf ("Працює% c \ n", A);

}

}

Для переривання програми також використовуються оператори return () і exit ().


1.6. Препроцесор


Препроцесор мови Сі дозволяє перед початком трансляції включати в програму фрагменти програм, написаних окремо від основної.

Директива # define.

Директива # define може з'являтися в будь-якому місці програми, а що дається нею визначення має силу від місця до кінця програми.

# Include <iostream.h>

# Include <stdio.h>

# Define TRI 3

# Define OTWET TRI * TRI

# Define OT printf ("ВІДПОВІДЬ дорівнює% d. \ n ", OTWET)

# Define jd cin>> C;

main ()

{

int C;

OT;

jd;

}

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

ВІДПОВІДЬ дорівнює 9

У першому рядку програми TRI - це макроозначень і воно дорівнює 3, де 3 - рядок заміщення.

У другому рядку макроозначень OTWET має рядок заміщення TRI * TRI і т.д. Кожен рядок складається з трьох частин. Першою стоїть директива # define, далі йде макроозначень. Макроозначень не повинно містити в собі прогалини. І, нарешті, йде рядок (звана "рядком заміщення"), яку представляє макроозначень. Коли препроцесор знаходить у програмі один з макроозначень, він замінює його рядком заміщення. Цей процес проходження від макровизначеннями до заключної рядка заміщення називається "макрорасшіренія".

Директива # include.

Коли препроцесор "розпізнає" директиву # include, він шукає таке за нею ім'я файлу і включає його в поточну програму. Директива буває у двох видах:

# Include <stdio.h> ім'я файлу в кутових дужках

# Include "my.h" ім'я файлу в подвійних лапках

Кутові дужки повідомляють препроцесора, що файл слід шукати в одному або декількох стандартних системних каталогів. Лапки говорять йому, що спочатку потрібно дивитися в робочому каталозі, а потім шукати в "стандартних" місцях.

Директиви: # undef, # ifdef, # else, # endif

Ці директиви дозволяють призупинити дію більш ранніх визначень.

Директива # undef скасовує саме останнє визначення пойменованого макровизначеннями.

# Define TRI 3

# Define F 5

# Undef TRI / * TRI тепер НЕ визначено * /

# Define F 10 / * F перевизначений як 10 * /

# Undef F / * F знову дорівнює 5 * /

# Undef F / * F тепер не визначений * /

Розглянемо ще приклад.

# Ifdef OTW

# Include "otw.h" / * виконається, якщо OTW визначений * /

# Define ST 10

# Else

# Include "wh" / * виконається, якщо OTW НЕ визначено * /

# Define ST 20

# Endif

Директива ifdef повідомляє, що якщо наступний ідентифікатор OTW визначається препроцесором, то виконуються всі наступні директиви аж до першої появи # else або # endif. Коли в програмі є # else, то програма від # else до # endif буде виконуватися, якщо ідентифікатор не визначений.


1.7 Програми. Функції


Як ми розглядали раніше, програма на Сі має кореневої сегмент, що починається з директив препроцесора і ключового слова main.

Далі йде власне програма, що починається з відкривається фігурної дужки {і закінчується закривається фігурною дужкою}.

Часто використовувані ділянки програми виділяються у функції. Кожна функція також починається з директив препроцесора і імені та дужок {}.

Розглянемо приклад програми малювання сходів.

# Include <stdio.h>

main ()

{

printf ("|----| \ n ");

printf ("|----| \ n ");

printf ("|----| \ n ");

}

А тепер напишемо цю програму з використанням функції Lestniza.

# Include <stdio.h>

Lestniza (void)

{

printf ("|----| \ n ");

}

main ()

{

Lestniza ();

Lestniza ();

Lestniza ();

}

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

# Include <stdio.h>

int C;

Lestniza (int B) / * B - формальний аргумент * /

{

int A;

for (A = 1; A <= B; A + +)

printf ("|----| \ n ");

}

main ()

{

Lestniza (3); / * 3 - фактичний аргумент * /

}

У даній функції B є формальним аргументом (кінцева величина оператора for to). Для присвоєння їй конкретного значення використовується фактичний аргумент, який передається функції при її виклику в основній програмі.

Якщо у функцію передається кілька параметрів, то вони повинні передаватися в тому порядку, в якому записані у функції.

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

# Include <stdio.h>

float Kwadrat (float A)

{

return A * A;

}

float B;

main ()

{

printf ("? \ n");

scanf ("% f", & B);

printf ("Kwadrat =% 8.2f \ n", Kwadrat (B));

}

Як видно з прикладу - ім'я функції Kwadrat - вона обчислює квадрат числа. У рядку printf ("Kwadrat =% 8.2f \ n", Kwadrat (B)); ця функція викликається - на вхід подається значення (введене число), а в результаті отримуємо результат - квадрат числа, який повертається в програму по команді return.

Розглянемо ще один варіант роботи з функцією, яка повертає значення без команди return.

# Include <stdio.h>

Kwadrat (float A, float * B)

{

* B = A * A;

}

float C, D;

main ()

{

printf ("? \ n");

scanf ("% f", & C);

Kwadrat (C, & D);

printf ("Kwadrat =% 8.2f \ n", D);

}

1.8. Покажчики


Покажчик - це змінна, що містить адресу даних, а не їх значення. Покажчик використовується:

1.Для зв'язку незалежних структур один з одним.

2.Для динамічного розподілу пам'яті.

3.Для доступу до різних елементів структури.

Розглянемо наступну програму:

# Include <stdio.h>

main ()

{

int Z, * Y;

Y = &Z;

Z = 100;

printf ("Пряме значення Z:% d \ n", Z);

printf ("Значення Z, отримане через покажчик:% d \ n", * Y);

printf ("Адреса Z через отримання адреси:% p \ n", & Z);

printf ("Адреса Z через покажчик:% p \ n", Y);

}

У даному прикладі Y покажчик на цілу змінну і містить її адресу. У свою чергу & дозволяє отримати адресу за яким розміщено значення змінної Z. У цій програмі:

- Адресу змінної Z присвоюється Y;

- Ціле значення 100 присвоюється Z;

- Оператор &, дозволяє отримати адресу,

по якому розміщено значення Z.

Результат роботи програми:

Пряме значення Z: 100

Значення Z, отримане через покажчик: 100

Адреса Z через отримання адреси: 85B3: 0FDC

Адреса Z через покажчик: 85B3: 0FDC

Покажчики також використовуються для оптимального розподілу пам'яті.

Розглянемо приклад покажчика на число типу char.

# Include <stdio.h>

# Include <alloc.h>

# Include <string.h>

# Include <stdlib.h>

# Include <process.h>

int main (void)

{

char * str; / * вказівник на символьну змінну * /

str = (char *) malloc (10);

strcpy (str, "Hello");

printf ("String is% s \ n", str);

free (str);

return (0);

}

Спочатку по команді char * str; створений тип str, який є покажчиком на змінну типу char (* позначає "покажчик"). За командою str = (char *) malloc (10); виділяємо 10 байт пам'яті під змінну str (типу рядок). За командою strcpy (str, "Hello"); здійснюється - "записати в область пам'яті, на яку вказує str, рядок символів" Hello ". По команді printf (" String is% s \ n ", str); здійснюється" надрукувати на екрані те, на що вказує str. Команда free (str); звільняє пам'ять, на яку вказує str.

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

# Include <stdio.h>

# Include <string.h>

# Include <alloc.h>

# Include <process.h>

struct Student {/ * запис Student * /

char Fio [30]; / * поле запису Fio * /

int Gruppa; / * полі запису Gruppa * /

} / * Кінець запису * /

struct Student * A;

main ()

{

if ((A = (Student *) malloc (sizeof (Student))) == NULL)

{

printf ("Ні пам'яті \ n ");

exit (1);

}

strcpy (A [1]. Fio, "Ivanov");

A [1]. Gruppa = 385;

printf ("Fio1% s \ n Gruppa% d \ n", A [1]. Fio, A [1]. Gruppa);

strcpy (A [2]. Fio, "Petrow");

A [2]. Gruppa = 386;

printf ("Fio2% s \ n Gruppa% d \ n", A [2]. Fio, A [2]. Gruppa);

free (A);

}

Покажчик також може використовуватися для отримання непрямого покажчика на структуру.

Нехай poit є покажчиком на структуру і що elem елемент, певний структурним шаблоном. Тоді point-> elem визначає елемент, на який виконується посилання. Розглянемо попередній приклад.

struct Student {/ * запис Student * /

char Fio [30]; / * поле запису Fio * /

int Gruppa; / * полі запису Gruppa * /

} / * Кінець запису * /

Student * poin;

Зараз до полів структури ми можемо звертатися декількома способами. Еквівалентні звернення:

Student.Gruppa = 236;

poin-> Gruppa = 236;

Відзначимо одну важливу особливість покажчиків в Сі. Транслятор автоматично враховує тип покажчика в арифметичних діях над ним. Наприклад якщо i є вказівник на цілу (тобто двухбайтное) змінну, то дія типу i + + означає, що покажчик чинить зріст не один, а два байти, тобто буде вказувати на наступну змінну або елемент масиву. З цієї причини покажчик можна використовувати замість індексів масиву. Наприклад якщо A - покажчик на масив цілого типу, то замість A [i] можна писати * (A + i). Більш того, використання покажчиків замість індексів дозволяє компілятору створювати більш компактний і швидкий код.


1.9 Покажчики та функції


Покажчики також можна використовувати як формальних параметрів функції. Розглянемо приклад.

Функція swap (обмін) оголошує два формальних параметра x і y, як покажчики на дані типу int. Це означає, що функція swap працює з адресами цілих змінних (а не з їх значеннями). Тому будуть оброблені дані, адреси яких передані функції під час звернення до неї. Функція main (), викликає swap.

# Include <stdio.h>

swap (int * x, int * y)

{

int wr;

wr = * x; * x = * y; * y = wr;

}

main ()

{

int i, j;

i = 100;

j = 200;

printf ("Було: i =% d, j =% d \ n", i, j);

swap (& i, & j);

printf ("Стало: i =% d, j =% d \ n", i, j);

}

Після виконання програми значення i і j поміняються місцями. Необхідно відзначити, що хоча покажчики і економлять пам'ять, але вони використовують час процесора горазда більше.

Таким чином, розглянуті основні елементи мови Сі.


1.10 Файли


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

Розглянемо спершу режим послідовного доступу.

Введення-виведення буферизованная. Це означає, що програма пише і читає в буфер; обмін даними між буфером і файлом відбувається у випадку, якщо буфер повний, або відбулося закриття файлу, або перед виходом з програми.

Розглянемо приклад: вважати дані з одного файлу і переписати в іншій.

# Include <stdio.h>

main ()

{

FILE * in, * out;

char n1 [8], n2 [8];

printf ("Вихідний файл \ n ");

gets (n1);

printf ("Вихідний файл \ n ");

gets (n2);

if ((in = fopen (n1, "rt "))== NULL)

{

printf ("Не можу відкрити вихідний файл \ n"); return 1;

}

if ((out = fopen (n2, "wt "))== NULL)

{

printf ("Не можу відкрити вихідний файл \ n"); return 1;

}

while (! feof (in))

fputc (fgetc (in), out);

fclose (in);

fclose (out);

}

Рядок FILE * in, * out; визначає покажчик на два файли. Ім'я файлу м.б. будь-яким-в нашому випадку in - вихідний файл, out - вихідний.

У наступному рядку char n1 [8], n2 [8]; визначаємо дві змінні n1 і n2 для зберігання імен файлів. Наступні чотири рядки дозволяють ввести імена вхідного і вихідного файлу і привласнити ці імена змінним n1 і n2. Перш ніж почати працювати з файлом він повинен бути відкритий. Для цього існує функція fopen () в якій перший параметр містить ім'я файлу, а другий - вид роботи, наприклад "rt" - читати файл.

Команда in = fopen (n1, "rt" викличе відкриття файлу, запомненного у змінній n1 на читання, і в програмі буде повернений покажчик in на цей файл, яким (покажчиком) ми й будемо користуватися при читанні символів з ​​файлу. Якщо файл не існує , то значення fp буде NULL, відбудеться виконання fprintf (stderr, "Не можу відкрити вихідний файл \ n"); return 1; і програма завершить роботу.

Аналогічно працює функція out = fopen (n2, "wt", тільки тепер out - вихідний файл, а вид роботи "wt"-запис у файл).

За цією командою створюється файл під ім'ям, записаним у змінній n2.

Читання з файлу здійснюється викликом fgetc (in). Читається один символ з файлу, пов'язаного з покажчиком in.

За командою fputc (fgetc (in), out); лічений символ записується у файл out. Для читання інформації з усього файлу використовується конструкція while (! Feof (in))

fputc (fgetc (in), out);.

Функція feof (in) повертає величину, відмінну від нуля, якщо перебуває в кінцевій позиції, і нуль - в іншому випадку. Ще не зустрінеться нуль, дані з вихідного файлу читаються і записуються у вихідний.

Закриття файлу відбувається при виклику функції fclose (). Якщо при цьому файл був відкритий на запис, відбувається виведення вмісту буфера, пов'язаного з цим файлом. Зв'язок між дороговказом і файлом розривається.

Аналогічно функція fgetc (string, n, fp) читає з файлу, пов'язаного з fp, рядок і поміщає її в string. Символи читаються, поки не буде отриманий символ '\ n', або поки не вичерпається файл, або поки не буде прочитано (n-1) символів.

Режим прямого доступу більш гнучкий, тому що дозволяє звертатися безпосередньо до будь-якого запису файлу. Мінімальною записом для файлу прямого доступу є байт. Нижче буде розглянуто випадок файлу прямого доступу з записом рівної байту. Такі файли називаються двійковими. Файли прямого доступу незамінні при написанні програм, які повинні працювати з великими обсягами інформації, що зберігаються на зовнішніх пристроях. В основі обробці СУБД лежать файли прямого доступу.

Коротко викладемо основні положення роботи з файлами прямого доступу.

1). Кожен запис у файлі прямого доступу має свій номер. Записи нумерются від 0 до N -1, де N - кількість записів у файлі. Для двійкового файлу N збігається з довжиною файлу в байтах. Для відкритого файлу один із записів є поточною - кажуть, що покажчик встановлений на даний запис. Переміщати вказівник можна за допомогою функції lseek.

2). При відкритті (або створення файлу) покажчик автоматично поміщається на початок (запис 0). При виконанні операцій читання або запису покажчик автоматично переміщається за останню зчитану (записану запис) запис.

3). Змінити розмір файлу (збільшити або урізати) можна за допомогою функції chsize. При збільшенні розміру файлу до нього додаються записи, заповнені кодами 0.

Нижче представлена ​​програма, що демонструє роботу з файлами.

# Include <stdio.h>

# Include <io.h>

# Include <string.h>

# Include <fcntl.h>

# Include <SYS\STAT.H>

void main ()

{

int h / * дескриптор створюваного файлу * /

char * s = "Цей рядок буде поміщена в файл";

char buf [7]; / * буфер для читання з файлу * /

_fmode = O_BINARY; / * працюємо з двійковими файлами * /

if ((h = creat ("proba.txt", S_IREAD | S_IWRITE ))==- 1) / * створити файл * /

{

printf ("Не вдалося відкрити файл! \ n");

exit (1);

}

write (h, s, strlen (s)); / * записати в файл рядок s * /

lseek (h, 4, SEEK_SET) / * четвертий байт від початку файлу * /

read (h, buf, 6); / * читати слово 'рядок' (6 байт) з файлу * /

buf [6] = 0; / * відзначаємо кінець рядка * /

close (h) / * закрити файл * /

printf ("% s \ n", buf) / * друк ліченої рядка * /

}

Наша програма досить повно прокоментовані, тому ми наводимо досить короткі пояснення. Програма створює файл прямого доступу і записує туди послідовність байт (рядок). Далі відбувається пряме звернення до підрядку цього рядка безпосередньо у файлі. При розборі тексту програми звернемо читачів на деякі моменти:

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

  2. При вдалому відкритті файлу йому відводиться дескриптор (унікальне число), за яким потім можна до файлу звертатися.

  3. Нарешті не забувайте, що рядок тільки тоді стане рядком, коли в кінці стоїть код \ 0.

Наприкінці нашого розгляду файлів відзначимо, що наш виклад стосувалося роботи з файлами в середовищі MS DOS. Робота з файлами в ОС Windows декілька відрізняється від розглянутого і грунтується на використанні спеціальних функцій API (про програмування в Windows див. нижче).

1.11 Додаткові функції Сі


1.11.1 Функції перетворення

Є мінлива С:

ФУНКЦІЯ ПЕРЕВІРЯЄ, ЧИ Є C

isalpha (c) буквою

isdigit (c) цифрою

islower (c) рядкової буквою

isspace (c) порожнім символом (пробіл, табуляція або новий рядок)

isupper (c) прописною літерою

isalnum (c) алфавітноціфровим (буква або цифра)

isascii (c) кодом ASCII (0-127)

iscntrl (c) керуючим символом

ispunct (c) знаком пунктуації

toupper (c) перетворить c на велику букву

tolower (c) перетворить c в малу літеру

Приклад: перетворить букву A з великої в рядкову a.

# Include <stdio.h>

# Include <ctype.h>

main ()

{

char Z, Y = 'A';

printf ("Було% c \ n", Y);

Z = tolower (Y);

printf ("Стало% c \ n", Z);

}


1.11.2 Перетворення символьних рядків: atoi (), atof ()

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

Для цього використовуються функції atoi () і atof (). Перша перетворює рядок у ціле, друга - у число з плаваючою крапкою. Приклад:

# Include <stdlib.h>

# Include <stdio.h>

main ()

{

char ch [10];

int integ;

puts ("Введіть, будь ласка, ціле");

gets (ch);

integ = atoi (ch);

printf ("Число було% d. \ n", integ);

}


1.11.3 Функції, що працюють з рядками

strlen () - знаходить довжину рядка;

strcat () - об'єднує два рядки;

strcmp () - порівнює рядки;

strcpy () - копіює рядка.

Розглянемо приклад.

# Include <string.h>

# Include <stdio.h>

main ()

{

char k [60] = "Є в дощі одкровення";

char l [20] = "потаємна ніжність";

printf ("Довжина 1 рядка =% d \ n", strlen (k));

strcat (k, l);

puts (k);

}

В результаті виконання програми вийде: Довжина 1 рядка = 24. Є в дощі одкровення, потаємна ніжність.

У даному прикладі функція strlen (k) визначає довжину рядка k.

Функція strcat (k, l) приєднує до кінця рядки k рядок l.


1.12 Особливості програмування на мові Сі


1.12.1 Модулі. Багатомодульні програмування

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

  1. Стандартний процес трансляції складається з двох етапів: власне трансляції та редагування зв'язків.

  2. На першій стадії трансляції текстовий файл, що містить фрагмент програми перетвориться до об'єктному увазі.

  3. На другій стадії трансляції всі об'єктні модулі (у тому числі модулі, що містяться в стандартних та інших бібліотеках) об'єднуються в один виконуваний модуль. На цій стадії відбувається узгодження використовуваних зовнішніх змінних і зовнішніх функцій.

На перший погляд здається, що двоетапний процес трансляції ускладнює і уповільнює розробку програмного забезпечення. Однак, розбиваючи програму на модулі ми можемо перевести їх в об'єктний формат і далі приєднувати їх тільки на другому етапі трансляції, що, в кінцевому підсумку, прискорює процес трансляції. До речі, всі стандартні функції, якими Ви користуєтесь у своїх програмах міститися, в стандартних бібліотеках об'єктних модулів. Опис ж бібліотечних функцій міститься в H-файлах. Зауважимо, що при будь-якій кількості модулів один і тільки один буде містити функцію main. Цей модуль ми будемо називати головним.

Сучасні засоби трансляції дозволяють легко розробляти багатомодульні програми. Працюючи з Borland С ви можете або включити всі модулі до проекту (якщо Ви працюєте з інтегрованим середовищем) або вказати їх у командному файлі (якщо Ви працюєте) з строковим компілятором. При цьому на першому місці повинен стояти головний модуль. При цьому, якщо Ви вказали модуль з розширенням. Obj, то він буде приймати участь тільки в другій стадії трансляції, в іншому випадку він кожен раз буде перекомпілювати. Стандартні бібліотеки в проекті вказувати не треба - система автоматично підключає їх на другому етапі трансляції.

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

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

Наведемо приклад двухмодульной програми.

/ * Модуль 1, головний * /

# Include <stdio.h>

extern int min (int, int, int); / * знаходить мінімальне значення з 3 * /

extern int max (int, int, int); / * знаходить максімалное значення з 3 * /

void main ()

{

int a, b, c;

a = 2; b = 10; c = 14;

/ * Надрукувати добуток мінімального і максимального числа * /

printf ("% d \ n", max (a, b, c) * min (a, b, c)); / * відповідь 28 * /

}

/ * Модуль 2 * /

# Include <stdio.h>

extern int min (int, int, int); / / знаходить мінімальне значення з 3

extern int max (int, int, int); / / знаходить максімалное значення з 3

int max (int a1, int b1, int c1)

{

if (a1> b1)

{

if (c1> a1) return c1; else return a1;

}

else

{

if (b1> c1) return b1; else return c1;

}

}

int min (int a1, int b1, int c1)

{

if (a1 <b1)

{

if (c1 <a1) return c1; else return a1;

}

else

{

if (b1 <c1) return b1;

else return c1;

}

}

Коротко прокоментіруем наведену вище програму.

Програма складається з двох модулів. У головному модулі міститися виклики функцій, які містяться у другому модулі. Як видно з тексту програми при описі функцій ми використовуємо ключове слово extern. Нехай перша програма називається modul 1, а друга modul 1. Тоді після першого етапу трансляції на диску з'являться об'єктні модулі modul 1. Obj і modul 2. Obj. На другому етапі трансляції відбувається об'єднання цих модулів та на диску з'являється виконуваний модуль modul 1. Exe.


1.12.2 Моделі пам'яті

Звернемося тепер до однієї дуже важливої ​​проблеми, з якою рано чи пізно стикається будь-який програміст програмує на Сі в операційній системі MS DOS. Ця проблема називається - вибір моделі пам'яті. Вибір моделі пам'яті можна здійснити зазначивши відповідні опції в інтегрованому середовищі обробки або або вказавши відповідні параметри для строкового компілятора. Питання полягає в тому: що означає вибрана модель пам'яті.

Щоб розібратися в зазначеній проблемі перш за все слід звернутися до того як здійснюється адресація пам'яті на комп'ютерах IBM. Насамперед зазначимо, що мікропроцесор Intel може працювати в двох режимах реальному і захищеному, що відрізняються в тому числі і системою адресації. Операційна система MS DOS працює в реальному режимі (або в імітованих реальному режимі). Почнемо, тому, з адресації в реальному режимі.

Оскільки перші мікропроцесори Intel були 16-бітні то для того, щоб розширити обсяг пам'яті, що адресується, адреса комірки пам'яті формується з двох компонентів. Позначимо перший компоненту як seg і назвемо її сегментним адресою. Другу компоненту позначимо ofs і назвемо її зміщенням. Тоді фізичну адресу комірки може бути знайдений за формулою: seg * 16 + ofs. Оскільки розмір регістрів складає 16 біт, то маємо, що максимальний можливий адрес становить (2 ^ 16-1) * 16 + (2 ^ 16-1). Тобто обсяг охоплюваній пам'яті виявляється рівним приблизно 1 Мб.

Зауважимо, що при фіксованому seg зміщення дозволяє адресувати 64 Кб пам'яті. У результаті вся пам'ять розбивається на сегменти. Максимальний розмір сегмента становить 64 Кб. Адреса початку сегмента завжди кратний 16. Таку сегментну структуру доводиться враховувати і при написанні програми. Традиційно в програмі можна виділити три компоненти: код, дані, стік. Для кожної з цих компонент має бути виділено певну кількість сегментів.

Для сегментації сегментів в мікропроцесорі Intel існує 4 регістра званих сегментними: cs - регістр сегменту коду, ds - регістр сегмента даних, ss - регістр сегмента стека, es - додатковий сегментний регістр.

Раніше було введено поняття покажчика. До цих пір ми користувалися цим поняттям не замислюючись про їх типі. Цей тип встановлюється за умовчанням відповідно до моделі пам'яті (див. нижче). У Сі існує 3 типи покажчика: NEAR, FAR і HUGE.

Покажчик NEAR - відповідає зсуву в поточному сегменті. Довжина його 16 біт.

Покажчик FAR - 32-бітний покажчик, точніше пара SEG, OFS. Легко бачити, що один і той же фізичний адреса може бути представлений декількома парами: seg, ofs. Крім того порівняння та дії над покажчиками стосується тільки зсуву. Т.ч. два покажчики відносяться до однієї і тієї ж осередки пам'яті виявляються не рівними один одному.

Покажчик HUGE - 32-бітний покажчик. Відрізняється від FAR тим, що він нормалізований - з усіх пар seg, ofs обрана пара з мінімальним ofs. Такий вид покажчика називається нормалізованим.

Перейдемо тепер безпосередньо до розгляду моделей пам'яті, яких існує рівно 6.

Модель tiny (крихітна). Всі сегментні регістри (cs, ds, ss, es) вказують на одну адресу. Т.ч. у Вас для всього (коду, даних, стека) всього 64 Кб. пам'яті. Використовуються тільки покажчики типу near. Програми написані в цій моделі можуть бути перетворені до COM-увазі.

Модель small (мала). Програмний сегмент і сегмент даних починаються з різних адрес. Тобто для коду та для стека відводиться по 64 Кб. Сегмент стека починається з того ж адреси, що сегмент даних. Використовуються тільки покажчики near.

Модель medium (середня). Може мати кілька сегментів коду, але один сегмент даних. Іншими словами покажчики типу far визначені тільки для сегментів коду. Сегмент стека починається з адреси сегмента даних.

Модель compact (компактна). Може мати кілька сегментів даних (один для статичних даних), але один сегмент коду. Іншими словами покажчики типу far визначені для сегментів даних (і стека). Стек має свій власний сегмент.

Модель large (більша). Може мати кілька сегментів коду і даних. Для стека, як і в попередньому випадку, є свій сегмент. Використовується покажчик типу far. Для статичних даних відводиться один сегмент.

Модель huge (величезна). Збігається з попередньою, але знімається обмеження на кількість сегментів для статичних даних.

Попередній матеріал показує які покажчики використовуються за замовчуванням в тій чи іншій моделі пам'яті. Проте використовуючи модифікатори near, far і huge можна змінити тип покажчика задається за замовчуванням.

1.12.3 Програмування в DOS і Windows

До цих пір ми не акцентували Вашу увагу на те в якій операційній системі ми працюємо. Для початку програмування на Сі це не має великого значення. Однак тепер ми можемо сказати, що даний програмування в Windows почнеться тільки з Глави 4. У цьому параграфі ми поговоримо про принципові особливості програмування в середовищі MS DOS і Windows.

Значна частина часу в програмуванні йде на про-граммирования зовнішніх пристроїв. Причому під зовнішніми пристроями розуміється і робота з пам'яттю, файловою системою, дисплеєм, клавіатурою, мишею і т.д. Основною відмінністю операційної системи Windows від MS DOS є те, все управління всіма зовнішніми пристроями Windows бере на себе. Нижче на малюнку представлена ​​схема взаємодії додатку з зовнішніми пристроями в системах MS DOS і Windows

Беручи на себе взаємодію із зовнішніми пристроями Windows дозволяє створювати більш надійне і сумісне програмне забезпечення.

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

Ще однією особливістю програмування в середовищі Windows є присутність лише однієї моделі пам'яті. в Windows використовується так звана лінійна або плоска моделі пам'яті. Суть цієї моделі полягає в тому, що зміст усіх сегментних регістрів фіксується, а адресація здійснюється за допомогою 32-бітових регістрів. Така модель грунтується на так званій сторінкової адресації в захищеному режимі. Для програмування це дає значні переваги, які полягають в тому, що оскільки сегментом тепер є вся пам'ять, то знімаються всі обмеження на розмір коду, даних, стека і обсягу відведеного під локальні змінні.

До особливостей програмування в Windows ми ще повернемося в розділі 4, а поки що ознайомимося з тим, як можна безпосередньо використовувати системні виклики в програмах для операційної системи MS DOS.

Нижче наведена програма, яка для друку рядка використовує системний виклик (так зване 21-е переривання).

# Include <stdio.h>

# Include <dos.h>

void main ()

{

char * s = "Друк за допомогою системного виклику";

struct REGPACK r;

r. r _ ax = 0 x 0200; / * функція 2, 21-його переривання * /

r.r_ds = FP_SEG (s);

r.r_bx = FP_OFF ​​(s);

while (* (char *) MK_FP (r.r_ds, r.r_bx)! = 0)

{

r.r_dx =* (char *) MK_FP (r.r_ds, r.r_bx);

intr (0x21, & r);

r.r_bx + +;

}

}

Прокоментіруем програму. У програмі використовується функція INTR, що дозволяє здійснювати системні виклики операційної системи MS DOS. Ці системні виклики називаються перериваннями і мають свій номер. Найбільш часто використовується переривання має номер 21 (шістнадцяткові). У нашій програмі ми використовуємо функцію 2 цього переривання, яка дозволяє друкувати один символ, код якого поміщений в регістр DX. Для роботи з регістрами використовується зумовлена ​​структура REGPACK. Особливо звертаємо увагу на функції FP _ SEG, FP _ OFF, MK _ FP. FP _ SEG і FP _ OFF дозволяють отримувати за вказівником сегментний адресу і зсув. Функція MK _ FP навпаки формує покажчик виходячи з сегментного адреси і зсуву. Нагадуємо, що на кінці рядка стоїть символ з кодом 0, на чому і грунтується вихід з циклу.


1.12.4 Використання мови асемблера в програмах на Сі

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

При роботі з мовою Сі можна використовувати як вбудований асемблер, так і мова асемблера в зовнішніх модулях.

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

Основою вбудованого асемблера є ключове слово asm, після якого може йти або команда на асемблері або блок команд, укладених у фігурні дужки. Нижче наводиться простий приклад.

# Include <stdio.h>

void main ()

{

char * s = "Друк з ассемблерного блоку";

/ * Далі йдуть команди на мові асемблера * /

asm lds bx, s

asm mov ah, 2

l1:

asm mov dl, [bx]

asm cmp dl, 0

asm jz l2

asm int 21h

asm inc bx

asm jmp short l1

l2:

}

Ми навмисно взяли програму з попереднього параграфа і переписали її на мові асемблера. Прокоментіруем її не вдаючись в особливості виконання ассемблерних команд. Для виведення символу на екран його поміщають в регістр dl і викликається функція 2 21-його переривання. На черговій символ рядка вказує регістр bx. Процес виведення символів закінчується коли в регістр dl потрапляє код 0 (кінець рядка).

Перейдемо тепер до випадку, коли до програми на мові Сі підключається модуль, написаний на мові асемблера. Підключення здійснюється на другому етапі трансляції (див. пункт 1.12.1). Нижче наведені модуль на мові асемблера і модуль на мові Сі. Причому перший містить процедуру, що спричинюється з другого.

; Модуль на мові асемблера

CODE SEGMENT

ASSUME CS: CODE

PUBLIC _PRI_STR; процедура буде викликатися з іншого модуля

_PRI_STR PROC FAR

PUSH BP

MOV BP, SP

; Отримуємо адресу початку рядка

LDS BX, [BP +6]

; Номер викликається функції

MOV AH, 2

CONT:

; Черговий символ помістити в регістр dl

MOV DL, DS: [BX]

; Перевіряємо - не кінець чи рядки

CMP DL, 0

JZ _en

; Виклик 21-його переривання

INT 21H

; Переходимо до наступного символу

inc bx

; На початок циклу

JMP SHORT CONT

_en:

POP BP

; Повертаємося в викликає модуль

RET

_PRI_STR ENDP

CODE ENDS

END

/ * Модуль на мові Сі * /

# Include <stdio. H>

extern void far PRI_STR (char *);

void main ()

{

char * st = "Друк з ассемблерного модуля.";

PRI_STR (st);

}

Коментар.

Перш за все, відзначимо, що модулі повинні бути узгоджені за моделлю пам'яті (див. 1.12.2). Ми припускаємо, що модуль на мові Сі компілюється в моделі Large. У модулі на мові асемблера узгодження по моделі полягає в тому, що викликається з іншого модуля процедура має тип Far. Обидва модулі можна просто включити в проект (модуль на мові Сі повинен бути першим, а модуль на мові асемблера повинен мати розширення asm) при цьому для ассемблерного модуля при трансляції автоматично буде викликатися транслятор tasm. Exe. Асемблерний модуль може бути отранслірован і окремо, тоді в проекті він повинен мати розширення obj.

Другий тип узгодження - узгодження імен. Ми повинні врахувати:

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

2. При трансляції до імен Сі попереду додається символ підкреслення, що слід врахувати в ассемблерной модулі.

Наша програма виконує ті ж дії, що і попередня програма цього параграфа, тобто друкує рядок. Друк здійснюється процедурою PRI _ STR, якій передається як параметр вказівник на цей рядок. Звертаємо вашу увагу на те, що викликається процедура в ассмблерном модулі оголошена як PUBLIC, тобто її ім'я буде поміщено в об'єктний модуль. У свою чергу в модулі на мові Сі ця процедура оголошена як extern.

На цьому ми закінчуємо розгляд аспектів пов'язаних з зиком асемблера. Докладні про мову асемблера та його використання в мовах високого рівня можна знайти у книзі [], написаної одним з авторів цих.

Глава 2. Приклади використання мови Сі


2.1 Сортування


Практично кожен алгоритм сортування можна розбити на три частини:

- Порівняння, що визначає впорядкованість пари елементів;

- Перестановку, який міняє місцями пару елементів;

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

М е т о д п у з и р ь к а (обмінна сортуванням з вибором).

Ідея цього методу відображена в його назві. Найлегші елементи масиву "спливають" вгору, самі "важкі" - тонуть. Алгоритмічно це можна. Реалізується так - будемо переглядати весь масив "знизу вверх" і змінювати стоять поруч елементи в тому випадку, якщо "нижній" елемент менше, ніж "верхній". Таким чином, ми виштовхніть наверх самий "легкий" елемент всього масиву. Тепер повторимо всю операцію для решти несортованими N-1 елементів (тобто для тих, які лежать "нижче" першого).

# Include <stdio.h>

# Define swap (a, b) {int tmp; tmp = a; a = b; b = tmp;}

main ()

{

int a [10], dim = 10;

int i, j;

for (i = 0; i <dim; i + +)

{

printf ("Елемент \ n");

scanf ("% d", & a [i]);

}

printf ("Було \ n");

for (i = 0; i <dim; i + +)

printf ("% d \ n", a [i]);

/ * Прохід масиву "вниз", починаючи з нульового елемента * /

for (i = 0; i <dim; i + +)

/ * Прохід масиву "вгору", починаючи з останнього до i-го елемента * /

for (j = dim-1; j> i; j -)

/ * Порівняння двох сусідніх елементів і їх обмін * /

if (a [j-1]> a [j]) swap (a [j-1], a [j]);

printf ("Стало \ n");

for (i = 0; i <dim; i + +)

printf ("% d \ n", a [i]);

}

З о р т і р о в к а в и б о р о м.

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

# Include <stdio.h>

# Define swap (a, b) {int tmp; tmp = a; a = b; b = tmp;}

main ()

{

int a [10], dim = 10;

int i, j, k;

for (i = 0; i <dim; i + +)

{

printf ("Елемент \ n");

scanf ("% d", & a [i]);

}

printf ("Було \ n");

for (i = 0; i <dim; i + +)

printf ("% d \ n", a [i]);

/ * Прохід масиву, починаючи з 0-го до передостаннього елемента * /

for (i = 0; i <dim-1; i + +)

{

/ * Прохід масиву, починаючи з (i +1)-го до останнього елемента * /

for (k = i, j = i +1; j <dim; j + +)

if (a [j] <a [k]) k = j; / * Пошук найменшого k-го ел - та * / swap (a [k], a [i]); / * Переміщення найменшого "вгору" * /

}

printf ("Стало \ n");

for (i = 0; i <dim; i + +)

printf ("% d \ n", a [i]);

}

М е т о д Ш е л л а.

Цей метод запропонував Donald Lewis Shell в 1959 р. Основна ідея алгоритму полягає в тому, щоб спочатку усунути масовий безлад в масиві, порівнюючи далеко стоять один від одного елементи. Як видно, інтервал між порівнюваними елементами (gap) поступово зменшується до одиниці. Це означає, що на пізніх стадіях сортування зводиться просто до перестановок сусідніх елементів (якщо, звичайно, такі перестановки є необхідними).

# Include <stdio.h>

# Define swap (a, b) {int tmp; tmp = a; a = b; b = tmp;}

main ()

{

int a [10], dim = 10;

int i, j, gap;

for (i = 0; i <dim; i + +)

{

printf ("Елемент \ n");

scanf ("% d", & a [i]);

}

printf ("Було \ n");

for (i = 0; i <dim; i + +)

printf ("% d \ n", a [i]);

for (gap = dim / 2; gap> 0; gap / = 2) / * Вибір інтервалу * /

for (i = gap; i <dim; i + +) / * Прохід масиву * /

/ * Порівняння пар, віддалених на gap один від одного * /

for (j = i-gap; j> = 0 & & a [j]> a [j + gap]; j -= gap) swap (a [j], a [j + gap]);

printf ("Стало \ n");

for (i = 0; i <dim; i + +)

printf ("% d \ n", a [i]);

}


2.2 Рекурсивні алгоритми


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

Розглянемо більш детально організацію і роботу рекурсивних підпрограм.

Рекурсію можна використовувати для обчислення факторіала n!. Щоб знайти n!, потрібно визначити (n-1)!. А для цього необхідний (n-2)! і так далі.

# Include <conio.h>

# Include <stdio.h>

int z;

int Fact (int n)

{

if (n == 1) return 1;

else return Fact (n - 1) * n;}

main ()

{Int n;

printf ("Кількість? \ n");

scanf ("% d", & n);

z = Fact (n); printf ("% d", z);

}


2.3 Завдання Ханойські вежі


Легенда говорить, - в одному з храмів Південно-Східної Азії знаходяться три вертикальних стрижня, на які нанизані 64 золотих кільця різного діаметру. Колись бог Вішну помістив всі 64 кільця на перший стрижень так, що діаметр кілець знизу вгору зменшувався, і повелів жерцям перемістити вежу з кілець з першого стрижня на третій, дотримуючись наступне правило: на кожному кроці можна перенести саме верхнє кільце з одного зі стрижнів наверх іншого стрижня за умови, що на кожному зі стрижнів кільця будуть зберігати форму вежі (тобто їх діаметр знизу вгору зменшується). З тих пір багато тисяч років жерці вдень і вночі перекладають кільця. Легенда свідчить, що коли всі кільця опиняться на третьому стрижні, настане кінець світу.

Програма:

# Include <stdio.h>

# Include <dos.h> / * sleep () * /

# Define MAX_NRINGS 64 / * Максимальне число кілець * /

int st [4] [MAX_NRINGS]; / * 1,2,3 - стрижні * /

int nr [4]; / * Число кілець на стрижнях * /

int nmoves; / * Число переміщень * /

/ * ---------------------------------------------- * /

/ * Друк поточного розташування кілець на стрижнях * /

/ * ---------------------------------------------- * /

void print_st (void)

{

int i, j;

for (i = 1; i <= 3; i + +) {

printf ("\ n |");

for (j = 0; j <nr [i]; j + +) printf ("% d", st [i] [j]);

}

printf ("\ n");

}

/ * ------------------------------------ * /

/ * Установка початкового положення кілець * /

/ * ------------------------------------ * /

void init (int nrings)

{

for (nr [1] = 0; nrings> 0; nr [1] + +, nrings -)

st [1] [nr [1]] = nrings;

* Нанизали кільця на 1-й стрижень * /

nr [2] = nr [3] = 0;

/ * Два інших стрижня порожні * /

nmoves = 0;

print_st ();

}

/ * ----------------------------- * /

/ * Функція переносить одне кільце * /

/ * Із стержня n1 на стрижень n2 * /

/ * ----------------------------- * /

void move1 (int n1, int n2)

{

st [n2] [nr [n2] + +] = st [n1] [- nr [n1]];

sleep (1); / * Пауза в 1 секунду * /

print_st (); / * Друк поточної позиції * /

nmoves + +;

}

/ * ------------------------------------------------ - * /

/ * Функція hanoi переміщує верхні nrings кілець * /

/ * Із стержня i1 на стрижень i3, використовуючи стрижень * /

/ * I2 в якості проміжного. 1 <= i1, i2, i3 <= 3. * /

/ * ------------------------------------------------ - * /

void hanoi (int nrings, int i1, int i2, int i3)

{

if (nrings == 1)

move1 (i1, i3);

else {

hanoi (nrings-1, i1, i3, i2);

move1 (i1, i3);

hanoi (nrings-1, i2, i1, i3);

}

}

main ()

{

int nrings;

printf ("Число кілець: "); scanf ("% d ", & nrings); init (nrings);

hanoi (nrings, 1, 2, 3);

printf ("Перенесення кілець завершено. \ n ");

printf ("Число переміщень -% d. \ n", nmoves); return (0);

}

У прложеніі N 1 показано рішення деяких завдання на мові С.

Глава 3. Основи С + +


3.1 Відмінності С + + від С


1. У С + + ключове слово void не обов'язково (еквівалентно int m (); і int m (void)).

2. В С + + всі функції повинні мати прототипи.

3.Якщо в С + + функція повертає тип, відмінний від void, то оператор return повинен містити значення типу.

4.У С + + можна вибирати місце для оголошення локальних змінних не тільки на початку блоку.

5.В С + + введення-виведення може здійснюватися не тільки за допомогою функцій, але і за допомогою операцій.


3.2 Об'єктно-орієнтоване програмування в С + +


Розвиток засобів обчислювальної техніки вимагало нових методик програмування:

- Програмування невеликих програм на базі перемикачів;

- Програмування на асемблері;

- Програмування на мовах високого рівня (Фортран);

- Програмування на мовах структурного програмування (Паскаль, Сі);

- Об'єктно-орієнтоване програмування (ООП).

ООР дозволяє розбити задачу на ряд самостійних пов'язаних між собою підзадач, що містять моделі об'єктів реального світу.

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

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

Об'єкт - це представник певного класу.

ООП використовує механізми інкапсуляції, поліморфізму і наслідування.

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

Дані, доступні для використання всередині об'єкта - private, дані доступні ззовні - public.

Загалом, як об'єкт можна розглядати як змінну, певну програмістом.

Поліморфізм дозволяє одне ім'я функції використовувати для вирішення різних завдань (загальних для класу дій).

Залежно від даних виконуються ті чи інші дії.

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


3.2.1 Класи

Клас використовується для створення об'єктів. Основна форма має вигляд:

class ім'я класу

{

закриті функції та змінні

public:

відкриті функції, функції-члени і змінні

}

список об'єктів; / / не є обов'язковим

Закриті функції та змінні - члени (members) доступні тільки для інших членів цього класу.

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

Функції, оголошені усередині опису класу називаються функціями членами (member functions).

Для визначення функцій-членів використовується форма:

тип ім'я класу:: ім'я функції-члена (параметри)

{

тіло функції

}

Два двокрапки після імені класу називаються операцією розширення області видимості (scope resolution operator).

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

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

Приклад.

# Include <iostream.h>

class class1 {/ / об'влен сласс class1

int a; / / доступна для функцій членів class1

public:

int kwadrat (int b); / / функція член класу class1

};

int class1:: kwadrat (int b) / / визначення функції kwadrat ()

{

a = b * b;

return a;

}

main ()

{

class1 c; / / створюється об'єкт з типу class1

cout <<"\ n" <<c.kwadrat (3) <<"\ n"; / / обчислення і виведення квадрата трьох

return 0;

}


3.2.2 Перевантаження функцій

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

Приклад.

# Include <iostream.h>

void k (int a); / / прототип перший функції

void k (int a, float b); / / прототип другої функції

void k (int a) / / опис першої функції

{

cout <<a <<"\ n";

}

void k (int a, float b) / / опис другої функції

{

cout <<a <<"\ n" <<b <<"\ n";

}

main ()

{

k (4); / / виклик першої функції

k (5, 10.2); / / виклик другої функції

return 0;

}


3.2.3 Конструктори

Для автоматичної ініціалізації створюваних об'єктів в С + + використовується функція - конструктор (constructor function), яка включається в опис класу.

Функція конструктор має теж ім'я, що й клас і не повертає жодного значення.

Приклад:

# Include <iostream.h>

/ / Оголошення класу class1

class class1 {

int a;

public:

class1 (); / / Конструктор

void kwadrat ();

};

/ / Ініціалізація а конструктором при створенні об'єкта pr

class1:: class1 ()

{

a = 100;

}

/ / Функція зведення в квадрат і друку

void class1:: kwadrat ()

{

cout <<a * a;

}

main ()

{

class1 pr; / / Створення об'єкта pr

pr.kwadrat (); / / Виклик функції kwadrat

return 0;

}

Як видно з прикладу конструктор викликається при створенні об'єкта pr.


3.2.4 Деструктори

Функція деструктор (destructor) викликається при видаленні об'єкта для звільнення ресурсів (пам'яті і т.д.). Вона також включається до оголошення класу. Перед описом деструктора ставиться значок ~.

Приклад.

# Include <iostream.h>

/ / Оголошення класу class1

class class1 {

int a;

public:

class1 (); / / Конструктор

~ Class1 (); / / Деструктор

void kwadrat ();

};

/ / Ініціалізація а конструктором при створенні об'єкта pr

class1:: class1 ()

{

a = 100;

}

/ / Звільнення ресурсів деструкцією

class1:: ~ class1 ()

{

cout <<"Звільнення \ n";

}

/ / Функція зведення в квадрат і друку

void class1:: kwadrat ()

{

cout <<a * a <<"\ n";

}


ain ()

class1 pr; / / Створення об'єкта pr

pr.kwadrat (); / / Виклик функції kwadrat

return 0;

}

Деструктор викликається при видаленні об'єкта або виходу з програми.


3.2.5 Конструктори з параметрами

Конструктору можна передати параметри. Для цього потрібно додати необхідні параметри в оголошення і визначення конструктора. Потім при оголошенні об'єкта параметри задаються в якості аргументу.

Приклад:

# Include <iostream.h>

class myclass {

int a;

public:

myclass (int x); / / конструктор

void show ();

};

myclass:: myclass (int x)

{

cout <<"У конструкторі \ n";

a = x;

}

void myclass:: show ()

{

cout <<a <<"\ n";

}

main ()

{

myclass ob (4);

ob.show ();

return 0;

}

Конструктор myclass має один параметр. Значення, що передається в myclass () використовується для ініціалізації а. Аргумент 4 передається в ob (4) в якості аргументу. Деструктор на відміну від конструктора параметрів не має.

У даному прикладі конструктору ми передавали константи, але так само можна передавати змінні:

Приклад:

include <iostream.h>

class myclass {

int i, j;

public:

myclass (int a, int b);

void show ();

};

myclass:: myclass (int a, int b)

{

i = a;

j = b;

}

void myclass:: show ()

{

cout <<i <<'' <<j <<"\ n";

}

main ()

{

int x, y;

cout <<"Введіть два цілих:";

cin>> x>> y;

/ / Використання змінних для створення ob

myclass ob (x, y);

ob.show ();

return 0;

}

У програмі розглянуто важлива властивість об'єктів. Вони можуть створюватися у міру необхідності.


3.2.6 Введення в спадкування

Спадкування - це механізм за допомогою якого один клас (похідний) може успадковувати властивості іншого класу (базового).

Базовий клас визначає всі якості, які є загальними для всіх прпоізводних класів.

Приклад:

/ / Базовий клас

class B {

int i;

public:

void set_i (int n);

int get_i ();

};

/ / Похідний клас D

class D: public B {

int j;

public:

void set_j (int n);

int mul ();

};

Після імені класу D варто двокрапка, за яким стоїть ключове слово public та ім'я класу B. Це означає, що клас D ​​буде наслідувати всі компоненти класу B. Саме ключове слово public інформує компілятор про те, що оскільки B буде успадковуватися, то всі відкриті елементи базового класу будуть відкритими елементами похідного класу. Проте всі закриті елементи базового класу залишаються закритими.

Приклад:

/ / Простий приклад наслідування.

# Include <iostream.h>

/ / Завдання базового класу

class base {

int i;

public:

void set_i (int n);

int get_i ();

};

/ / Завдання похідного класу

class derived: public base {

int j;

public:

void set_j (int n);

int mul ();

};

/ / Встановлення значення i в базовому класі

void base:: set_i (int n)

{

i = n;

}

/ / Повернення значення i в базовому класі

int base:: get_i ()

{

return i;

}

/ / Встановлення значення j у похідному класі

void derived:: set_j (int n)

{

j = n;

}

/ / Повернення значення i з base і, одночасно, j з derived

int derived:: mul ()

{

/ / Похідний клас може викликати функції-члени базового класу

return j * get_i ();

}

main ()

{

derived ob;

ob.set_i (10); / / завантаження i в base

ob.set_j (4); / / завантаження j в derived

cout <<ob.mul (); / / вивід числа 40

return 0;

}

Важливо! При визначенні mul () викликається функція get_i () - базового класу B, а не похідного D, що вказує на те, що відкриті члени базового класу стають відкритими членами похідного. Але у функції mul () замість прямого доступу до i, необхідно викликати get_i (), тому що закриті члени базового класу (i) залишаються закритими для похідних класів.


3.2.7 Віртуальні функції

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

# Include <stdio.h>

class base {

public:

int i;

base (int x); / / конструктор

void func ()

{

printf ("Базова функція% d", i);

return;

};

};

/ / Текст конструктора

base:: base (int x)

{

i = x;

return;

};

class der1: public base {

public:

der1 (int x): base (x) {}; / / конструктор

void func ()

{

printf ("Функція з похідного класу% d", i * i);

return;

}

};

main ()

{

base * pc; / / покажчик на базовий клас

base ob (2); / / створити екземпляр об'єкта базового класу

der1 ob1 (2); / / створити екземпляр об'єкта похідного класу

pc = &ob; / / покажчик на об'єкт базового класу

pc-> func (); / / виклик функції базового класу

pc = &ob1; / / покажчик на об'єкт похідного класу

pc-> func (); / / спроба виклику функції похідного класу

return 0;

}

На перший погляд, здається, що в перврм випадку буде викликатися функція базового класу, а в другому функція похідного. Однак при перевірці Ви легко переконаєтеся, що і в тому і в іншому випадку буде викликана функція функція базового класу. У чому тут справа? Справа в тому, що компілятору важко зрозуміти, яку реально функцію ми маємо на увазі і він на стадії компілювання підставляє у всіх тих випадках, де зустрічається ім'я func () адреса функції базового класу. Такий процес установки адрес називається "раннім зв'язуванням". Іноді вживається термін "статичне зв'язування". Якщо ж ми хочемо, щоб у другому випадку, тобто коли покажчик pc вказував на похідний клас викликалася функція цього класу, її ще в базовому класі слід вказати як віртуальну. У нашому випадку замість рядка void func () слід написати virtual void func (). Після цього наш приклад буде працювати як треба.

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

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

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

# Include <stdio.h>

class base {

public:

int i;

base (int x); / / конструктор

virtual void func ()

{

printf ("Базова функція% d \ n ", i);

return;

};

};

/ / Текст конструктора

base:: base (int x)

{

i = x;

return;

};

class der1: public base {

public:

der1 (int x): base (x) {}; / / конструктор

void func ()

{

printf ("Функція з похідного класу% d \ n", i * i);

return;

}

};

class der2: public base {

public:

der2 (int x): base (x) {}; / / конструктор

};

main ()

{

base * pc; / / покажчик на базовий клас

base ob (2); / / створити екземпляр об'єкта базового класу

der1 ob1 (2); / / створити екземпляр об'єкта похідного класу 1

der2 ob2 (2); / / створити екземпляр об'єкта похідного класу 2

pc = &ob; / / покажчик на об'єкт базового класу

pc-> func (); / / виклик функції базового класу

pc = &ob1; / / покажчик на об'єкт похідного класу 1

pc-> func (); / / спроба виклику функції похідного класу

pc = &ob2; / / покажчик на об'єкт похідного класу 2

pc-> func (); / / спроба виклику функції похідного класу

return 0;

}

Як бачите, ми ввели ще один похідний клас. У ньому функція func () не визначена. У цьому випадку буде викликатися функція класу батька. Тобто з'явиться рядок: Базова функція 2. Як бачите принцип дуже простий: якщо Ви хочете, щоб викликалася функція батьківського класу, не визначайте її в похідному. Ще одне питання може виникнути у зв'язку з даним прикладом: як бути, якщо ми хочемо, щоб для класу об'єктів der 2 викликалася функція класу der 1. Рішення дуже просто - зробіть клас der 2 спадкоємцем не класу base, а класу der 1.

І останнє. Як ми бачили, в похідних класах функція, визначена в базовому класі як віртуальна може визначатися, а може і ні. Якщо Ви хочете, щоб в усіх похідних класах обов'язково була визначена віртуальна функція, то в базовому класі її треба визначити наступним чином:

virtual void func () = 0;

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


3.2.8 Покажчики на об'єкти

Доступ до члена об'єкта можливий не тільки через крапку (.). Можливий доступ і через вказівник на цей об'єкт. У цьому випадку застосовують стрілку (->).

Приклад:

# Include <iostream.h>

class myclass {

int a;

public:

myclass (int x); / / конструктор

int get ();

};

myclass:: myclass (int x)

{

a = x;

}

int myclass:: get ()

{

return a;

}

main ()

{

myclass ob (120); / / створення об'єкта

myclass * p; / / створення покажчика на об'єкт

p = &ob; / / передача адреси ob в p

cout <<"Значення, що отримується при використанні об'єкта:" <<ob.get ();

cout <<"\ n";

cout <<"Значення, що отримується при використанні покажчика:" <<p-> get ();

return 0;

}

У програмі оголошення myclass * p створює покажчик на об'єкт myclass (а не створює об'єкт!).

Для передачі адреси ob в p використовується вираз p = & ob.

Для отримання доступу до об'єкта через покажчик використовується вираз p-> get ();.

Глава 4. Основи програмування на мові C + + Builder


4.1 Характеристика С + + Builder


С + + Builder - це подальший розвиток мови Сі, засноване на системі швидкої розробки додатків RAD (Rapid Application Development).

У C + + Builder інтегрована Палітра компонент, розділена картотечними вкладами на кілька функціональних сторінок. Функціональні можливості компонент зі сторінок можна досить просто модифікувати, а також розробляти власні компоненти.

Система містить бібліотеку з понад 100 візуальних компонент, які перетягуються мишею на форму і відразу стають елементами управління прототипу програми.

Після розміщення компонентів на формі, Інспектор об'єктів допоможе встановлювати їх властивості і наказувати подіям коди обробки. Проект буде будуватися поступово, на тлі вироблених змін у властивостях, події та функціях використовуваних елементів.

C + + Builder підтримує основні принципи об'єктно-орієнтованого програмування - інкапсуляцію, поліморфізм і множинне спадкування, а також нововведені специфікації та ключові слова в стандарті мови С + +.

C + + Builder підтримує зв'язок з базами даних: dBASE, Paradox, Sybase, Oracle, InterBase, Informix, Exel, Access, FoxPro. Механізм BDE (Borland Database Engine) надає обслуговування зв'язків з базами даних простоту і прозорість. Провідник Database Explorer дозволяє зображати зв'язки і об'єкти баз даних графічно.

Інтегроване середовище розробки об'єднує Редактор форм, Інспектор об'єктів, Палітру компонент, Адміністратор проекту, інтегровані Редактор коду і Відладчик - інструменти швидкої розробки програмних додатків, що забезпечують повний контроль над кодом і ресурсами.

Професійні засоби мови С + + інтегровані в візуальне середовище розробки. C + + Builder надає швидкодіючий компілятор з мови Borland С + +, інкрементальний завантажувач і засоби налагодження.

Конструювання за способом «drag - and - drop» дозволяє створювати додаток простим перетягуванням захоплених мишею візуальних компонент з палітри на форму додатку. Інспектор об'єктів надає можливість оперувати з властивостями і подіями компонент, автоматично створюючи заготовки функцій обробки подій, які наповнюються кодом і редагуються в процесі розробки.

Механізми двонаправленої розробки (two - way - tools) забезпечує контроль за кодом за допомогою гнучкого, інтегрованого та синхронізованого взаємодії між інструментами візуального програмування і Редактором коду.

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

Між програмними продуктами С + + Builder і Borland C + + існує повна і взаємна функціональна сумісність.

Всі компоненти, форми і модулі даних, мови Delphi, можуть бути повторно використані у додатках C + + Builder без яких би то не було змін.

C + + і Delphi рівноправні - майже все, що написано в Delphi, можна використовувати в C + + Builder, і навпаки.

C + + Builder не робить різниці між тим, які програмні модулі ви додаєте до проекту свого застосування - написані вони на C + + (файли з розширенням CPP) або на Delphi (файли з розширенням PAS). Компілятор вільно приймає такі кодові конструкції моделей Delphi 3.0: компоненти, форми, об'єкти, константи, прості методи і функції - всі перераховані коди можна прямо підставляти у свої проектні файли. Технологія візуального наслідування форм дає можливість модифікувати форми Delphi в середовищі C + + Builder без яких би то не було проблем.


4.2 Компоненти VCL. Властивості, події, методи


Компоненти VCL - це будівельні цеглини, з яких розробляється інтерфейс програми з користувачем. VCL це об'єкт, який можна «перетягнути» з вкладок Палітри компонентів на форму додатку. Помістивши компоненту на форму, можна маніпулювати її властивостями (Редактором форм) і кодом (Редактором коду).

Властивості.



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

У інспекторі об'єктів для кожної компоненти є дві закладки Properties (властивості) і Events (події).

Багато властивостей є загальними для різних компонент, але деякі властивості є тільки в окремих компонент.

Деякі властивості компонент встановлюються числовими значеннями, наприклад Height (висота), деякі забезпечені вікном, що дозволяє вибрати варіант, наприклад Cursor (курсор).

У деяких компонент є властивості, забезпечені спливаючими меню і редакторами, призначеними для внесення змін.

Також деякі властивості залежать від установки інших властивостей, наприклад Hint (підказка), з'являється, якщо властивість ShowHint має значення True.

Події.

Компоненти C + + Builder пов'язані з набором подій або асоційованих з ними обробників подій.


Для створення обробника подій потрібно двічі клацнути мишею правіше події і ввести потрібний код.

Методи.

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

Щоб переглянути методи, доступні для компонента, необхідно клацнути на цій компоненті і натиснути клавішу F 1, далі клацнути на Methods та отримати список доступних методів.

Наприклад, для компоненту Button метод Hide () робить кнопку невидимою:

Button1-> Hide ();

На відміну від властивостей методи не видно у вікні інспектора об'єктів.


4.2.1 Типи компонент

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

Стандартні компоненти VCL інкапсулюють поведінка типових елементів управління операційної системи Windows, як TButton, TL i stbox і TEdit. В основному вони розташовані на вкладках Standard і Win95 Палітри компонентів.

На відміну від стандартних компонент, оригінальні компоненти являють собою елементи управління, у яких немає ні методу для власного відображення, ні заздалегідь певної поведінки (Tpanel, TstringGrid та ін.)

Графічні компоненти являють собою видимі елементи управління, які не можуть прийняти фокус введення, тому що не є віконними (TI mage, Tshape та ін.)

Невидимі компоненти не з'являються на формі у вигляді будь-яких елементів управління. Поведінка невидимих ​​компонентів визначається на етапі проектування, шляхом інкапсуляції потрібних властивостей об'єкта (TOpenDialog, Ttimer та ін.)


4.2.2 Ієрархія класів VCL

Розташована нижче схема показує ключові класи в ієрархічній структурі, від яких проведені всі компоненти VCL.


TObject -> ... -> TComponent -> TGraphicControl -> ...

|

| -> TWinControl -> ...


TObject є базовим класом для всіх породжуваних класів, а TCompone n t є базовим класом для всіх породжуваних компонент.

Невидимі компоненти вироблені від класу TComponent. Основні графічні компоненти - від класу TGraphlcControl.

Компоненти стандартного управління зроблені безпосередньо від класу TWinControl, а оригінальні компоненти - посередньо від класу TCustornControl, випливає зі TWinControl. Нижче наведена схема, яка продовжує ієрархічну структурну схему компонентних класів VCL.


TGraphicControl TWinControl

* Tbevel * TButtonControl

* TCustomLabel o Tbutton

  • TDBText + TBitBtn

  • Tlabel o TCustomCheckBox

* Timage + TCheckBox

* TPaintBox + TDBCheckBox

* TShape o TRadioButton

* TSpeedButton * TCustomComboBox

  • TComboButton o TComboBox

  • TNavButton o TDBComboBox

  • TDriveComboBox

  • TFilterComboBox

* TCustomControl

  • TCustomGrid

+ TCunstomDBGrid

+ TDBGrid

+ TDBLookupList

+ TpopupGrid

+ TCustomOutline

+ TOutline

+ TDrawGrid

+ TStringGrid

  • TCunstomGroupBox

+ TCunstomRadioGroup

+ TDBRadioGroup

+ TRadioGroup

+ TGroupBox

  • TCunstomPanel

+ TDBNavigator

+ TPanel

  • TDBImage

  • TDBLookupControl

+ TDBLookupComboBox

+ TDBLookupListBox

+ TPopupDataList

  • THeader

  • THintWindow

  • TMediaPlayer

  • TNotebook

  • TOleContainer

  • TPage

  • Tscroller

  • TTabSet

* TCustomEdit

  • TCustomMaskEdit

+ TDBEdit

+ TInplaceEdit

+ TMaskEdit

  • TCustomMemo

+ TCustomRichEdit

+ TRichEdit

+ TDBMemo

+ TMemo

  • TDBLookupCombo

  • TEdit

* TCustomHotKey

  • THotKey

* TCustomListBox

  • TDBListBox

  • TDirectoryListBox

  • TFileListBox

  • TListBox

* TCustomListView

o TListView

* TCustomTabControl

  • TPageControl

  • TTabbedNotebook

  • TTabControl

* TCustomTreeView

  • TTreeView

* TCustomUpDown

  • TUpDown

* TDBCtrlGrid

* TDBCtrlPanel

* THeaderControl

* TOleControl

* TProgressBar

* TScrollBar

* TScrollingWinControl

  • TForm

+ TDesignWindow

+ TInputRedDialog

+ TLoginDialog

+ TPasswordDialog

  • TScrollBox

* TStatusBar

* TTabPage

* TTabSheet

* TTrackBar


4.3 Структури файлів в C + + Builder


Для кожного додатка C + + Builder створюється один файл проекту, один make-файл один файл модуля і один файл ресурсів.

Спочатку файлу проекту присвоюється за замовчуванням ім'я Project 1. Cpp Якщо в процесі розробки програми додаються форми і модулі C + + Builder оновлює файл проекту.

Make-файл (за замовчуванням Project 1. Mak) - це текстовий файл, що містить макроси, директиви та інструкції щодо збирання і складанні проекту.

Модулі є основою створення бібліотек та додатків в C + + Builder. Модуль містить вихідний текст на мові C + + і спочатку представляє собою файл з розширенням Unit 1. Cpp.

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

Форма є одним з найважливіших елементів програми C + + Builder. Процес редагування форми відбувається при додаванні до форми компонентів, зміну їх властивостей, створення обробників подій (за замовчуванням файл форми або файл ресурсів має ім'я Unit 1. Dfm).

Коли до проекту додається нова форма, створюються 3 окремих файлу:

файл модуля (. Срр) - містить вихідний код, пов'язаний з формою;

h-файл (. H) - містить опис класу форми, тобто опис утримуються на формі компонентів і обробників подій;

файл форми (. Dfm) - двійковий файл, що містить відомості про доступні в інспекторі об'єктів властивості компонентів, які у формі.

У процесі трансляції створюються додаткові файли з розширеннями ilc, ild, ilf, ils, obj, які можна видалити.


4.4 Візуальні компоненти (VCL)


VCL в C + + Builder знаходяться на декількох сторінках.

Сторінка Standard складається з наступних візуальних компонент.



1.Компонент MainMenu дозволяє створювати лінійку меню проектованої форми і меню, що випадає (компонент Невізуальний).

2.Компонент PopupMenu дозволяє створювати спливаюче меню при натисненні правої кнопки миші (компонент Невізуальний).

3.Компонент Label використовується для створення написів.

4.Компонент Edit використовується для вводу або відображення однорядкових текстів.

5.Компонент Memo використовується для вводу або відображення багаторядкових текстів.

6.Компонент Button використовується для створення кнопок, якої можна вибирати ті чи інші команди.

7.Компонент Checkbox дозволяє вибирати або вимикати ті або інші опції.

8.Компонент RadioButton пропонує набір альтернатив з яких вибирається одна.

9.Компонент ListBox представляє стандартне вікно списку, що дозволяє вибирати ті чи інші пункти зі списку.

10.Компонент ComboBox об'єднує функції ListBox і Edit. Він дозволяє ввести текст або вибрати зі списку.

11.Компонент ScrollBar-це стандартна лінійка прокручування.

12.Компонент GroupBox об'єднує групу пов'язаних органів управління (контрольні індикатори, радіокнопки).

13.Компонент RadioGroup-комбінація GroupBox з набором RadioButton. Він дозволяє створювати групи радікнопок.

14.Компонент Panel іспорльзуется для групування органів управління.

Сторінка Win 95 включає наступні компоненти:



- TabControl - використовується для створення закладок, які можна вибирати;

- PageControl - створює сторінки, керовані закладками;

- TreeView - дозволяє переглядати ієрархічні структури даних;

- ListView - відображає списки в колонках;

- ImageList - дозволяє працювати зі списками зображень (Невізуальний компонент);

- Header - створює складові переміщувані заголовки;

- Richedit - створює вікно редагування (дозволяє вибирати колір, шрифт і т.д.);

- StatusBar - відображає інформацію про стан програми;

- TrackBar - створює повзунок;

- ProgressBar - використовується для відображення ходу процесу;

- UpDown - створює кнопку-лічильник;

- HotKey - створює підтримку "гарячих клавіш";

- AnimatedSymbol - створює найпростішу аннімацію.

Сторінка Additional складається з наступних компонент:



- BitBtn-використовується для створення кнопок, на яких розташований малюнок;

- SpeedButton - застосовується для створення лінійок інструментів разом з компонентом Panel;

- MaskEdit - використовується для введення символів відповідно до шаблоном;

- StringGrid - застосовується для відображення текстової інформації в рядках і стовпцях;

- DrawGrid - застосовується для відображення нетекстової інформації в рядках і стовпцях;

- Image - використовується для відображення графіки;

- Shape - використовується для малювання геометричних фігур;

- Bevel - використовується для малювання об'ємного прямокутника;

- ScrollBar - застосовується для створення зон відображення з прокруткою;

- Scroller - застосовується для створення зон відображення з горизонтальною прокруткою;



Компоненти сторінки Data Acces використовуються для зв'язку і передачі інформації між програмами та базами даних. У роботі не розглядаються.

Компоненти сторінки Data Controls використовуються для організації доступу до даних. У роботі не розглядаються.



Сторінка Win 3.1 містить компоненти, орієнтовані на Windows 3.1.

У роботі не розглядаються.


Сторінка Internet містить компоненти, орієнтовані на роботу з Internet.



  • TFTP - компонент, який здійснює перенесення даних між локальним і віддаленим комп'ютером з рлмощью протоколу FTP;

  • THTML - призначений для відображення документів формату HTML;

  • THTTP - дозволяє отримувати документи з допомогою протоколу HTTP;

  • TNNTP - дозволяє здійснювати з'єднання on - line з серверами новин по протоколу NNTP;

  • TPOP - дозволяє додатку обмінюватися даними з поштовими серверами з використанням протоколу POP 3;

  • TSMTP - підтримує обмін повідомленнями з поштовими серверами на основі протоколу SMTP;

  • TTCP - здійснює мережеве з'єднання і обмін даними по протоколу TCP;

  • TUDP - здійснює з'єднання і обмін даними по протоколу UDP.

Компоненти сторінки Dialogs використовуються для створення різних вікон діалогу (невізуальні компоненти);



- OpenDialog - для створення вікон діалогу "відкрити файл";

- SaveDialog - для створення вікон діалогу "зберегти файл";

- FontDialog - для створення вікон діалогу "шрифти";

- ColorDialog - для створення вікон діалогу "колір";

- PrintDialog - для створення вікон діалогу "печатку";

- PrinterSetupDialog - для створення вікон діалогу "установки принтера";

- FindDialog - для створення вікон діалогу "знайти";

- ReplaceDialog - для створення вікон діалогу "замінити".

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



- Timer - використовується для запуску процедур, функцій і т.д. в заданий час (Невізуальний компонент);

- PaintBox - створює область, в якій можна малювати;

- FileListBox - створює вікно, в якому відображається список файлів з ​​вибраного каталогу;

- DirectoryListBox - відображає каталоги вибраного диска;

- DriveComboBox - дозволяє відображати і вибирати диски;

- FilterComboBox - дозволяє створювати вікно для відображення фільтрів файлів;

- MediaPlayer - дозволяє програвати звукові і відеофайли;

- OLEContainer-створює область для об'єкта OLE;

- DDEClientConv - використовується для діалогу з DDE сервером (Невізуальний компонент);

- DDEClientItem - використовується для специфікації даних, переданих DDE сервера (Невізуальний компонент);

- DDEServerConv - використовується для DDE сервером для діалогу з DDE з клієнтом (компонент Невізуальний);

- DDEServerItem - використовується для специфікації даних сервера (компонент Невізуальний).

QReport-ВК використовуються для генерації звітів. У роботі не розглядається.



Activeve X - OCX-компоненти, неявляющіеся частиною C + + Builder.



- ChartFX - використовується для побудови діаграм;

- VCFirstImpression-реалізує тривимірну графіку;

- VCFormulaOne - використовується для роботи з електронними таблицями;

- VCSpeller - засіб перевірки орфографії;

- GraphicsServer - засіб для роботи з графікою;

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

Сторінка Samples містить компоненти, розроблені користувачами - приклади VCL.



- Gauge - створює індикатор ходу процесу;

- SpinButton - дозволяє створювати кнопки-лічильники;

- SpinEdit - створює вікно редагування з кнопкою-лічильником;

- MCxSpriteBgr - панель, на якій можна створювати спрайт;

- MCxStrite - дозволяє створювати спрайт.

Компоненти VCL можна розробляти самостійно, тому існує велика кількість сторінок і компонентів. Ось деякі з сторінок.

JG - додаткові компоненти



- Banner - позволет створювати у вікні рухомий текст або зображення;

- SizeTask - дозволяє встановлювати максимальний розмір форми

MyStuff - додаткові компоненти



- Animated - програє bmp-файли;

- AutoLed - кнопка міняє колір;

- MMLabel - мітка змінює колір;


4.5 Програми, управління подіями, виключення


Розглянемо найпростішу програму - висновок рядка після натискання кнопки. Створимо новий проект або скористаємося порожнім проектом, який надається С + + Builder у момент його запуску.

На порожню форму покладемо два компоненти: рядок редагування Edit і кнопку Button.

Для цього клацнемо мишею на піктограмі необхідного елемента в палітрі, а потім поставимо його в потрібне місце форми.

Далі клацнемо на властивості Text компоненти Edit і видалимо текст, присвоєний рядку системою.

Змінимо властивість Caption кнопки Button, ввівши текст "Натисни". Форма готова. Залишилося написати текст для обробки натиснення кнопки. Для цього треба виділити кнопку Button, переключити вікно інспектора об'єкта в режим створення обробників подій і двічі клацнути на події OnClick.

Відкриється вікно редагування коду, в якому з'явився порожній обробник події. Додамо в нього рядок вихідного тексту:

Edit1-> Text = "Привіт від Borland C ++!";

Після цього командою Run - Run почати компіляцію і виконання програми.

Натиснемо кнопку "Натисни", і програма привітає нас. На відміну від DOS, в якій програма отримує управління при запуску, і виконується від початку до кінця, в Windows 95 програма управляється подіями. При управлінні подіями програма не робить нічого до тих пір, поки не відбувається подія - натискання клавіші миші, натискання клавіші клавіатури і т.д.

Існують різні види подій і їх обробка. На прикладах розглянемо деякі з них.

1.Обработчік, відгукується на подію.

Розглянемо приклад - обробка натискання клавіші миші і висновок координат курсору миші.

1.Запускаем C + + Builder.

2.В інспектора об'єктів вибираємо сторінку Events.

3.Справа від мітки події OnMouseDown (натискання клавіші миші) двічі клацаємо мишею.

4.Появляется програмний код процедури - обробника подій.

5.Ввод код.

Form 1 -> Canvas -> TextOut (X, Y, "Координата" + IntToStr (X) +

"," + IntToStr (Y));

6. Запускаємо програму на виконання.

При натисканні клавіші миші активізується обробник подій OnMouseDown, якому передаються параметри - координати X і Y.

Таким чином в даному випадку ми розглянули варіант, коли обробнику подій передана деяка інформація - параметри X і Y.

2.Обрабочік подій, що передає інформацію, що викликається процедурою.

Можливий варіант, коли обробник подій передає інформацію функції, яка його викликала. Розглянемо приклад, коли у вікні редагування всі літери перетворюються в великі.

1.Запускаем C + + Builder.

2.Виводім на форму з палітри компонент елемент Edit.

3.В розділі інспектора об'єктів Events вправо від OnKeyPress два рази клацаємо мишею, отримуємо фрагмент коду.

4.Набіраем код.


Key = AnsiUpperCase (Key) [1];


5.Запускаем на виконання. Будь-яка введена літера друкується як прописна.

У даному прикладі мінлива Key, що містить значення натиснутоюклавіші вказана як покажчик на адресу символу - в цьому випадку будь-які зміни, зроблені у змінній передаються назад в зухвалу функцію. Функція AnsiUpperCase (Key) перетворює символ в заголовний.

Крім цього існують обробники подій, орієнтований на обробку допоміжних операцій у складній програмі.

Винятки. Для обробки виключень (помилок) в C + + Builder є спеціальні засоби. Зокрема, при виникненні помилки можлива передача керування блоку, який орієнтований на обробку цієї помилки. Для цієї мети використовується блок try ... except () наступного формату:

try {

виконуваний код

}

except (перевіряється пе p Ємен)

{

код, що виконується при помилку

}


4.6 Стратегія налагодження Windows-програм


Помилки в програмі можуть бути найрізноманітнішими. Але для Windows-додатків характерні наступні:

- Виклик невірної функції, коли замість однієї функції помилково викликається інша;

- Викликам Windows API передаються неправильні аргументи;

- Завдання невірних параметрів циклу;

- Помилка в умові операторів if, switch, while і т.д., що призводить до неправильного розгалуженню;

- Виникнення не передбаченого програмістом варіанти реакції системи.

Для налагодження програм звичайно використовується декілька стандартних операцій:

* Установка точок переривання (breakpoints);

* Перегляд вмісту змінних і ділянок пам'яті;

* Підстановка неправдивих даних для моделювання ситуації "що - якщо";

* Помилкові виклики.

DOS-програму можна виконувати покроково, перебираючись від одного рядка вихідного тексту до іншої У Windows ж це нереально. Потрібно поставити крапку переривання на вас цікавить ділянці програми і запустити її на виконання командою Run - Run. Досягнувши точки переривання, програма призупинить своє виконання, даючи можливість програмісту приступити до налагодження дій.

У програмах на C + + Builder, точки переривання найзручніше ставити усередині обробників подій.

Найпростіший спосіб встановити точку переривання - натиснути на клавішу <F5>. При цьому вибрана для зупинки рядок виділяється червоною смугою, на лівому краю рядка з'являється маленький значок "Stop".

Повторне натискання на <F5> скасовує вже наявну точку переривання.

Інший спосіб встановити точку переривання - клацнути мишею на лівому краю вікна редагування.

Коли помилковий обробник знайдений, потрібно приступати до уточнення місця помилки. Для цього можна виконувати програму крок за кроком командою Trace Into (клавіша <F7>) або Step Over (клавіша <F8>), перевіряючи, як змінюються дані програми.

Після того як програма налагоджена, необхідно перетрансліровать її, встановивши в головному меню в розділі Options -> C + + опцію Release.


4.7 Використання компонентів VCL у розробці програм


Використання меню.

Сторінка Standard містить найбільш часто використовувані компоненти - до них відносяться компоненти MainMenu і PopupMenu.

Кожному користувачеві Windows, меню, що розкривається представляє собою детальний перелік таких команд, як Open або Exit. У більшості додатків в головному меню перераховані імена одного або декількох розкривних підменю.

Головне меню (компонент MainMenu). Використовується для створення головного меню програми, яке завжди відображається під заголовком вікна.

Спливаюче меню (компонент PopupMenu). Використовується для створення спливаючих меню, які з'являються при при клацанні правою кнопкою миші, коли вказівник, миші знаходиться всередині клиентной області вікна.



Для того щоб побудувати головне меню програми, необхідно виконати наступне:

1. На форму головного вікна помістіть об'єкт MainMenu.

За умовчанням в C + + Builder. йому присвоюється ім'я MainMenu 1.

2. Встановіть властивість форми Menu рівним імені об'єкта MainMenu.

3. Двічі клацніть на об'єкті MainMenu 1 і використовуйте Menu Designer для введення команд меню.

Для того щоб створити спливаюче меню, яке з'являється при клацанні правою кнопкою миші, виконайте наступне:

1. Помістіть на форму об'єкт Рор up Ме nu. За умовчанням в C + + Builder йому присвоюється ім'я PopupMenu 1.

2. Дайте PopupMenu 1 властивості форми PopupMenu.

3. Двічі клацніть на об'єкті PopupMenu 1 і використовуйте Menu Designer для введення команд меню.

Розглянемо приклад - розробимо найпростіший редактор тексту.

Створіть файл з ім'ям 1. Txt в каталозі, в якому буде зберігатися приклад і запишіть у нього який-небудь текст. Запустіть C + + Builder.

1.Поместіте на форму компонент Memo. Згідно малюнка змініть розміри.

У інспекторі об'єктів встановіть ScrollBars в позицію ssVertical (вертикальна смуга прокручування). На полі Memo ви бачите текст Memo 1. Для того щоб він зникав при запуску програми клацніть мишею по формі і напишіть між {і}; команду очищення вікна Memo 1:


Memo 1 -> Clear ();


2. Помістіть на форму кнопку Button. Властивість Caption у інспекторі об'єктів змініть на Close. Клацніть на кнопці. і напишіть код:

Close (); - по цій команді програма припиняє роботу.

3. Помістіть на форму компоненти MainMenu і PopupMenu.

Клацніть по формі і напишіть у властивостях MainMenu - MainMenu 1 і PopupMenu - PopupMenu 1 відповідно.

4.Щелкніте два рази на компоненті MainMenu. З'являється конструктор меню. У інспекторі об'єктів властивість З aption змініть на & File (& - швидка клавіша ALT + F). Натисніть клавішу Enter. Далі в конструкторі меню клацніть мишею під командою File і знову властивість Caption змініть на & Open, нижче знову з'являється синій квадратик напишіть властивість Caption & Save, а потім на наступному пункті меню змініть Caption на E & xit.

5.Щелкніте мищью поруч з & File (правіше) і запишіть у Caption & Help.

Таким чином всі пункти меню ми записали і вони повинні появітсяна формі.

6.Начнем ставити у відповідність подій (пунктам меню) програмний код. Клацніть мишею на команді File, поставте курсор на Open і клацніть мишею. між командами {і} запишіть код:

Memo 1 -> Lines -> LoadFromFile ("1. Txt");

За цією командою текст з файла 1. Txt завантажиться у вікно Memo. Властивість Lines об'єкта Memo це об'єкт типу рядок символів, яка відображається у вікні. Метод LoadFromFile дозволяє завантажити файл у Memo.

Перед нами редактор тексту - текст можна модифікувати, а потім записати.

7.Щелкніте мишею на команді File, поставте курсор на Save і клацніть мищью. між командами begin і end; запишіть код:

Memo 1 -> Lines -> SaveToFile ("1. Txt");

За цією командою текст запишемо у файл 1. Txt.

8. Найбільш Цікаві дії з командою Exit.

Стандартно можна було-б клацнути мишею на команді Exit і записати код Close ();, але цей код у нас є по натисненню клавіші Button програма припиняє роботу, тому ми робимо так:

8.1.В інспектора об'єктів у випадаючому меню (у шапці) вибираємо опцію Exit 1.

8.2 Переходимо в інспекторі об'єктів на сторінку Events і клацаємо мишею у полі події OnClick.

8.3.Вибіраем Button 1 Click. Тобто ми поєднуємо події:

- Натискання клавіші (закриття програми);

- Вибір опції меню Exit.

9. У дизайнера меню заходь в розділ Help-клацаємо мишею і пишемо код:

Canvas -> TextOut (10,10, "Допомоги поки немає!");

10. Додаємо спливаюче меню. Клацаємо двічі на компоненті PopupMenu.

11.Появляется дизайнер меню. Першу опцію меню вказуємо в Caption - & Open, наступну & Save і останню E & xit (також як в MainMenu).

12.Щелкаем на опції Open. У випадаючому меню інспектора об'єктів вибираємо опцію Open 2. Переходимо в інспекторі об'єктів на сторінку на сторінку Event і клацаємо мишею у полі події OnClick. Знаходимо Open 1 Click і клацаємо мишею (тепер ми поєднали подія відкриття файлу 1. Txt в меню MainMenu і PopupMenu);

Відповідно вибираємо опцію & Save і поєднуємо з подією Save 1 Click. Далі поєднуємо опцію Exit з подією Button 1 Click. Далі програму запам'ятовуємо і транслюємо. Програма буде виглядати так:

//------------------------------------------------ ---------------------------

# Include <vcl \ vcl. H>

# Pragma hdrstop


# Include "Unit 1. H"

//------------------------------------------------ ---------------------------

# Pragma resource "*. dfm"

TForm1 * Form1;

//------------------------------------------------ ---------------------------

__fastcall TForm1:: TForm1 (TComponent * Owner)

: TForm (Owner)

{

}

//------------------------------------------------ ---------------------------

void __fastcall TForm1:: FormCreate (TObject * Sender)

{

Memo1-> Clear ();

}

//------------------------------------------------ ---------------------------

void __fastcall TForm1:: Button1Click (TObject * Sender)

{

Close ();

}

//------------------------------------------------ ---------------------------

void __fastcall TForm1:: Open1Click (TObject * Sender)

{

Memo1-> Lines-> LoadFromFile ("1.txt");

}

//------------------------------------------------ ---------------------------

void __fastcall TForm1:: Save1Click (TObject * Sender)

{

Memo1-> Lines-> SaveToFile ("1.txt");

}

//------------------------------------------------ ---------------------------

void __fastcall TForm1:: Help1Click (TObject * Sender)

{

Canvas -> TextOut (10,10, "Допомоги поки немає!");

}

//------------------------------------------------ ---------------------------

Кнопки перемикачі і вимикачі.

Кнопки, перемикачі та вимикачі - це основа графічного інтерфейсу, тому C + + Builder надає цілий "набір" всіляких кнопок, перемикачів і вимикачів. Крім того, є можливість об'єднувати групи кнопок і використовувати організуючі компоненти - фаски і панелі.

Кнопка (компонент Button). Стандартний керуючий елемент

Windows.

Кнопка з растровим зображенням (компонент BitBtn). Компонент BitBtn працює також, як і компоненти Button, але відрізняються від останніх наявністю кольоровий піктограми, візуально представляє дію кнопки.

Кнопка панелі інструментів (компонент SpeedButton). Зазвичай ці компоненти використовуються для створення панелей інструментів.

На кнопках BitBtn або SpeedButton відображається піктограма (glyph), яка представляє собою растрове зображення Windows. Незважаючи на те, що розміри піктограм не обмежені, зазвичай застосовується стандартний розмір - 16х16 пікселів при 16 кольорах.

Властивість glyph компонента є об'єктом, у яких тип TBitmap.

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

1. Стан кнопки = ненажатое (звичайний стан).

2. Стан кнопки = недоступне (відображення сірим кольором; Enabled = false).

3. Стан кнопки = натискання (відображення зміщене і, можливо, затемнене).

4. Стан кнопки = фіксоване натискання (тільки для кнопок панелі інструментів).

Піктограми можна призначати як при створенні форми, так і під час роботи програми (наприклад, для отримання динамічного візуального ефекту або для зміни виду кнопки в залежності від зовнішніх умов). Для того щоб піктограма завантажувалася під час роботи, розмістіть об'єкт BitBtn на формі, клацніть на ньому двічі, і в обробник події OnClick вставте наступні оператори:

BitBtn1-> Glyph-> LoadFromFile ("alarm.bmp");

Вимикач (компонент CheckBox). Це також стандартний керуючий елемент Windows, що складається з мітки і невеликого квадратика. Натиснувши на ньому, користувач може включити або вимкнути параметр або режим, описаний UA.

Група (компонент GroupBox). Даний компонент призначений для логічного об'єднання безлічі перемикачів та інших об'єктів.

Фокус введення користувачі можуть переміщати між групами за допомогою клавіші <Tab>. Потім, використовуючи клавіші управління курсором, можна вибрати один з керуючих елементів, об'єднаних в групу.

Перемикач (компонент RadioButton). На групу або панель можна помістити кілька перемикачів, але в більшості випадків для створення наборів перемикачів набагато зручніше використовувати компонент RadioGroup. Крім того, набори перемикачів можна розташовувати безпосередньо на формі.

Група перемикачів (компонент RadioGroup). Цей компонент має багато спільного з групою, але він набагато зручніше у використанні при створенні наборів перемикачів. Для організації перемикачів необхідно тільки вказати текст перемикаються параметрів у властивості Items групи перемикачів.

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

Панель (компонент Panel). Даний компонент дозволяє впорядкувати захаращені інформацією вікна, а також є основою створення панелей інструментів і рядків стану.

Фаска (компонент Bevel). Цей суто візуальний компонент виглядає у вікні як прямокутний виступ або заглиблення. Фаска також використовується для створення горизонтальних і вертикальних ліній.

Розглянь приклад використання розглянутих вище компонент.


Почнемо розробку нового проекту.

Згідно малюнка помістимо на верхню частину форми компонент Panel.

Властивості Caption привласнимо "Демонстрація". Далі на форму додамо компонент Label і встановимо властивість Caption "Назва". Під мітку додамо компонент Edit. Використовуючи інспектор об'єктів видалимо символи з властивості Text об'єкта Edit. Далі додамо компонент Memo.

У інспекторі об'єктів встановимо ScrollBars в позицію ssVertical (вертикальна смуга прокручування). Далі в інспекторі об'єктів подвійним клацанням відкриємо властивість Lines, видалимо текст Memo 1 та чотири рази натиснемо клавішу Enter (будемо працювати з чотирма рядками).

Встановимо на формі компоненти RadioGroup, Scrollbar і ComboBox. Двічі клацнемо на правіше властивості Items і введемо чотири рядки: сірий, блакитний, жовтий, червоний. Двічі клацнемо по компоненті RadioGrouo і введемо код:

if (RadioGroup1-> ItemIndex == 0) {Form1-> Color = clSilver;}

if (RadioGroup1-> ItemIndex == 1) {Form1-> Color = clBlue;}

if (RadioGroup1-> ItemIndex == 2) {Form1-> Color = clYellow;}

if (RadioGroup1-> ItemIndex == 3) {Form1-> Color = clRed;}

Цей фрагмент коду дозволяє змінювати колір форми залежно від зазначеної кнопки.

Далі двічі клацнемо по компоненті Scrollbar і додамо код:


RadioGroup1-> ItemIndex = ScrollBar1-> Position;


Цей фрагмент коду дозволяє змінювати колір форми залежно від положення повзунка.

Помістимо на форму копонент GroupBox і додамо дві кнопки Button, дві кнопки BitBtn, дві RadioButton і дві Checkbox. Клацнемо по кнопці Button 1 і введемо код:

/ / Очистити вміст Memo

Memo1-> Clear ();

/ / Копіювати в Memo текст, введений в Edit

Memo1-> Lines-> Add (Edit1-> Text);

/ / Копіювати в Memo текст з Combobox

Memo1-> Lines-> Add (ComboBox1-> Text);

/ / Якщо натиснута першою радіокнопка, то колір Memo білий

if (RadioButton1-> Checked) Memo1-> Color = clWhite;

/ / Якщо натиснута першою радіокнопка, то колір Memo світло-блакитний

if (RadioButton2-> Checked) Memo1-> Color = clAqua;

Клацнемо по кнопці Button 2 і введемо код:

Close (); / / закінчити роботу

Клацнемо по кнопці BitBtn 1 і введемо код:

/ / Якщо позначена кнопка Checkbox 1, то розмір шрифту на формі 12

/ / Інакше розмір шрифту 8

if (CheckBox1-> State == cbChecked)

Font-> Size = 12;

else

Font-> Size = 8;

/ / Якщо позначена кнопка Checkbox 2, то колір шрифту на формі фіолетовий

/ / Інакше колір шрифту чорний

if (CheckBox 2 -> State == cbChecked)

Form1-> Font-> Color = clPurple;

else

Form1-> Font-> Color = clBlack;

Клацнемо по кнопці BitBtn 2 і введемо код:

Form 1 -> Hide ();// згорнути форму з ім'ям Form 1

AddTab -> Show ();// показати форму з ім'ям AddTab

Як працювати з двома формами розглянемо далі.

Вся програма буде виглядати наступним чином:

//------------------------------------------------ ---------------------------

# Include <vcl\vcl.h>

# Pragma hdrstop

# Include "Unit1.h"

# Include "Unit2.h"

//------------------------------------------------ ---------------------------

# Pragma resource "*. dfm"

TForm1 * Form1;

//------------------------------------------------ ---------------------------

__fastcall TForm1:: TForm1 (TComponent * Owner)

: TForm (Owner)

{

}

//------------------------------------------------ ---------------------------

void __fastcall TForm1:: RadioGroup1Click (TObject * Sender)

{

if (RadioGroup1-> ItemIndex == 0) {Form1-> Color = clSilver;}

if (RadioGroup1-> ItemIndex == 1) {Form1-> Color = clBlue;}

if (RadioGroup1-> ItemIndex == 2) {Form1-> Color = clYellow;}

if (RadioGroup1-> ItemIndex == 3) {Form1-> Color = clRed;}

}

//------------------------------------------------ ---------------------------

void __fastcall TForm1:: ScrollBar1Change (TObject * Sender)

{

RadioGroup1-> ItemIndex = ScrollBar1-> Position;

}

//------------------------------------------------ ---------------------------

void __fastcall TForm1:: Button1Click (TObject * Sender)

{

Memo1-> Clear ();

Memo1-> Lines-> Add (Edit1-> Text);

Memo1-> Lines-> Add (ComboBox1-> Text);

if (RadioButton1-> Checked) Memo1-> Color = clWhite;

if (RadioButton2-> Checked) Memo1-> Color = clAqua;

}

//------------------------------------------------ ---------------------------

void __fastcall TForm1:: Button2Click (TObject * Sender)

{

Close ();

}

//------------------------------------------------ ---------------------------

void __fastcall TForm1:: BitBtn1Click (TObject * Sender)

{

if (CheckBox1-> State == cbChecked)

Font-> Size = 12;

else

Font-> Size = 8;

if (CheckBox2-> State == cbChecked)

Form1-> Font-> Color = clPurple;

else

Form1-> Font-> Color = clBlack;

}

//------------------------------------------------ ---------------------------

void __fastcall TForm1:: BitBtn2Click (TObject * Sender)

{

Form 1 -> Hide ();

AddTab -> Show ();


}

//------------------------------------------------ ---------------------------

Побудуємо другу сторінку програми. Додамо в проект, що розробляється другу форму і дамо їй ім'я AddTab і збережемо під ім'ям AdditionalTab. Pas.

Розмістимо візуальні компоненти на формі згідно малюнка.


Помістимо на форму в лівий нижній кут компонент Bevel. Помістимо три кнопки типу BitBtn в нижній лівий кут форми на компонент Bevel.

Властивість Kind для BitBtn 1 і BitBtn 2 встановимо рівним bkCustom, а для BitBtn 3 - рівним bkClose.

Встановимо на кнопках для властивостей Caption текст, що відповідає малюнку. Для кожної з кнопок встановимо гравіювання (glyph), використовуючи готові гравіювання, що поставляються в комплекті з мовою або створюючи свої за допомогою редактора Image Editor в меню інструментів Tools.

Додаємо код дії для кнопок:

BitBtn 1:

Form1-> Show (); \ \ показати форму Form 1

AddTab-> Hide (); \ \ згорнути форму AddTab

BitBtn 2:

ShowMessage ("Поки НІ"); \ \ наступної сторінки поки немає

BitBtn3:

Form1-> Close ();// закрити форму Form1

Для правильного закриття програми та звільнення ресурсів необхідно додати для події Close форми Form 1 код:


Application-> Terminate (); \ \ звільнити ресурси


У лівому верхньому кутку форми розмістимо компонент Shape (зазначимо у властивості Shape значення stEllipse), компонент Panel і на ньому дві кнопки SpeedButton і компонент Image, в який можна завантажити будь-яке зображення.

Кнопки SpeedButton можуть перебувати в стані: Up - верхнє, Disabled - відключено, Down - нижнє, Stay Down - притиснуте. Для кожного стану відображається відповідний елемент гравіювання. Для використання цих станів за допомогою вбудованими графічного редактора створюється матриця 16х64 крапки. Зображення буде мати чотири квадратні зони.

Встановимо властивість NumGlups для Speedbutton 1 рівним 4, а властивість GroupIndex рівним 1.

Двічі по кнопки SpeedButton 1 і пишемо код:


if (SpeedButton1-> Down == true)

Image1-> Visible = false;

Shape1-> Brush-> Color = clRed;


Код означає, що якщо натиснута кнопка, то зображення Image 1 зникає, а зображення фігури Shape 1 червоного кольору.

Двічі клацаємо по кнопці SpeedButton 2 і записуємо код:


if (SpeedButton1-> Down = true)

{Image1-> Visible <<true;

Shape1-> Brush-> Color = clLime;


Для SpeedButton 1 використовуємо властивість Hint (підказка). У цій властивості зберігається рядок підказки, яка з'являється, коли курсор миші знаходиться над кнопкою. ShowHint необхідно встановити в true.

Додамо на форму компонент Label властивість Caption задамо Phone.

Під міткою встановимо компонент MaskEdit. Двічі клацнемо на властивості EditMask і запусти редактор маски вводу. Далі клацнемо на Phone і натиснемо клавішу OK. Компонент MasEdit буде налаштований на прийом телефонних номерів.

Помістимо на форму компонент StringGrid і встановимо властивості: RowCount і ColCount. Властивості FixedCols і FixedRows встановимо в 0.

Підберемо розмір сітки щоб ​​було видно дев'ять осередків. Додамо на форму кнопку з властивістю Caption Fill Grid. Двічі клацнемо на ній і наберемо код:

int x, y;

for (x = 0; (x <= StringGrid1-> ColCount-1); x + +)

for (y = 0; (y <= StringGrid1-> RowCount-1); y + +)

StringGrid1-> Cells [x] [y] = ("Coord." +

IntToStr (x )+"-"+ IntToStr (y));


Далі поставимо на форму панель з прокруткою ScrollBox і розмістимо на ній компоненти: BitBtn з властивістю Kind рівним bkHelp. Додамо на ScrollBox Panel. Двічі клацаємо на кнопці BitBtn 4 і додаємо код:


ShowMessage ("Test");


Компонент ScrollBox c розміщеними на ньому компонентами дозволяє продемострували здібності показвает фрагменти, які не поміщаються в зоні використання.

Загальний вигляд програмного модуля AddTab:

//------------------------------------------------ ---------------------------

# Include <vcl\vcl.h>

# Pragma hdrstop


# Include "Unit2.h"

# Include "Unit1.h"

//------------------------------------------------ ---------------------------

# Pragma link "Grids"

# Pragma resource "*. dfm"

TAddTab * AddTab;

//------------------------------------------------ ---------------------------

__fastcall TAddTab:: TAddTab (TComponent * Owner)

: TForm (Owner)

{

}

//------------------------------------------------ ---------------------------

void __fastcall TAddTab:: BitBtn1Click (TObject * Sender)

{

Form1-> Show ();

AddTab-> Hide ();

}

//------------------------------------------------ ---------------------------

void __fastcall TAddTab:: BitBtn3Click (TObject * Sender)

{

Form1-> Close ();

}

//------------------------------------------------ ---------------------------

void __fastcall TAddTab:: FormClose (TObject * Sender, TCloseAction & Action)

{

Application-> Terminate ();

}

//------------------------------------------------ ---------------------------

void __fastcall TAddTab:: SpeedButton1Click (TObject * Sender)

{

if (SpeedButton1-> Down == true)

{Image1-> Visible = false;

Shape1-> Brush-> Color = clRed;

}

}

//------------------------------------------------ ---------------------------

void __fastcall TAddTab:: SpeedButton2Click (TObject * Sender)

{

if (SpeedButton1-> Down = true)

{Image1-> Visible <<true;

Shape1-> Brush-> Color = clLime;

}

}

//------------------------------------------------ ---------------------------

void __fastcall TAddTab:: Button1Click (TObject * Sender)

{

int x, y;

for (x = 0; (x <= StringGrid1-> ColCount-1); x + +)

for (y = 0; (y <= StringGrid1-> RowCount-1); y + +)

StringGrid1-> Cells [x] [y] = ("Coord." +

IntToStr (x )+"-"+ IntToStr (y));

}

//------------------------------------------------ ---------------------------


void __fastcall TAddTab:: BitBtn4Click (TObject * Sender)

{

ShowMessage ("Test");

}

//------------------------------------------------ ---------------------------

void __fastcall TAddTab:: BitBtn2Click (TObject * Sender)

{

ShowMessage ("Поки НІ");

}

//------------------------------------------------ ---------------------------

void __fastcall TAddTab:: MaskEdit1Change (TObject * Sender)

{


}

//------------------------------------------------ ---------------------------

Розглянемо ще один проект. Помістимо на форму згідно малюнка компоненти:



TabControl (на нього помісти панель Panel

Додати в блог або на сайт

Цей текст може містити помилки.

Програмування, комп'ютери, інформатика і кібернетика | Методичка
683.8кб. | скачати


Схожі роботи:
Предмет і значення дисципліни Основи екології Наукові основи раціонального природокористування
Основи аудиту 2 Правові основи
Основи енергоаудиту
Основи культурології 2
Основи конструювання
Основи маркетингу 4
Основи медіапланування
Основи реклами 2
Основи БЖД
© Усі права захищені
написати до нас