Реферати

Учбова допомога: Об'єктно-орієнтоване програмування на Borland З++

Інвентаризація товарів і тари на складах. ДОПОВІДЬ По дисципліні бухгалтерський облік у торгівлі На тему: "Інвентаризація товарів і тари на складах". Зміст 1. Загальні правила проведення інвентаризації......3

Аліса в країні чудес. Аліса в країні чудес Автор: Керрол Л. Переказ з англійського БОРИСА ЗАХОДЕРА ГЛАВА НІЯКА, з якої проте можна дещо довідатися Більше всього на світі я ненавиджу обман і люблю чесність і тому відразу чесно визнаюся, що я вас (зовсім трошки!) обдурив: насправді це не НІЯКА ГЛАВА, а НІЯКА НЕ ГЛАВА - це просто-напросто...

Організація наукової діяльності учнів. Конкурс соціальних проектів " Наше місто" Номінація: "Місто дитинства" Назва проекту: "Організація наукової діяльності учнів"

Ефективність використання основних проихзводственних фондів. Зміст УВЕДЕННЯ 3 Глава I. ТЕОРИЕТИЧЕСКИЕ ОСНОВИ ВІДТВОРЕННЯ ОСНОВНИХ ФОНДІВ 7 § 1.1. Основні фонди підприємств і їхня класифікація 7 §1.2. Економічна сутність виробничих фондів, особливості їхньої організації й амортизації. 14

Остерман, Андрій Іванович. План Уведення 1 Початок діяльності. Сподвижник Петра 2 В політичній боротьбі 1725-1730 3 Зовнішня політика при Ганні Иоанновне 4 Падіння і посилання 5 Характеристика

Тексти лекцій, прочитаних в Московському державному університеті економіки, статистики і інформатики

В текстах лекцій розглянуті основні принципи і кошти об'єктно-орієнтованого програмування із застосуванням мови З++ і системи програмування Borland З++. У додатку приведені задачі для самостійного рішення. Передбачається, що читач вже знайомий з основами універсальних мов програмування. Допомога призначена для студентів спеціальності "Прикладна математика" і може бути використане студентами інших спеціальностей для самостійного вивчення З++.

1. Об'єктно-орієнтований підхід в програмуванні

1.1 Технології програмування

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

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

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

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

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

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

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

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

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

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

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

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

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

1.2. Суть об'єктно-орієнтованого підходу до програмування

Основні ідеї об'єктно-орієнтованого підходу спираються на наступні положення:

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

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

- Об'єкт описується набором параметрів, значення яких визначають стан об'єкта, і набором операцій (дій), які може виконувати об'єкт.

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

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

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

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

Класи об'єктів часто зручно будувати так, щоб вони утворювали ієрархічну структуру. Наприклад, клас "Студент", що описує абстрактного студента, може служити основою для побудови класів "Студент 1 курсу", "Студент 2 курсу" і т. д., які володіють всіма властивостями студента взагалі і деякими додатковими властивостями, що характеризують студента конкретного курсу. При розробці інтерфейса з користувачем програми можуть використати об'єкти загального класу "Вікно" і об'єкти класів спеціальних вікон, наприклад, вікон інформаційних повідомлень, вікон введення даних і т. п. У таких ієрархічних структурах один клас може розглядатися як базовий для інших, похідних від нього класів. Об'єкт похідного класу володіє всіма властивостями базового класу і деякими власними властивостями, він може реагувати на ті ж типи повідомлень від інших об'єктів, що і об'єкт базового класу і на повідомлення, що мають значення тільки для похідного класу. Звичайно говорять, що об'єкт похідного класу успадковує всі властивості свого базового класу.

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

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

Досвід програмування показує, що будь-який методичний підхід в технології програмування не повинен застосовуватися сліпо з ігноруванням інших підходів. Це відноситься і до об'єктно-орієнтованого підходу. Існує ряд типових проблем, для яких його корисність найбільш очевидна, до таких проблем відносяться, зокрема, задачі імітаційного моделювання, програмування діалогів з користувачем. Існують і задачі, в яких застосування об'єктного підходу ні до чого, крім зайвих витрат труда, не приведе. У зв'язку з цим найбільше поширення отримали об'єктно-орієнтовані мови програмування, що дозволяють поєднувати об'єктний підхід з іншими методологіями. У деяких мовах і системах програмування застосування об'єктного підходу обмежується коштами інтерфейса з користувачем (наприклад, Visual FoxPro ранніх версій).

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

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

2. Початкові відомості про мову Ці

2.1 Призначення Ці, історичні відомості

Мова Сі був розроблений в 70-е роки як мову системного програмування. При цьому ставилася задача отримати мову, що забезпечує реалізацію ідей процедурного і структурного програмування і можливість реалізації специфічних прийомів системного програмування. Така мова дозволила б розробляти складні програми на рівні, порівнянному з програмуванням на Асемблері, але істотно швидше. Ці цілі, в основному, були досягнуті. Більшість компіляторів для Сі написані на Сі, операційна система UNIX < також майже повністю написана на Сі. Недоліком Сі виявилася низька надійність програм, що розробляються через відсутність контролю типів. Спроба поправити справу включенням в систему програмування Сі окремої програми, контролюючої неявні перетворення типів, вирішила цю проблему лише частково.

На основі Сі в 80-е роки була розроблена мова Сі++, спочатку названа "Сі з класами". Сі++ практично включають мову Сі і доповнені коштами об'єктно-орієнтованого програмування. Робоча версія Сі++ з'явилася в 1983 р. Відтоді мова продовжує розвиватися і опублікована декілька версій проекту стандартів Сі і Сі++.

Рядом фірм, виробляючих програмне забезпечення, розроблені компілятори для Сі і Сі++. Системи програмування фірми Borland International виділяються серед інших фірм передусім комплексним підходом до розробки програм, що виражається у включенні в систему програмування інтегрованої середи розробника, об'єднуючої під загальним управлінням текстовий редактор для введення початкових текстів програм, компілятор, редактор зв'язків і набір відлагоджувальний коштів. У 1989 р. цією фірмою була випущена система Turbo З++, що включала компілятор Сі++, працюючий в операційній системі DOS, з 1992 р. випускаються системи Borland З++, вмісні компілятори Сі++ для DOS і WINDOWS, з 1997 р. постачається версія Borland З 5.0, вмісна компілятори Сі++ для WINDOWS, причому компілятор для WINDOWS тепер дозволяє розробляти як 16-розрядний, так і 32-розрядні варіанти програм для ПЕВМ з процесорами i486 і Pentium.

Програма на Сі/Сі++ являє собою один або декілька початкових файлів, які можуть транслюватися роздільно. Результати трансляції (об'єктні файли) об'єднуються в файл, що виконується редактором зв'язків (компоновщиком). Звичайно розрізнюють два типи початкових файлів: файли заголовків і програмні файли. Файли заголовків містять опису типів даних і прототипів функцій і призначені для включення в програмні файли перед їх компіляцією, їх імена, як правило, мають розширення. h, наприклад, stdio.h. Програмні файли містять описи функцій і, можливо, глобальних змінних і констант, їх імена прийнято записувати з розширеннями. c або. cpp, наприклад, myprog.cpp. Один і той же файл заголовків може включатися в декілька програмних файлів

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

У подальших параграфах цього розділу приведений огляд коштів Сі/Сі++, не пов'язаних з об'єктною орієнтацією Сі++.

2.2 Алфавіт, базові типи і опис даних.

Алфавіт мови включає практично всі символи, що є на стандартній клавіатурі ПЕВМ:

- латинські букви А...Z, a...z;

- цифри 0...9;

- знаки операцій і роздільники:

{ } [ ] ()., - > & * + - ~ ! / %? :; = < > ¦ # ^

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

Базові (приречені) типи даних об'єднані в дві групи: дані цілого типу і дані з плаваючою точкою (речовинні).

Дані цілого типу можуть бути звичайним цілим зі знаком (signed) і цілим без знака (unsigned). По числу розрядів, тих, що використовуються для представлення даного (діапазону значень) розрізнюють звичайне ціле (int), коротке ціле (short int) і довге ціле (long int). Символьні дані (char) також розглядаються як ціле і можуть бути зі знаком і без знака.

Константи цілого типу записуються як послідовності десятеричних цифр, тип константи залежить від числа цифр в записі константи і може бути уточнений додаванням в кінці константи букв L або l (тип long), U або u (тип unsigned) або їх поєднання:

321 - константа типу int,

5326u - константатипа unsigned int,

45637778 - константа типу long int,

2746L - константа типу long int.

Цілі константи можуть записуватися у вісімковій системі числення, в цьому випадку першою цифрою повинна бути цифра 0, число може містити тільки цифри 0. .. 7:

0777 - константа типу int,

0453377 - константа типу long.

Цілі константи можна записувати і в шестнадцатеричной системі числення, в цьому випадку запис константи починається з символів 0x або 0X:

0x45F - константа типу int,

0xFFFFFFFF - константатипа unsigned long.

Константи типу char завжди беруться в одиночні лапки, значення константи задається або знайоме з набору символів, що використовується, або цілою константою, якою передує зворотна коса межа: 'A', '\33', '\042', '\x1B'. Є також ряд спеціальних символів, які можуть вказуватися як значення константи типу char:

'\n' - новий рядок,

' \t' - горизонтальна табуляція,

' \v' - вертикальна табуляція,

' \r' - переклад каретки,

' \f' - переклад сторінки,

' \a' - звуковий сигнал,

' \'' - одиночної лапки (апостроф),

' \"' - двійчастої лапки,

' \\' - зворотна коса межа.

Дійсні числа можуть бути значеннями одного з трьох типів: float, double, long double. Діапазон значень кожного з цих типів залежить від ЕОМ, що використовуються і компілятора. Константи речовинних типів можуть записуватися в природній або експонентній формах і за умовчанням мають тип double, наприклад, 15.31, 1.43 Е-3, 2345.1 e4. При необхідності тип константи можна уточнити, записавши в кінці суфікс f або F для типу float, суфікс l або L для типу long double.

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

int i, j, k; // Три змінних типи int без явної инициализацииdouble х=1, у=2; //Два змінних типи double з початковими значеннями 1 і 2char c1='0'; // Змінна типу char, її значення - код літери 0

Текст, записаний в цих прикладах після знаків //, є коментарем і служить тільки для документування програми. Такий коментар може займати тільки один рядок тексту і допускається в текстах програм на Сі++. Коментар, що займає декілька рядків, береться в спеціальні дужки /* і */.

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

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

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

Нарівні з показаними вище константами-літералами, значення яких визначаються їх уявленням в програмі, в Сі і Сі++ передбачені константи, яким привласнюються власні імена - іменовані константи. У описі іменованої константи присутній описувач const, наприклад,

const double Pi = 3.141592653;

Змінної, ідентифікатор якої оголошений з описувачем const, не можна привласнити інакше значення, чим було встановлено при оголошенні ідентифікатора. Ініціалізоване значення при оголошенні константи є обов'язковим.

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

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

enum ідентифікатор {список переліку} декларатори-инициализатори;

Тут ідентифікатор задає ім'я перечислимого типу, список переліку складається з перечислителей, розділених комами. Кожний перечислитель задається ідентифікатором і, можливо, цілим значенням типу char або int, наприклад,

enum color { RED, GREEN, BLUE } en_color;enum lex_type { CNST, VAR, OPER=3, FUNC };

Якщо значення перечислителя не задане, перший з них набуває значення 0, а кожний наступний - значення, більше на 1. Взагалі будь-який перечислитель за умовчанням має значення на 1 більше попереднього. У Сі/Сі++ прийнято записувати ідентифікатори перечислителей великими буквами. Імена перечислителей використовується або як іменовані константи або для присвапивания змінним перечислимого типу.

У Сі/Сі++ для посилань на змінну того або інакшого типу служать покажчики. Покажчик - це тип даного, значенням якого є адреса іншого даного. При оголошенні покажчика перед ідентифікатором записується знак *. Покажчик може ініціалізуватися адресою даного, для отримання адреси служить операція & (амперсенд):

double у;double *px, *py = &у;

Для покажчиків визначені операції порівняння, складання покажчика з цілим числом, віднімання двох покажчиків, а також операція індексування (операція []).

Для звернення до змінної по покажчику виконується операція разименования, що означається знаком * (зірочка), наприклад, *py = 7.5;.

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

const int cc = 20;const int *pc = &cc; // Можна ініціалізувати адресою константи.double *const delta = 0.001; // Покажчик - константа

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

int ii;int& aii = ii;

При такому описі оператори aii = 5; і ii = 5; еквівалентні.

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

int а [ 5 ]; // Масив з п'яти елементів типу int

Індекси елементів масиву завжди починаються з 0, індекс останнього елемента на одиницю менше числа елементів в масиві. Масив може ініціалізуватися списком значень в фігурних дужках:

int b [ 4 ] = { 1, 2, 3, 4 };

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

int з [ ] = { 1, 2, 3 }; // Масив з трьох елементів типу int

Масиви з розмірністю 2 і більш розглядаються як масиви масивів і для кожного вимірювання вказується число елементів:

double aa [ 2 ] [ 2 ] = { 1, 2, 3, 4 }; // Матриця 2 * 2

Масиви типу char можуть ініціалізуватися рядковим літералом. Рядковий літерал - це послідовність будь-яких символів, крім лапки і зворотної косої межі, взята в лапки. Якщо рядковий літерал не уміщається на одному рядку, його можна перервати символом "\" і продовжити з початку наступного рядка. У стандарті З++ передбачена і інша можливість запису довгих літералів у вигляді декількох записаних підряд рядкових літералів. Якщо між рядковими літералами немає символів, відмінних від пропусків, такі літерали зливаються компілятором в один.

При розміщенні в пам'яті в кінці рядкового літерала додається символ ' \0', т. е. нульовий байт. Рядковий літерал може застосовуватися і для ініціалізації покажчика на тип char:

char str1 [ 11 ] = "Це рядок", str2 [ ] = " Розмір цього масиву визначається"" числом знаків в літералі + 1";char *pstr = "Покажчик з ініціалізацією рядком";

Ім'я масиву в Сі/Сі++ є покажчиком-константою, що посилається на перший елемент масиву, що має індекс, рівний нулю. Для звернення до елемента масиву вказується ідентифікатор масиву і індекс елемента в круглих дужках, наприклад, з[2], aa[0][1].

2.3 Структури і об'єднання

Нарівні з масивами в Сі/Сі++ є агрегати даних типу структур і об'єднань. Тип структури являє собою впорядковану сукупність даних різних типів, до якої можна звертатися як до єдиного даного. Опис структурного типу будується по схемі:

struct ідентифікатор

{ декларатори членів } декларатори_инициализатори;

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

Ідентифікатор після ключового слова struct є ім'ям структурного типу. Ім'я типу може бути відсутнім, тоді тип буде безіменний і в інших частинах програми не можна буде оголошувати дані цього типу. Декларатори_ініциалізатори оголошують конкретні змінні структурного типу, т. е. дані описаного типу, покажчики на цей тип і масиви даних. Декларатори_ініциалізатори можуть бути відсутнім, в цьому випадку оголошення описує тільки тип структури.

Структура, що описує точку на площині, може бути визначена так:

struct Point_struct // Ім'я структури{ int х, у; } // Декларатори членів структуриpoint1, *ptr_to_point, arpoint [3]; // Дані структурного типу

Члени (компоненти) структури описуються аналогічно даним відповідного типу і можуть бути скалярними даними, покажчиками, масивами або даними іншого структурного типу. Наприклад, для опису структурного типу "прямокутник зі сторонами, паралельними осям координат" можна запропонувати декілька варіантів:

struct Rect1{Point p1; // Координати лівого верхнього углаPoint p2; // Координати правого нижнього кута};struct Rect2{Point р [ 2 ]; };struct Rect3 {Pointp; // Лівий верхній уголintwidth; // Ширінаint high; // Висота прямокутника};

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

struct Value;struct Tree_element{Value * val;Tree_element *left, *right;};

Членами структур можуть бути так звані бітові поля, коли в полі пам'яті змінної цілого типу (int або unsigned int) розміщується декілька цілого даного меншої довжини. Нехай, наприклад, в деякої програме синтаксичного розбору опис лексеми містить тип лексеми (до шести значень) і порядковий номер лексеми в таблиці відповідного типу (до 2000 значениий). Для представлення значення типу лексеми досить трьох двійкових розрядів (трьох біт), а для представлення чисел від 0 до 2000 - 11 двійкових розрядів (11 біт). Опис структури, вмісної відомості про лексему може виглядати так:

struct Lexema{unsigned int type_lex: 3;unsigned int num_lex: 11;};

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

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

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

union uword{unsigned int u;unsigned char b [ 2 ];};

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

typedef struct { double re, im } COMPLEX; typedef int *PINT;

Після таких оголошень синонім імені може використовуватися як спецификатор типу:

COMPLEX ca, *pca; // змінна типу COMPLEX і покажчик на COMPLEXPINT pi; // покажчик на int

Приведений вище опис структур і об'єднань в основному відповідає їх побудові в мові Сі. У Ці++ структури і об'єднання є окремими випадками об'єктних типів даних. Додаткові відомості про це будуть приведені при розгляді об'єктно-орієнтованих коштів Сі++.

2.4 Операції і вираження

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

Як операнди у вираженні виступають ідентифікатори змінних, константи, і рядкові літерали, що є первинними виразами. Вираження, взяте в круглі дужки, також розглядається як первинне. Кожна операція передбачає використання певних типів операндів (цілих, речовинних, покажчиків). Операція привласнення в Сі++ також є вираженням, в зв'язку з цим розрізнюються операнди, яким можна привласнити нове значення і операнди, значення яких не може мінятися. Щоб операнду можна було привласнити значення, йому повинна відповідати область пам'яті і компілятору повинен бути відома адреса цієї пам'яті. Такі операнди називають L-виразами (від англійського left - лівий), оскільки вони можуть бути записані в лівій частині оператора привласнення.

Результат обчислення вираження залежить від пріоритетів операцій. У Сі++ складна система пріоритетів операцій, включаюча 16 рівнів. У таблиці 2.1 приведений перелік операцій Сі++ з вказівкою їх пріоритетів, призначення і схеми запису.

Таблиця 2.1

Пріоритет

Знак операції

Призначення

Схема

1:

:

Доступ до глобального імені або імені з іншої області:

: ідентифікатор (глобальний)

ім'я області: : имя_члена_структури

1

- >

Звернення до члена структури по покажчику на структуру

покажчик - > имя_члена_структури

1.

Звернення до члена структури на ім'я структури

имя_структури. имя_члена_структури

1

[ ]

Звернення до елемента масиву

покажчик [ індекс ]

1

()

Перетворення типу даного

имя_типа (вираження) або (тип) вираження

1

()

Виклик функції

функція (аргументи)

2

++

Автоувеліченіє

++ L-значення або

L-значення++

2

-

Автоуменьшение

- L-значення або

L

~

Бітове інвертування

~ целое_виражение

2

!

Логічне заперечення

! вираження

2

-

Одномісний мінус

- вираження

2

+

Одномісний плюс

+ вираження

2

&

Отримання адреси

& L-значення

2

*

Разименованіє покажчика

* покажчик

2

new

Виділення динамічної пам'яті

new тип даного

2

delete

Звільнення пам'яті

delete покажчик

2

delete []

Звільнення пам'яті для масиву

delete [] покажчик

2

sizeof

Розмір даного

sizeof вираження

2

Розмір типу даного

sizeof (ім'я типу)

3

*

Множення

вираження * вираження

3

/

Ділення

вираження / вираження

3

%

Залишок від ділення без остачі

вираження % вираження

4

- > *

Звернення до члена структури по покажчику

указатель_на_структуру - > * имя_члена_структури-покажчика

4.

*

Звернення до члена структури на ім'я структури

имя_структури. *

имя_члена_структури-покажчика

5

+

Складання

вираження + вираження

5

-

Віднімання

вираження - вираження

6

<виг вліво

целое_виражение < целое_виражение

6

> >

Зсув вправо

целое_виражение > > целое_виражение

7

<жение <

7

<ньше або одинаково

вираження < вираження

7

>

Більше

вираження > вираження

7

> =

Більше або одинаково

вираження > = вираження

8

==

Одинаково

вираження == вираження

8

!=

Не рівне

вираження != вираження

9

&

Поразрядная конъюнкция

вираження & вираження

10

^

Заперечення рівнозначності

вираження ^ вираження

11

¦

Поразрядная дизъюнкция

вираження ¦ вираження

12

&&

Логічне "И"

вираження && вираження

13

¦ ¦

Логічне "АБО"

вираження ¦ ¦ вираження

14?

:

Умовне вираження

вираження? виражение1: виражение2

15

=

Просте привласнення

вираження = вираження

15

@=

Составное привласнення, знак @ - один із знаків операцій * / % + - < < > > & ^ ¦

вираження @= вираження

16,

Операція проходження

вираження, вираження

Розглянемо особливості застосування основних з перерахованих вище операцій.

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

Для звернення до членів структури або об'єднання можна скористатися або ім'ям структурного даного, або покажчиком на структурне дане. У першому випадку повне ім'я члена структури складається з імені самої структури і імені члена структури, розділеного точкою. У другому випадку за ім'ям покажчика на структуру ставиться знак - > (стрілка), а за ним ім'я члена структури. Нехай в програмі оголошений структурний тип AnyStruct, вмісний компоненту з ім'ям member типу int і оголошені

AnyStruct s1; // Дане s1 типи AnyStruct

AnyStruct *ps1 = &s1; // Покажчик на дане типу AnyStruct

Тоді до члена структури member з s1 можна звернутися як до s1.member або як ps1- > member.

Оскільки членом структури може бути покажчик, в Сі++ є спеціальні операції разименования такого покажчика, операції. * і - >. Нехай одним з членів структури AnyStruct є покажчик pp1 на дане типу int. Тоді вираження s1.*pp1 і ps1- > *pp1 забезпечать доступ до значення даного, на яке вказує pp1 з s1.

Вище зазначалося, що ім'я масиву в Сі/Сі++ інтерпретується як покажчик-константа на перший елемент масиву. Для разименования покажчика, т. е. для доступу до даного по покажчику на це дане служить операція * (зірочка). Отже, якщо в програмі оголошений масив

int Array1 [ 10 ];

те вираження *Array1=0 служить для привласнення нульового значення першому елементу масиву. Щоб звернутися до довільного елемента масиву, треба указати індекс елемента, наприклад, Array1 [3]. Це вираження еквівалентне вираженню *(Array1 + 3), т. е. потрібно спочатку збільшити покажчик Array1 на 3 одиниці, а потім разименовать отриманий покажчик. При складанні покажчика на об'єкт деякого типу Т з цілим числом N значення покажчика збільшується на N, помножене на довжину даного типу T. Отметім, що індекс можна задавати не тільки для імен масивів, але і для будь-якого типу покажчика, крім покажчика на тип void:

int *pint = &Array[ 4 ]; pint [ 2 ] =1;

У цьому прикладі покажчик pint ініціалізований адресою п'ятого елемента масиву Array, а потім сьомому елементу цього масиву привласнене значення 1.

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

Оскільки Сі++ є типізованою мовою, в ньому визначені явні і неявні перетворення типів даних. Неявні перетворення виконуються при двуместних арифметичних операціях і операції привласнення і називаються стандартними арифметичними перетвореннями. Ці перетворення виконуються в наступній послідовності:

- якщо один операнд має тип long double, інший операнд перетворюється в тип long double;

- інакше, якщо один операнд має тип double, інший операнд перетворюється в тип double;

- інакше, якщо один операнд має тип float, інший операнд перетворюється в тип float;

- інакше, якщо один операнд має тип unsigned long int, інший операнд перетворюється в тип unsigned long int;

- інакше, якщо один операнд має тип long int, > інший операнд перетворюється в тип long int;

- інакше, виконуються стандартні перетворення для цілого, при цьому типи char, short int і бітові поля типу int перетворюються в тип int, потім, якщо один операнд має більший розмір (більший діапазон значень), ніж інший операнд, то другий операнд перетворюється до типу операнда більшого розміру;

- в інших випадках операнди мають тип int.

Явне перетворення типів може бути задане в двох формах. Перша форма сумісна з Сі, в ній за ім'ям типу в круглих дужках записується значення, що перетворюється, яке може бути первинним вираженням або вираженням з одномісною операцією. Ім'я типу в цьому випадку може бути представлене послідовністю описувачів, наприклад, (long int *) pp определеяет перетворення деякого даного pp в тип покажчика на long int. Друга форма перетворення типу записується як виклик функції, при цьому ім'я типу повинно задаватися ідентифікатором, наприклад, int (х). Потрібно відмітити, що результат явного перетворення не є L-значенням.

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

++х * 2 + у- *3

змінна х спочатку збільшується на 1, а потім множиться на 2, змінна у спочатку множиться на 3, потім меншає на 1.)( Якщо перед обчисленням цього вираження х і у були рівні 1, то результат вираження буде рівний 5, крім того змінна х набуде значення 2, а змінна у - значення 0.)( Таким чином, операції автоувеличения і автоуменьшения завжди дають побічний ефект, змінюють значення своїх операндів.)( Операнди цих операцій повинні бути L-значеннями.)(

Операція ~ (тильда) застосовується тільки до цілого значення і замінює всі біти свого операнда зі значенням 0 на 1, а біти зі значенням 1 на 0.)(

Логічне заперечення (операція !) повертає значення 0 цілого типу, якщо операнд не рівний нулю, або значення 1, якщо операнд рівний нулю.)(

Операції "одномісний +" і "одномісний -" мають звичайне математичне значення, знак + не змінює значення операнда, знак - міняє знак операнда на протилежний.)(

Для отримання адреси операнда, що є L-значенням, застосовується операція & (амперсанд).)( Результатом цієї операції буде покажчик на відповідний тип даного.)( Разименование покажчика, т.)( е.)( отримання значення даного по покажчику на нього забезпечується операцією) * (зірочка). Результат операції разименования є L-значенням.

У Сі++ визначені операції розміщення даних в динамічній пам'яті і видалення динамічних даних з пам'яті.

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

int *ip = new int; /* створення об'єкта типу int і отримання покажчика на нього */int *ip2 = new int(2); // те ж з установкою початкового значення 2inr *intArray = new int [ 10 ]; // масив з 10 елементів типу intdouble **matr = new double [ m ] [ n ]; // матриця з m рядків і n стовпців

Дане, розміщене в динамічній пам'яті операцією new, видаляється з пам'яті операцією delete з операндом-покажчиком, значення якого отримане операцією new, наприклад,

delete intArray; delete ip2;

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

Розмір даного або типу даного в байтах можна отримати по операції sizeof. Операнд може бути будь-якого типу, крім типу функції і бітового поля. Якщо операндом є ім'я типу, воно повинно братися в дужки. Значення, що Повертається має приречений тип size_t, це цілий тип, розмір якого визначається реалізацією компілятора, звичайно типу size_t відповідає unsigned int. Розмір масиву рівний числу байт, займаних масивом в пам'яті, розмір рядкового літерала - це число знаків в літералі +1, т. е. завершальний нульовий байт враховується при визначенні довжини літерала. Значення, те, що повертається sizeof є константою.

Двуместние арифметичні операції множення (*), ділення (/), отримання залишку від ділення без остачі (%), складання (+) і віднімання (-) мають звичайне значення і звичайний відносний пріоритет. Якщо операнди арифметичної операції мають різні типи, заздалегідь виконуються стандартні арифметичні перетворення і тип результату операції визначається загальним типом операндів після стандартних перетворень. Отже, вираження 7/2 буде мати значення 3 типу int, оскільки обидва опернда мають тип int, а вираження 7.0/2 дасть результат 3.5 типу double, оскільки цей тип має перший операнд.

Операції відношення двох виразів ( <, < =, >, > =) вимагають операндів арифметичного типу або ж обидва операнди повинні бути покажчиками на однаковий тип. У разі операндів арифметичного типу обчислюються значення операндів, виконуються стандартні арифметичні перетворення і повертається 1 типи int, якщо відношення виконується (істинно), або 0, якщо відношення не виконується (помилково). Коли порівнюються два покажчики, результат залежить від відносного розміщення в пам'яті об'єктів, на які посилаються покажчики. Операції порівняння (== і !=) виконуються аналогічним образом, але мають менший пріоритет.

Вирази відносин можуть сполучатися логічними зв'язками && (конъюнкция, логічне множення) і ¦ ¦ (дизъюнкция, логічне складання). У загальному випадку операндами логічних зв'язок можуть бути будь-які скалярні значення і операцію && дає реззультат, рівний 1 типи int, якщо обидва операнди мають ненульові значення, а операція ¦ ¦ дає результат, рівну 0, якщо значення обох операндів нульові. Застосовується скорочена форма обчислення значення логічних зв'язок, якщо в операції && перший операнд рівний нулю, то другий операнд не обчислюється і повертається 0, якщо в операції ¦ ¦ перший операнд не рівний нулю, то другий операнд не обчислюється і повертається значення 1.

Як вже відмічалося, привласнення, що означається знаком = в Сі/Сі++ розглядається як операція і повертає значення, яке було привласнене лівому операнду. Операція привласнення обчислюється праворуч наліво, т. е. спочатку обчислюється значення, що привласнюється, потім виконується привласнення. Це дозволяє записувати вирази вигляду х = у = z = 1 для установки однакових значень декільком змінним. Можна, хоч це і знижує наглядність програми, будувати і вираження з побічним ефектом вигляду (х = 2) * (у = 3) + (z = 4). Результатом цього вираження буде 24, але одночасне змінні х, у і z набудуть нових значень.

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

Для цілих операндів визначені операції зсуву вліво і вправо. При виконанні операції e1 < < e2 біти першого операнда зсуваються вліво на e1 розрядів і результат має тип першого операнда. Праві розряди, що Звільняються заповнюються нулями. При зсуві вправо (e1 > > e2) якщо e1 має тип unsigned, що звільняються ліві розряди заповнюються нулями, а при e1 типи signed в лівих розрядах, що звільняються повторюється знаковий розряд.

Над цілими операндами допустимі операції поразрядного логічного множення, логічного складання і що виключає або (заперечення рівнозначності). У цих операціях операнди розглядаються як послідовності бітів і операція виконується над кожною парою відповідних розрядів з обох операндів. Наприклад, результатом вираження (х > > (р - n +1)) & (~(~0 < < n)) буде виділення з цілого беззнакового х n бітів, починаючи з біта з номером р, і зсув виділених бітів вправо, т. е. виділення n-розрядного цілого, того, що зберігається в машинному слові х починаючи з р-го розряду.

У Сі/Сі++ є конструкція, яка називається умовним вираженням. Умовне вираження будується по схемі:

умова? виражение1: виражение2

Як умова може виступати будь-яке скалярне вираження. Якщо результат обчислення умови ненульовий, то значенням всього вираження буде виражение1, при нульовому значенні умови значення всього вираження визначається виражением2. Другий і третій операнди умовного вираження повинні бути або обидва арифметичних типи, або однотипними структурами або об'єднаннями, або покажчиками однакового типу, або один з них - покажчик на який-небудь тип, а інший операнд NULL або має тип void*. Вираження х > 0? 1: 0 повертає 1, якщо х більше 0, і 0 в іншому випадку.

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

х = 2, е * 3, х +1 буде отримане значення 3 і попутно х набуде значення 2. Результат множення е * 3 ніяк не може бути використаний.

2.5 Оператори Ці++

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

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

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

х = 3; у = (х +1) * t; i++;

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

Оператори вибору в Сі/Сі++ представлені умовним оператором і перемикачем. Умовний оператор аналогічний умовним операторам інших мов програмування і може використовуватися в скороченій і повній формах, яким відповідають схеми:

if (вираження-умова) оператор

if (вираження-умова) оператор-1 else оператор-2

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

У повній формі умовного оператора при ненульовому значенні вираження-умови виконується оператор-1 з подальшим переходом до наступного оператора програми, а при нульовому значенні вираження умови виконується оператор-2 з переходом до наступного оператора програми.

Перемикач дозволяє вибрати одну з декількох можливих гілок висислений і будується по схемі:

switch (ціле вираження) оператор.

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

{case константа-1: оператори

case константа-2: оператори

default: оператори

};

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

switch (count){case 1: х=1;case 2: х=2;case 3: х=3;default: х=4;};

якщо значення count дорівнює 1, то після переходу на case 1 будуть виконані всі оператори, в результаті х стане рівним 4. Щоб розділити гілки перемикача, в кінці кожної гілки треба записати оператор break, що не має операндів. По цьому оператору відбувається вихід з перемикача до наступного оператора програми:

switch (count){case 1: х = 1; break;case 2: х = 2; break;case 3: х = 3; break;default: х = 4;};

Тепер в залежності від значення count буде виконуватися тільки одна гілка перемикача і х буде приймати одне з чотирьох передбачених значень.

У Сі/Сі++ є три варіанти оператора циклу: цикл з предусловием, цикл з постусловием і цикл з параметром.

Цикл з предусловием будується по схемі

while (вираження-умова) оператор.

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

do оператор while (вираження-умова).

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

Цикл з параметром будується по схемі:

for (E1; E2; E3) оператор

де E1, E2 і E3 - вирази скалярного типу. Цикл з параметром реалізовується по наступному алгоритму:

1. Обчислюється вираження E1. Звичайно це вираження виконує підготовку на початок циклу.

2. Обчислюється вираження E2 і якщо воно дорівнює нулю виконується перехід до наступного оператора програми (вихід з циклу). Якщо E2 не дорівнює нулю, виконується крок 3.

3. Виконується оператор - тіло циклу.

4. Обчислюється вираження E3 - виконується підготовка до повторення циклу, після чого знов виконується крок 2.

Нехай потрібно підрахувати суму елементів деякого масиву з n елементів.

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

int s=0;int i=0;while (i < n) s +=a[ i ++];

Ця ж задача із застосуванням циклу з постусловием вирішується наступними операторами:

int s = 0;int i = 0;do s +=a[ i++]; while (i < n);

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

int i, s;for (s = 0, i = 0; i < n; i++) s +=a[ i ];

Оголошення змінних можна внести у вираження E1 оператора for і все записати у вигляді одного оператора for з пустим тілом циклу:

for (int i = 0, s = 0; i < n; s += а [i++]);

Для переривання повторень оператора циклу будь-якого типу в тілі циклу може бути використаний оператор break. Для переходу до наступного повторення циклу з будь-якого місця тіла циклу може бути застосований оператор continue. Ці оператори по своєму назаначению аналогічні відповідним операторам мови Паськаль.

Незважаючи на те, що Сі++ містять повний набір операторів для структурного програмування, в нього все ж включений оператор переходу:

goto влучна;

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

2.6 Функції

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

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

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

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

Функція, що повертає середнє арифметичне трьох речовинних даних, може бути описана так:

double sred (double х, double у, double z){ double s;s = х + у + z;return s / 3;};

Для виклику такої функції при умові, що заздалегідь оголошені змінні р, a, b, і з, можна записати оператор:

р = sred (a, b, з);

Очевидно, що функція повинна бути описана до того, як зустрінеться її перший виклик. Це не завжди можливе, наприклад, коли дві функції викликають один одну. Коли програма складається з декількох файлів, повний опис функції повинно бути присутній тільки в одному файлі, але виклики функції можливі з різних файлів програми. Щоб дозволити подібні протиріччя передбачені дві форми опису функцій, повна форма, звана також визначенням функції, і скорочена, звана описом прототипу функції або просто прототипом. Прототип функції містить тільки заголовок функції і задає таким чином ім'я функції, тип значення, що повертається і типи параметрів. По цій інформації при компіляції програмного файла можна перевірити правильність запису виклику функції і використання значення, що повертається. У Сі++ потрібно, щоб виклику будь-якої функції передувало в тому ж файлі або повне визначення функції або опис її прототипу.

Потрібно відмітити ряд додаткових можливостей опису функцій в Сі++:

- При описі прототипу функції можна не вказувати імена параметрів, досить указати їх типи.

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

double sred (double х, double у, double z = 0){ double s;s = х + у + z;return s / 3;};

До такої функції можна звертатися з двома і з трьома аргументами.

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

int varfunc (int n,. ..);

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

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

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

double sred (int х, int у, int z = 0){int s;s = х + у + z;return s / 3;};

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

inline int max (int x1, int x2){return x1 > x2? x1: x2 }

В системах програмування Turbo З++ і Borland З++ головна функція (функція main) може приймати три параметри, що дозволяє викликати Сі-програми з командного рядка DOS з передачею в програму необхідних аргументів. Стандартний прототип функції main має вигляд:

int main (int argc, char *argv[ ], char *envp[ ])

В конкретній програмі можна оголошувати функцію main без значення (що повертає тип void), що повертається, з використанням тільки двох перших параметрів або взагалі без параметрів. Параметри argc і argv служать для передачі в програму аргументів у вигляді масиву рядків, argc містить число елементів цього масиву, а argv - це масив покажчиків на елементи масиву, причому перший елемент масиву, на який вказує argv [0], містить ім'я програми (ім'я ехе-файла програми), інші елементи являють собою аргументи з командного рядка DOS. Параметр envp використовується для доступу до елементів поточної середи DOS.

2.7 Бібліотека часу виконання

В визначенні мов Сі і Сі++ відсутні оператори введення-виведення, над рядковими даними і багато які інші кошти, що є в інших мовах програмування. Цей недолік компенсується додаванням в системи програмування Сі і Сі++ бібліотек функцій, що підключаються до робочих програм при редагуванні зв'язків і званих бібліотеками часу виконання. Відділення цих бібліотек від компілятора дозволяє в необхідних випадках використати різні варіанти цих бібліотек, наприклад, для різних моделей ЕОМ або операційних систем.

Частина функцій з бібліотек часу виконання стандартизована, в стандарті зафіксовані ім'я функції, її призначення, перелік і типи параметрів і тип значення, що повертається. Інші функції орієнтовані на конкретні моделі ЕОМ і операційні системи, способи їх виклику і використання можуть бути різними в системах програмування різних фірм.

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

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

Стандартом Сі визначені наступні файли заголовків:

ASSERT.H - Містить макроси для повідомлень про помилки при виконанні умови, що задається програмістом.

CTYPE.H - Функції для перевірки і перетворення даних типу char.

FLOAT.H - Макроси для операцій над числами з плаваючою точкою.

LIMITS.H - Макроси, задаючі діапазони представлення цілого.

LOCALE.H - Представлення дати, часу, грошових одиниць.

MATH.H - Пакет стандартних математичних функцій.

SETJUMP.H - Імена типів і функції для реалізації операторів переходу, використовується рідко.

SIGNAL.H - Макроси для сигналізації про помилки згідно з стандартом ANSI.

STDARG.H - Макроси для виклику функцій із змінним числом аргументів.

STDDEF.H - Визначення загальних типів для покажчиків, типів size_t і NULL.

STDIO.H - Стандартні функції введення-висновку.

STDLIB.H - Визначення загальних типів, змінних і функцій.

STRING.H - Функції для операцій над рядковими даними.

TIME.H - Структури і функції для операцій з датами і часом.

У Сі++ додані операції з комплексними числами і десятеричними даними:

BCD.H - Дані, представлені в десятеричній системі числення

COMPLEX.H - Функції і операції над комплексними числами.

Є також файли прототипів функцій для розподілу і звільнення динамічної пам'яті, використання коштів DOS і BIOS.

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

# include < ім'я файла >

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

< PRE >

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

stdin - стандартне введення,

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

stderr - для виведення про помилки,

stdprn - стандартний пристрій друку,

stdaux - стандартний послідовний порт.

Потоки stdin, stdout і stderr звичайно зв'язуються з консоллю, але можуть бути перепризначувані на інші пристрої. Призначення двох останніх потоків залежить від апаратури, що використовується. Стандартні потоки автоматично відкриваються при запуску Сі-програми і закриваються при її завершенні. Потоки, що створюються програмістом, відкриваються функцією fopen і закриваються функцією fclose.

Функції введення-висновку з stdio.h умовно можна розбити на чотири групи: введення-виведення, введення-виведення, форматний введення-висновок і так званий прямий (бесформатний) введення-висновок. Тут відмітимо тільки окремих представників перших трьох груп, призначених для введення з потоку stdin і висновку в потік stdout.

Функція int getchar() служить для введення одного символа з клавіатури і повертає код символа, перетворений до типу int. Функція int putchar (int з) виводить символ з в чергову позицію на екрані монітора.

Для введення рядка з клавіатури служить функци char * gets (char * buf), яка читає введення з клавіатури (до символа нового рядка або натиснення клавіші Enter) і вміщує коди прочитаних символів в буфер, адреса якого задається параметром buf, в кінці рядка додається нульовий байт. Виведення виконує функци int puts (char * string), яка виводить рядок за адресою string на екран, поки в рядку не зустрінеться нульовий байт і повертає код останнього виведеного символа.

Функції форматного введення-висновку приймають як параметри рядок з описом формату представлення даних на зовнішньому пристрої і список або даних, що виводяться, що вводяться. Рядок опису формату складається із звичайних символів, керуючих символів типу нового рядка, повернення каретки і т. п. і специфікацій полів введення або висновку. Кожна така специфікація починається символом % (відсоток) за яким слідують коди прапорів, розмір поля введення або висновку, число цифр в дробовій частині числа, префікса розміру даного і коду типу формату. Обов'язково вказувати тільки тип формату, інші компоненти специфікації формату задаються з потреби. Відмітимо деякі коди типу формату:

d - для представлення цілого зі знаком в десятеричній системі числення,

i - для представлення цілого без знака в десятеричній системі числення,

f - для представлення числа з плаваючою точкою в природній формі,

е або Е - представлення числа з плаваючою точкою в експонентній формі,

s - введення-виведення рядкових,

з - введення-виведення.

Для форматного висновку служить функція int printf (char *format,. ..), що має список параметрів змінної довжини, кількість додаткових параметрів повинно відповідати числу специфікацій формату в форматной рядку, дані для висновку можуть задаватися виразами, відповідальність за правильне завдання специфікації формату для кожного даного, що виводиться повністю лежить на програмістові. Приклад застосування функції printf:

printf ( \n "х = %d, у = %f %s", х, у, st);

При виконанні цієї функції переглядається рядок формату зліва направо і символи що не є специфікаціями формату копіюються на вивідний пристрій, керуючий символ \n переводить курсор на екрані на початок наступного рядка, коли зустрічається специфікація формату, вибирається черговий аргумент з списку висновку, перетворюється у відповідно до формату і виводиться в чергову позицію екрана. Для правильного висновку потрібно, щоб змінна х була типу int, у - типу float, а змінна st - типу char*.

Форматний введення виконує функція int scanf (char *format,. ..) в якій список введення повинен задавати покажчики на змінні, що вводяться. Якщо в рядку формату присутні символи, не вхідні в специфікації форматів і що не є пропусковий, то у вхідному потоку повинні бути присутній ті ж символи. Пропусковий символами вважаються знаки пропуску, табуляції, нового рядка, вони прочитуються з потоку введення, але не беруть участь в формуванні вхідних даних. Коли в форматной рядку зустрічається специфікація формату, у вхідному потоку проаускаются пропусковий символи, а подальші символи інтерпретуються відповідно до типу формату, перетворюються у внутрішнє уявлення і отримане значення записується в пам'ять за адресою чергового елемента списку введення. Наприклад, для введення двох змінних цілого типу і однієї речовинного типу можна застосувати оператора виклику функції

scanf ( %d %d %f, &"x1, &x2, &у);

Тут x1 і x2 повинні бути типу int, а у - типу float. У вхідному потоку значення, що вводяться повинні розділятися хоч би одним пропуском.

Більш повну інформацію про функції введення-висновку в стилі Сі можна отримати в довідковій системі інтегрованої середи Borland З++.

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

cin - для введення даних,

cout - для виведення,

cerr - виведення про помилки без буферизації висновку,

clog - виведення про помилки з буферизацией висновку.

Як знак операції висновку визначені знаки < <, а знаком операції введення - знаки > >, ті ж, що і для операцій зсуву. Компілятор по контексту визначає, яку операцію задають ці символи, введення-висновок або зсув.

Щоб використати кошти введення-виведення ++в програму повинен бути включений файл-заголовок iostream.h:

# include < iostream.h >

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

"cout < < x1 = " < < x1 < < " x2 = " < < x2 < < \n";

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

У операції введення лівим операндом повинен бути потік введення, а правим операндом - ім'я даного, що вводиться для арифметичних даних або покажчик типу char* для введення рядків, наприклад,

cin > > x1 > > x2 > > st;

Операції введення-висновку виконуються зліва направо і останній оператор еквівалентний оператору (cin > > x1)( > > x2) > > st; або трьом операторам

cin > > x1; cin > > x2; cin > > st;

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

# include < iostream.h > int х, у; "int main (){cout < < х = "; cin > > х; // Запит і введення значення "xcout < < \n у = "; cin > > у; // Запит і введення значення "ycout < < \n" < < " х + у = " < < х + у;return 0;}.