Елементи програмування мовою Сі

      Повернутись в головне меню

        

·        Вступ

·        Основнi поняття

·        Константи та змiннi у Сі

·        Вирази, операції, стандартні функції

·        Задання значень змінних, оператор присвоєння

·        Виведення значень на екран дисплею

·        Структури вибору

·        Цикли (команди повторення)

·        Логічні  вирази у Сі

·        Структурні типи і структури

·        Об'єднання, бітові поля. Двійкова і шістнадцяткова системи числення

·        Операції із комплексними змінними у Сі++

·             Функції у Сі

·       Функції роботи з графікою у Сі

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

·        Робота з файлами в Сі. Стандартні файли

·        Додавання до тексту програми текстів із файлів

·        Основні етапи створення і виконання  програм на ЕОМ

·        Основи ООП у С++

·        Додатки

 

 

 

 

 

Вступ

Мову програмування Сі створив Денісом Ритчі (Dennis Ritshie) з компанії AT&T Bell Labs у 1970 р. Основна мета

автора полягала у створенні простої і ефективної мови програмування, яка дає змогу розширювати свої можливості

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

іншими мовами програмування ( Паскаль, Фортран тощо). Показником ефективності мови Сі може бути

співвідношення між розміром тексту програми, записаної мовою Сі, та розміром відтрансльованого

(перекладеного у машинні команди) модуля — близько 1/2. Унаслідок цього Сі забезпечує високу швидкодію

виконуваних модулів. Розширення Сі  засобами об’єктно-орієнтованого програмування (Б.Старуструп) відоме

під назвою С++.

 

 

       Основнi поняття

Мова програмування Сі є знаковою, тобто всi вирази i конструкції мови складаються зі знакiв, якi містить  алфавiт Сі. Алфавiт

Сі охоплює:

     букви латинського алфавiту — A, B, C, D, E, F...Z, a, b, c, d, e, f, …z;

     десяткові цифри — 0, 1, 2, 3, 4, 5, 6, 7, 8, 9;

     спеціальні символи .  , “ [ ] ( ) { } + - / % \ ; : ? < = > ~ ^ &  *  #  , символ прогалини тощо.

         Із символів складаються базові елементи мови — лексеми. У Сі є шість типів лексем:

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

ключові слова;

         константи;

         рядки;

         роздільники;

         знаки операцій.

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

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

 конструкцій мови, називають ключовими словами:

позначення типів данихchar, int, float, double, union, long, short, unsigned, enum, typedef, struct, void;

позначення класів памятіauto, extern, static, register;

модифікатори видимості private, protected, public;

позначення операторів та їх складових частинbreak case continue default do else for goto if return switch while.

         Ключові слова

 

asm

auto

const cast

default

delete

do

dynamic_cast

explicit

export

for

friend

if

inline

int

mutable

namespace

new

operator

register

reinterpret_cast

static cast

template

try

typedef

typeid

typename

using

volatile

wchar t

 

 

 

Загальну структуру програми мовою Сі можна зобразити так:

 

 # include <stdio.h>

 .

 .

 .

 # include <ім’я бібліотечного файла>

 void main()

 /* службове слово void перед  main  означає, що програма не передає значень*/

 

 { /* аналог службового слова Паскалю Begin */

  описи змінних;

  виконувані оператори(команди);

  } /* аналог службового слова Паскалю End. */

 

         Конструкція типу /* пояснювальний текст */ є коментарем.  Змінні описують до їхнього використання, найкраще

 це робити на початку програми.

 

 

       Константи та змiннi у Сі

Арифметичнi вирази у Сі, як i в математицi, складаються з чисел (констант), iмен змiнних, імен функцій, знакiв

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

 десятковою крапкою (цілі константи записують без дробової частини). Кiлькiсть цифр у числi не бiльше  12.

Наприклад:

         -7.58

         10345.7563

         0.0000347

     Дiапазон  чисел,  якi можна записати у такий спосіб, невеликий — вiд 0.00000000001 до 999999999999.

Для розширення дiапазону чисел  у  Сі  використовують  форму запису чисел з плаваючою крапкою:

  знак(+або-)числоEзнак (+ або -)число.

         Наприклад:

         34.578E23що означає 34.578 * 1023                            

         2.1268E-19що означає 34.578 * 10-19                                         

         -7.4588E21що означає -7.4588 * 1021

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

 та іменами функцій.

         Виконуючи обчислення на ЕОМ, ми можемо мати справу з рiзними числовими значеннями.

Довжина числа (кiлькiсть знакiв у числi) впливає на  розмiр  областi пам’ятi, необхiдний для зберiгання цього числового

 значення. У Сі передбачено такі базові типи змінних:  

 

Тип

Імя типу

Розмір(байт)

Діапазон значень

Цілі

int

2 або 4

дивалі

short int

2

від -32768 до 32767

long int

4

від -2 147 483 648 до  2 147 483 647

Беззнакові цілі

unsigned int

2 або 4

дивалі

unsigned short

2

від 0 до 65535

unsigned long

4

від 0 до 4 294 967 295

unsigned char

1

від 0 до 255

         Дійсні(плаваючі)

float

4

3.14*10-383.14*1038

double        (long float)

8

1.7*10-3081.7*10308

Символьні

char

1

від -128 до 127

Логічні

bool

1

true, false

 

         Кількість байтів, які відводять під цілі змінні, залежить від довжини машинного

слова (визначається мікропроцесором, який встановлений у системному блоці). Для визначення розміру у

байтах цілої змінної можна скористатись функцією sizeof, наприклад

            a = sizeof(int);

            b = sizeof(long int);

            c = sizeof(unsigned long);

            d = sizeof(short);

 

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

 

       float x,y;   int i;    char v;                           

 

         Крім скалярних змінних (з одним значенням) у Сі можна використовувати масиви (індексовані змінні), які дають

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

            int a[2][3]; /* ціла матриця з двох рядків і трьох стовпців */

            double b[10]; /* вектор з 10 елементів типу  double */

                 int w[3][3] = { { 2, 3, 4 },

                                                 { 3, 4, 8 },

                                     { 1, 0, 9 } };

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

 

Конструкція enum

       enum [<ім’я множини>] { <назва константи> [=<значення>] } [список змінних]

                   ,   де

                            м’я множини> - опціональне ім’я множини

                            <назва константи> - ім’я елементу множини якому можна присвоїти певне цілочисельне значення

                <значення> - змінна типу int

Вирази, операції, стандартні функції

 

Вирази описують процеси породження значень застосуванням операцій над іншими

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

арифметичні;

         відношення;

         логічні;

         присвоювання.

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

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

 в операції, їх (операції) поділяють на унарні, бінарні і тернарні.

         Унарні операції:

         - зміна знаку;

         ~ побітове логічне заперечення (доповнення);

         ! логічне заперечення;

         * розадресація (непряма адресація);

         & обчислення адреси;

         + унарний плюс;

         ++ збільшення (інкремент);

         -- зменшення (декремент);

         sizeof розмір .

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

операнда на одиницю. Їх можна  записати як  справа, так і зліва від операнда. Якщо знак операції

розміщений перед операндом (префіксна форма), то зміна операнда відбувається до його використання

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

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

         префіксна форма                  постфіксна форма

         int i,j;                            int i,j;

         i=1;                     i=1;

         j=++i;                          j=i++;       

тут i=2,j=2                   тут i=2,j=1(спочатку використано значення  i=1, післо чого виконано збільшення значення i на 1).

Бінарні операції поділяють на:

арифметичні операції

      + додавання

      - віднімання

      * множення

      / ділення

      % залишок при діленні цілих чисел

         логічні операції

                   !        заперечення

¦¦    логічне “або”

&&     логічне  “і”

¦        побітове  “або”

&        побітове “і”

 

         операції відношення

         <       менше

                   >       більше

         ==    дорівнює

                   !=      не дорівнює

         <=    менше або дорівнює

         >=    більше або дорівнює

         Бінарні операції виконуються  зліва направо з урахуванням пріоритету виконання операцій. 

Пріоритет виконання арифметичних операцій такий самий, як в алгебрі (лише до операцій множення

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

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

обраховуються у першу чергу. Варто зауважити, що зайві дужки, наприклад a+(18*x+12*y),

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

типами операндів у виразі.

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

         (x+5/(z-3*sin(q-2.4))арифметичний вираз;

         x*x+y*y<=1                — вираз відношення.

         Тернарна операція (лише одна) має вигляд:

         Змінна = вираз1 ? вираз2: вираз3;

Виконання цієї операції можна задати алгоритмом:

ЯКЩО вираз1 =0  ТО змінна=вираз2 ІНАКШЕ змінна=вираз3.

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

 /* визначення більшого з двох значень (a b) і присвоєння його змінній max*/

         max=(a<=b)? b:a;

         Для вирахування числових значень елементарних функцiй у програмах, записаних мовою Сі,

потрібно під’єднати бібліотечний файл із програмами обчислення цих функцій

( у заголовку програми вставити рядок # include <math.h>

[для операцій з комплексними значеннями # include <complex.h>]). Розглянемо ці функції:

         абсолютне значення

         abs             для цілих значень

         fabs, fabsl  — для дійсних значень

         cabs, cabsl для комплексних значень

         labs            — для дійсних значень

         округлення значень

         ceil, ceill     — найближче ціле, але не менше аргумента функції

         floor, floorlнайближче ціле, але не більше аргумента функції

         тригонометричні функції (аргумент задається у радіанах!)

         sin, sinl       синус

         cos, cosl     косинус

         tan, tanl     — тангенс   

          зворотні тригонометричні функції

         asin, asinl            — арксинус

         acos, acosl           — арккосинус

         atan, atanl          — арктангенс

         atan2(x,y), atan2l        — арктангенс відношення x/y

         гіперболічні функції

         sinh, sinhl   — гіперболічний синус {sinh(x) =(exp(x)-exp(-x))/2}

         cohs, coshl — гіперболічний косинус {cosh(x) =(exp(x)+exp(-x))/2}

         tanh, tanhl — гіперболічний тангенс {tanh(x) =sinh(x)/cosh(x)} 

          зворотні гіперболічні функції

         asinh, asinl — арксинус гіперболічний

         acos, acosl — арккосинус гіперболічний

         atan, atanl — арктангенс гіперболічний

         показникові і логарифмічні функції

         exp, expl    — експонента { для комплексного аргумента exp(z) =  exp(Rez)*(cos(Imz)+jsin(Imz)),

тут Rez — дійсна частина комплексного значення, Imz — уявна частина комплексного значення}

         log, logl      — натуральний логарифм

         log10,log10l        — десятковий логарифм

pow10(p), pow10l 10**p

pow(x,y), powl x**y

sqrt,sqrtl    — корінь квадратний

 

 

Задання значень змінних, оператор присвоєння

 

Основним   способом  задання значень змiнних є оператор присвоєння, який можна записати так:

 

         ім’я змiнної= вираз;

 

     Наприклад

 

         w= (x-y)/(z+5);

         sq= f+(r+s)/(d+7);

         d=sqrt(sqr(a)+sqr(b));

         day=”понедiлок”;

         q=’y;

 

         Оператор присвоєння

         x=x*0.2;

         можна  прочитати так:

змiннiй х надається (присвоюється) значення рiвне добутку попереднього значення х на 0.2.

     Тепер   ми   взнали  досить  для  того,  щоб  написати першу програму мовою Сі. Напишемо програму

вирахування значення функції:

         y = 5sin(x-3)+v(z+7)

при x=5.9, z=2476.89. Для порівняння зліва розмістимо текст аналогічної Паскаль-програми

 

    Program one;                     # include <stdio.h>

    Var x,y,z:Real;                            void main() {

      Begin                                float  x,y,z;

        x:=5.9;                                    x=5.9;

        z:=2476.89;                   z=2476.89;

        y:=5*sin(x-3)+sqrt(z+7);       y=5*sin(x-3)+sqrt(z+7);

      End.                                  }

 

         Окрім команди присвоєння типу

                iмя змiнної= вираз;

в Сі можливі ще й такі форми операторів присвоєння:

         zm+= вираз; що означає «нове значення zm =старе значення zm+вираз

         zm-= вираз; що означає «нове значення zm =старе значення zm-вираз

         zm*= вираз; що означає «нове значення zm =старе значення zm*вираз

         Наприклад

         x+=0.2; /*нове значення x рівне попередньому значенню x +0.2 */

         x-=0.2; /*нове значення x рівне попередньому значенню x -0.2 */

         x*=0.2; /*нове значення x рівне попередньому значенню x *0.2 */

         x/=0.2; /*нове значення x рівне попередньому значенню x /0.2 */    

            double  a[4]={ 2.0, 3.3, 5.2, 7.5 } ;

            double  b=3.0;

            b+=a[2];      /*  еквівалентно   b=b+a[2] тобто b=3.0+3.3 */

            a[3]/=b+1;    /*  еквівалентно   a[3]=a[3]/(b+1)   */

 

Виведення значень на екран дисплею

Основним   способом  задання значень змiнних є оператор присвоєння, який можна записати так:

 

         ім’я змiнної= вираз;

 

     Наприклад

 

         w= (x-y)/(z+5);

         sq= f+(r+s)/(d+7);

         d=sqrt(sqr(a)+sqr(b));

         day=”понедiлок”;

         q=’y;

 

         Оператор присвоєння

         x=x*0.2;

         можна  прочитати так:

змiннiй х надається (присвоюється) значення рiвне добутку попереднього значення х на 0.2.

     Тепер   ми   взнали  досить  для  того,  щоб  написати першу програму мовою Сі. Напишемо програму

вирахування значення функції:

         y = 5sin(x-3)+v(z+7)

при x=5.9, z=2476.89. Для порівняння зліва розмістимо текст аналогічної Паскаль-програми

 

    Program one;                     # include <stdio.h>

    Var x,y,z:Real;                            void main() {

      Begin                                float  x,y,z;

        x:=5.9;                                    x=5.9;

        z:=2476.89;                   z=2476.89;

        y:=5*sin(x-3)+sqrt(z+7);       y=5*sin(x-3)+sqrt(z+7);

      End.                                  }

 

         Окрім команди присвоєння типу

                iмя змiнної= вираз;

в Сі можливі ще й такі форми операторів присвоєння:

         zm+= вираз; що означає «нове значення zm =старе значення zm+вираз

         zm-= вираз; що означає «нове значення zm =старе значення zm-вираз

         zm*= вираз; що означає «нове значення zm =старе значення zm*вираз

         Наприклад

         x+=0.2; /*нове значення x рівне попередньому значенню x +0.2 */

         x-=0.2; /*нове значення x рівне попередньому значенню x -0.2 */

         x*=0.2; /*нове значення x рівне попередньому значенню x *0.2 */

         x/=0.2; /*нове значення x рівне попередньому значенню x /0.2 */    

            double  a[4]={ 2.0, 3.3, 5.2, 7.5 } ;

            double  b=3.0;

            b+=a[2];      /*  еквівалентно   b=b+a[2] тобто b=3.0+3.3 */

            a[3]/=b+1;    /*  еквівалентно   a[3]=a[3]/(b+1)   */

 

 

Цикли (команди повторення)

 

Сі має три форми команди циклу:

         цикл з попередньою умовою

         while (логічний вираз)

         {тiло циклу

         };

         Якщо логічний вираз істинний (значення 1), то команди, які входять у тіло циклу, виконуються.

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

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

         a=-5;

         b=5;

         x=a;

         while (x<=b)

         {

         y=sin(x);

         printf(“ x= %f y= %f \n”,x,y);

         x=+0.2;

         }

         У цьому циклі послідовно обчислюється значення функції sin(x) для значень аргумента

з ряду -5, -4.8, -4.6 …5. Виконання циклу припиняється, як тільки значення x стане

більшим 5 (логічний вираз x<=b стане хибним).

 

         цикл з післяумовою:

         do

         {тiло циклу

}

while (логічний вираз);

 

         Команди, які входять у тіло циклу, виконуватимуться щонайменше один раз. Далі,

якщо логічний вираз істинний (значення 1), то команди, які входять у тіло циклу, виконаються

ще раз. Коли ж логічний вираз хибний (значення 0), то виконання циклу припиняється. Запишемо

попередній приклад з використанням циклу do  - while :

a=-5;

         b=5;

         x=a;

         do

         {

         y=sin(x);

         printf(“ x= %f y= %f \n”,x,y);

         x=+0.2;

         }

         while (x<=b);

 

         Правила  запису  логічних виразів у Сі розглянемо далі. Зараз розглянемо,  що означає

термiн "тiло  циклу".  Тiлом  циклу  може  бути будь-який виконуваний оператор Сі, або їхня  сукупнiсть.

         Ще одна форма команди циклу  має вигляд:

         параметричний цикл

         For (вираз1; умова; вираз2)

         { тіло циклу};

         вираз1 визначає дії, які проводяться до виконання циклу (тут може бути кілька виразів,

розділених комами), умова задає умови продовження виконання циклу (умова істинна —

цикл продовжується, хибна — виконання циклу припиняється), вираз2 задає метод зміни

параметрів та змінних циклу. Розглянемо приклад:

         arg=-5;

         n=20;

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

         {

y[i]=sin(arg);

x[i]= arg;

         arg=+0.05;

         }

         У цьому прикладі змінна циклу і перед виконанням циклу набуває значення 1.

Цикл виконується, поки i<=n , при кожному виконанні тіла циклу значення змінної і збільшується на одиницю.

 

 

Логічні  вирази у Сі

 

Логічні вирази (умови) можуть   бути   простими   або   складеними. Просту  умову записують

як операцiю вiдношення, у якiй значення двох виразiв порiвнюються мiж собою.

Для запису операцiй  вiдношення  використовують позначення (у цих прикладах z=7):

 

Операцiя відношення

Позначення

Приклад

Значення

дорівнює

==

(z==7)

1

менше

(z<5)

0

більше

(z>6)

1

не дорівнює

!=

(z!=2)

1

менше або дорівнює

<=

(z<=7)

1

більше або дорівнює

>=

(z>=6.5)

0

 

         Як видно з таблицi значенням  умовних  виразiв  може  бути  1 (True iстина) 

або 0 (Falseне iстина). Зверніть увагу — умовний вираз обов’язково виділяють

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

                &&логiчне i;

                ¦¦          логiчне або;

                !логiчне не .

         Наприклад:

        ((x>7) && (y/x<=5))

        ((z-x==12) ¦¦ (r>0.3))

         Операцiя ! перетворює значення 1 (True) у значення 0 (False) i навпаки. Навчитися правильно складати логічні вирази є надзвичайно важливо не лише для опрацювання числової інформаці, а й для пошуку інформації (напр. у мережі Інтернет).

         Розглянемо приклад використання складних логічних виразів та оператора ЯКЩО. Нехай ми маємо такий сигнал:

 

 

 


 

Рис.3.21. Графік сигналу, заданого складним виразом (файл )

 

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

         if ((t>0)&&(t<=0.02))   s=5*t/0.02;

         if ((t>0.02)&&(t<=0.06)) s=5.0;

         if  ((t>0.06)&& (t<=0.08))  s=5 - 5*(t-.06)/.02;

         if (( t>0.08)&& (t<=0.16))  s=7.0*sin(2*Pi*t/.16);

 

 

Структурні типи і структури

 

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

         struct ім'я_структурного_ типу {визначення елементів} список_структур;

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

 

#include <stdio.h>

#include <math.h>

#include <conio.h>

#include <dos.h>

void main()

{

float dx,r;

int i;

struct tabul

{float x[50],y[50];

float xp,xk;

int n;

} pryklad;

 pryklad.xp=-5.0; pryklad.xk=5.0;

 pryklad.n=20;

 dx=(pryklad.xk-pryklad.xp)/pryklad.n;

 r=pryklad.xp;

 for (i=0; i<=pryklad.n;i++)

 {

  pryklad.x[i]=r;

  pryklad.y[i]=sin(r);

  r+=dx;

  printf(" x= %f y= %f\n",pryklad.x[i],pryklad.y[i]);

 }

 getch();

}

 

         У цій програмі введено структуру

         struct tabul

         {float x[50],y[50];

          float xp,xk;

          int n;

         } pryklad;

 

тут tabul ім'я структурного типу, pryklad ім'я змінної цього  типу. До складу структури входять компоненти:

         масиви — float x[50],y[50];

         скалярні змінні — float xp,xk; int n;

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

         pryklad.xp=-5.0;

         pryklad.n=20;

         pryklad.x[i]=r;

         pryklad.y[i]=sin(r);

        

         Змінні структурного типу можна описувати і таким чином:

         1) спочатку описують структурний тип;

         2) потім описують змінні цього типу.

         Наприклад:

         struct tabln

         {float x[50],y[50];

          float xp,xk;

          int n;};

          

тут  описано структурний тип tabln з п'ятьма  компонентами. Змінні цього новоствореного типу можна описати так:

         tabln prykl;

тут prykl є змінною типу tabln.

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

 

         typedef struct

         {char processor[10];

          int frequency;

          int memory;

          int hdd;}comp;

тут описано структурний тип comp. Наступний рядок вводить три змінні цього типу:

         comp eom1, eom2, eom3;

         Компоненти змінних типу comp можна задати так:

         eom1.processor="I80486DX4";

         eom1.frequency=100;

         eom1.memory=16;

         eom1.hdd=40;

         eom2.processor="K6-2+";

         eom2.frequency=450;

         eom2.memory=128;

         eom2.hdd=4300;

         У цьому прикладі змінна eom1 задає параметри ЕОМ з процесором I80486DX4 і

тактовою частотою 100МГц., оперативною пам'яттю 16Мб і жорстким магнітним

диском 40Мб, а змінна eom2 задає параметри ЕОМ з процесором K6-2+ і тактовою частотою

450МГц., оперативною пам'яттю 128Мб і жорстким магнітним диском 4.3Гб.

 

 

Об'єднання, бітові поля. Двійкова і шістнадцяткова системи числення

 

         На відміну від структур, які під одним іменем містять різнорідну інформацію (кожна компонента

має свій тип і для неї відводять потрібну кількість байт пам'яті), об'єднання забезпечують різне

подання однієї і тієї самої ділянки пам'яті. Розглянемо приклад:

 

union

{ char b[2];

  int i;

} pr_un;    

 

         тут задано об'єднання двох компонент — цілої i та символьного масиву b[2]. Оскільки обидві

компоненти розміщені у одній  тій самій ділянці пам'яті (2 байти), то b[0] містить у собі молодший

байт змінної i, а b[1] - старший байт змінної i. Ще однією дуже корисною властивістю структур

і об'єднань є можливість використання бітових полів — компонентами структур і об'єднань може

бути бітове поле заданої ширини. Для прикладу розглянемо використання бітових полів для перетворення

послідовності бітів на цифровому виході вольтметра В7-16А у змінну типу float.  Результати

вимірювань цифрового вольтметра В7-16А (з роботою цифрового вольтметра ви познайомитесь у загальному

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

десяткового розряду на вихідному рознятті вольтметра відведено чотири сигнальних лінії (двійкових розряди).

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

0 — 0000,             5 — 0101,

1 — 0001,             6 — 0110,

2 — 0010,             7 — 0111,

3 — 0011,             8 — 1000,

4 — 0100,             9 — 1001.

         Для введення в IBM-подібну ПЕОМ цифрової інформації використовують порти

вводу-виводу (з портами вводу-виводу ви ознайомитесь у курсах "Основи цифрової

і мікропроцесорної техніки" та "Автоматизація фізичного експерименту").

Одним із засобів роботи з портами вводу-виводу мови Сі  є функції

in(номер_порта) читання двійкового восьмибітного коду з порта з заданим номером,

out(номер_порта) вивід двійкового восьмибітного коду у порт із заданим номером.

Після читання двійкової інформації з порта інструкцією in ви отримаєте беззнакове

ціле значення (unsigned char). Наступна програма аналізує введені два байти (v7_16b1,v7_16b2)

і перетворює їх у результат вимірювання (змінна rezult) з урахуванням заданої межі

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

Об'єднання v7_16 має три компоненти:

         беззнакову байтову vymir;

         та дві беззнакові чотирибітні c1,c2.

Для задання байтів використовуємо оператор присвоєння з шістнадцятковою константою

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

 

# include <stdio.h>

# include <math.h>

# include <conio.h>

# include <dos.h>

void main ()

{

 float rezult;

 union

 {

          unsigned char vymir;

         struct

          {

                   unsigned char c1:4;

                   unsigned char c2:4;

         } vv_byte;

 }v7_16b1,v7_16b2;

 /* задаємо перший байт результата вимірювання 97 */

  v7_16b1.vymir=0X97;   

/* задаємо другий байт результата вимірювання 56 */

  v7_16b2.vymir=0X56;

/* обчислюємо результат з урахуванням межі вимірювання 1В */

rezult=v7_16b2.vv_byte.c2*0.1+v7_16b2.vv_byte.c1*0.01+v7_16b1.vv_byte.c2*0.001+v7_16b1.vv_byte.c1*0.0001;

 printf(" rezult= %f \n", rezult);

  getchar();

}

 

 

Операції із комплексними змінними у Сі++

 

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

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

Для використання змінної, яка матиме своїм значенням комплексне число, у рядку опису потрібно зазначити

 

         complex <ім'я змінної>;

 

наприклад,

 

         complex z(1.0, 2.1), z1, z2;

 

Тут описано три комплексні змінні —  z, z1, z2. Значення змінної  має дійсну частину, яка  дорівнює 1, та уявну 2.1 (ініціалізація під час опису).

Усі функції модуля math.h, які означені у полі комплексних чисел, можна використовувати у програмах із коплексними змінними.

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

Змінні, які отримують (або задають) значення модуля, аргумента, дійсної або  уявної  частини комлексної змінної повинні мати тип double.

Як приклад розглянемо програму виділення дійсної та уявної частини комплексного числа, обчислення його модуля та аргумента і

задання комплексного числа через модуль і аргумент:

 

#include <stdio.h>

#include <math.h>

#include <complex.h>

void main()

{

complex z(1.0, 2.0),z1,z2; /* опис комплексних змінних */

double  mz,x,y,fi;

         mz = abs(z); /* обчислення модуля комплексної змінної z  */

         printf("IzI= %f\n", mz);

         x=real(z); /* виділення дійсної частини комплексної змінної z  */

         y=imag(z); /* виділення уявної частини комплексної змінної z  */

         printf("Rez= %f\n", x);

         printf("Imz= %f\n", y);

/* задання комплексної змінної z1 через  дійсну та уявну частини   */

         z1=complex(x,y);

          mz = abs(z1);

         printf("Iz1I= %f\n", mz);

         fi=arg(z1);  /* обчислення аргумента комплексної змінної z1  */

         printf("fi= %f\n", fi);

/* задання комплексної змінної z2 через  модуль і аргумент  */

         z2=polar(mz,fi);

         mz = abs(z2);

         printf("Iz2I= %f\n", mz);

}

 

         У курсі електрики (який ви зараз вивчаєте) для опису електричних кіл змінного струму використовують комплексні опори

основних компонент електричного кола:

         ємності — Zc-=1/ (Zc-=1/ (i*w*C);

         індуктивності — ZL-=i*w*L;

         резистора — ZR-=R.

         Тут  iуявна одиниця,  wколова частота напруги, яка діє на коло, C, L, Rвеличини ємності, індуктивності і опору.

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

Розглянемо програму табуляції модуля  комплексного коефіцієнта передачі RC-кола (коефіцієнт передачі кола рівний відношенню

 вихідної напруги кола до вхідної), яке зображено на рис. 3.22а.

 

#include <stdio.h>

#include <math.h>

#include <complex.h>

void main()

{

complex z1,z2,k;

double  mk,r,c,w;

r=5000;

c=1e-6;

w=0.1;

/* задання комплексного опору резистора R   */

z1=complex(r,0);

while (w<=1000)

{

/* задання комплексного опору ємності C   */

z2=complex(0,-1.0/(w*c));

/* обчислення  комплексного коефіцієнта передачі кола   */

k = z2/(z1+z2);

/* обчислення модуля комплексного коефіцієнта передачі кола   */

mk=abs(k);

                   printf("w= %f IkI= %f\n",w,mk);

w=w+50;

}

}

 

 

 

 

 

 

 

 

 

 


                  
а)                                                     б)     

 

 Коло змінного струму (а — з опором і ємністю, б- із комплексними опорами Z1, Z2)    

 

         З використанням комплексних опорів Z1, Z2 відношення вихідної напруги кола до вхідної обчислюємо як

 

K=Uвих/Uвх;   Uвих =I*Z2; I= Uвх /(Z1+Z2)

         Остаточно

K=Z2 /(Z1+Z2).

 

 

Функції у Сі

 

Аналогом процедур-функцій та процедур загального виду у Паскалі (підпрограм у багатьох

інших мовах програмування, наприклад Fortran, Basic) у мові Сі є функції. Кожна програма,

написана мовою Сі, зазвичай є сукупністю функцій. Одна з них є обов'язковою — функція main,

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

ANSI у мові Сі діє два варіанти опису і визначення функцій:

         стандартний;

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

написаних до прийняття стандарту ANSI.

         Розглянемо структуру стандартного опису функції:

тип_результату ім'я_функції(список_формальних_параметрів)

{

опис об'єктів;

виконувані оператори;

} 

 

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

 

float seredne(int n, float x[]);

{

int i;

float r;

r=0;

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

r=r+x[i];

r=r/n;

return r;

}

 

У наступній програмі обчислюємо середнє значення вимірювання довжини d.

 

#include <stdio.h>

#include <conio.h>

float seredne(int n, float x[]) /* заголовок функції */

{

float r;

int i;

r=0;

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

r+=x[i]; /* аналог r=r+x[i]; */

r/=n; /* аналог r=r/n; */

return r; /* передача отриманого значення за іменем функції */

}

void main()

{

/* опис і ініціалізація масиву d */

float d[]={2.07,2.1,2.12,2.2,2.08,2.13,2.03,2.11,2.15};

float ser_zn_vym;

ser_zn_vym=seredne(9,d); /* виклик функції */

printf(" середнє значення= %f\n",ser_zn_vym);

getch();

}

 

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

Внаслідок  цього отримаємо програму статистичної обробки результатів експерименту з двома функціями:

 

float seredne(int n, float x[])

float ser_kw_vidhyl(int n, float x[], float sz).

 

#include <stdio.h>

#include <math.h>

#include <conio.h>

float seredne(int n, float x[])

{

float r;

int i;

r=0;

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

r+=x[i]; /* r=r+x[i]; */

r/=n; /* r=r/n; */

return r;

}

float ser_kw_vidhyl(int n, float x[], float sz)

{

float r,sum;

int i;

sum=0;

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

r=x[i]-sz;

sum+=r*r;  /* sum=sum+r*r; */

r=sqrt(sum/(n*(n-1)));

return r;

}

void main()

{

/* опис і ініціалізація масиву d */

float d[]={2.07,2.1,2.12,2.2,2.08,2.13,2.03,2.11,2.15};

float ser_zn_vym,skw;

/* виклик функції обчислення середнього значення */

ser_zn_vym=seredne(9,d);

            printf(" середнє значення= %f\n",ser_zn_vym);

/* виклик функції обчислення середньоквадратичного відхилення */

         skw=ser_kw_vidhyl(9,d,ser_zn_vym);

            printf(" середньоквадратичне відхилення= %f\n",skw);

            getch();

}

 

         У цій програмі для статистичної обробки результатів експерименту  використані дві

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

значення (тобто функція у Сі є аналогом процедури-функції Паскалю). Для того щоб функція

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

На завершення розглянемо приклад “достандартного” опису функції:

float ser_kw_vidhyl(n,x,sz)

int n;

float x[];

float sz;

{

float r,sum;

int i;

sum=0;

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

r=x[i]-sz;

sum+=r*r;  /* sum=sum+r*r; */

r=sqrt(sum/(n*(n-1)));

return r;

}

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

 

Функції роботи із графікою у Сі

void arc(int x, int y, int stAngel, int endAngle, int radius);

void arc(int x, int y, int stAngel, int endAngle, int radius, COLORS color);

void arc(int x, int y, int stAngel, int endAngle, int radius, int color);

void bar(int x, int y, int x1, int y1);

void bar(int x, int y, int x1, int y1, COLORS color);

void bar(int x, int y, int x1, int y1, int color);

void bar3d(int x, int y, int x1, int y1, int z, bool top);

void circle(int x, int y, int radius);

void circle(int x, int y, int radius, COLORS color);

void circle(int x, int y, int radius, int color);

void cleardevice();

void close();

void closegraph();

void drawfunc(int numOfPoints, double *arrayX, double *arrayY);

void drawpoly(int numOfPoints, int* array);

void drawpoly(int numOfPoints, int* arrayX, int* arrayY);

void drawpoly(int numOfPoints, int** arrayXY);

void ellipse(int x, int y, int rWidth, int rHeight);

void ellipse(int x, int y, int rWidth, int rHeight, COLORS color);

void ellipse(int x, int y, int rWidth, int rHeight, int color);

void fillellipse(int x, int y, int rWidth, int rHeight);

void fillellipse(int x, int y, int rWidth, int rHeight, int color);

void fillellipse(int x, int y, int rWidth, int rHeight, COLORS color);

int getmaxx();

int getmaxy();

void image(int x, int y, char* path);

void initgraph();

void initgraph(int drv, int drm, char *text);

void initgraph(int setWidth, int setHeight);

void line(int x, int y, int x1, int color);

void line(int x, int y, int x1, COLORS color);

void line(int x, int y, int x1, int color);

void lineto(int x, int y);

void lineto(int x, int y, int color);

void lineto(int x, int y, COLORS color);

void moveto(int x, int y);

void outtext(const char* text);

void outtext(const char* text, int color);

void outtext(const char* text, COLORS color);

void outtextxy(int x, int y, const char* text);

void outtextxy(int x, int y, const char* text, int color);

void outtextxy(int x, int y, const char* text, COLORS color);

void pieslice(int x, int y, int stAngle, int endAngle, int radius);

void pieslice(int x, int y, int stAngle, int endAngle, int radius, int color);

void pieslice(int x, int y, int stAngle, int endAngle, int radius, COLORS color);

void putpixel(int x, int y);

void putpixel(int x, int y, COLORS color);

void putpixel(int x, int y, int color);

void rectangle(int x, int y,int x1,int y1);

void rectangle(int x, int y,int x1,int y1, COLORS color);

void rectangle(int x, int y,int x1,int y1, int color);

void save(const char* path);

void setbkcolor(COLORS color);

void setbkcolor(int color);

void setcolor(COLORS color);

void setcolor(int color);

void setfillcolor(int color);

void setfillcolor(COLORS color);

void setfillstyle(PATERN patern, COLORS color);

void setfillstyle(int patern, COLORS color);

void setfillstyle(PATERN patern, int color);

void setfillstyle(int patern, int color);

void setlinestyle(int linestyle, unsigned upattern, int thickness);

void setlinestyle(LINESTYLE linestyle, unsigned upattern, int thickness);

void settextstyle(char* font, int direction, int size);

 

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

 

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

параметри-значення, які не можуть змінюватись процедурою;

параметри-змінні (перед іменем такого параметра стоїть слово var), які  змінюються або

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

що аналога процедурам Паскалю у мові Сі немає.

Однак завдяки використанню вказівників на змінні в якості параметрів

функції  можна написати функції, у яких значення вказівників на змінні не змінюватимуться,

а значення, на які показують вказівники, будуть змінені.

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

при компіляції програми у пам’яті ЕОМ відводиться певна кількіть байтів (задається фізична адреса)

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

програми на виконання у відведені комірки пам’яті програма вписує значення змінних. Отже,  з

кожною змінною у програмі пов’язані ім’я змінної,  її тип, значення і фізична адреса області оперативної

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

а технічну справу розміщення значення змінної в оперативній  пам’яті покладаємо на компілятор

(при програмуванні у машинних командах розподілом пам’яті керує програміст). За допомогою

спеціальної конструкції — вказівника на змінну ми можемо отримати доступ до адреси змінної,

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

 різну кількість байт (комірок пам’яті),  то опис вказівника на змінну здійснюємо таким чином:

 

         тип_змінної *ім’я_змінної;

наприклад:

 

float *x — вказівник на змінну типу float.

 

Якщо x є масивом,  то  *x  вказує на компоненту x[0],  *(x+1) - на компоненту x[1],

*(x+i) на компоненту x[i]. У наступній програмі функція stat_obr(n, *x) має два параметри

n —кількість елементів масиву і  *x — вказівник на масив.

Під час виконання функції ( наприклад stat_obr(9,d);) функція змінює  два останні значення масиву:

нульове значення d[10]  замінюється середнім значенням результатів вимірювання;      

нульове значення d[11]  — середньоквадратичним відхиленням.

 

#include <stdio.h>

#include <math.h>

#include <conio.h>

void stat_obr(int n, float *x) /* функція не повертає значення */

/* float *x — вказівник на змінну типу float  */

{

float r,sum;

int i;

sum=0;

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

sum+=*(x+i);  /* sum=sum+x[i],  *(x+i) — вказівник на x[0]+i; */

*(x+n)=sum/n; /* елемент масиву x[n]=sum/n; */

sum=0;

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

            {

                       r=*(x+i)-*(x+n);

                       sum+=r*r; /* sum=sum+r*r; */

            }

*(x+n+1)=sqrt(sum/(n*(n-1)));  /* елемент масиву x[n+1]=sqrt(sum/(n*(n-1))); */

}

void main()

{

float d[]={2.17,2.1,2.12,2.2,2.18,2.13,2.13,2.11,2.15,0,0};

            stat_obr(9,d);

            printf(" seredne= %f\n",d[9]);

            printf(" ser_kw_vydh= %f\n",d[10]);

            getch();

}

 

Робота з файлами в Сі. Стандартні файли

 

Для  довготривалого зберiгання програм, даних, текстiв, зображень та фонограм на ЕОМ

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

дисках називають файлами (англ. fileшеренга, ряд бітів).   Щоб вiдрiзнити один файл

вiд iншого використовують  iмена  файлiв. Зазвичай iм’я файла складають з двох частин:

власне iмені файлу довжиною до 256 знаків ( у MS DOS 8 знакiв);

розширення імені файлу ( у MS DOS до трьох знаків). Розширення вiддiляють вiд iменi крапкою.

Наприклад:

 

                   boll.pas

                   readme.txt

                   vdisk.sys

                   tabl.dat

         lab3.c

         lab4.cpp

        

 

Деякi розширення є стандартними, наприклад:

         sysсистемнi файли;

         pasпрограми, написанi мовою Паскаль;

         cпрограми, написанi мовою C;

         cpp — програми, написанi мовою C++;

         txtтекстовi файли;

         datфайли даних.

 

      Файл можна зобразити довгим рядком, на якому зроблено написи

          

           I ім’я файлу I запис  I запис  I... I запис  I кiнець файлу I

 

         Роботу з файлами на магнітних дисках у мові Сі можна здійснювати на трьох рівнях:

         потоковий ввід/вивід;

         ввід/вивід нижнього рівня (побайтовий ввід/вивід з використанням засобів операційної системи);

         ввід/вивід для консолі і портів.

         Розглянемо потоковий ввід/вивід. Потоковий ввід/вивід побудований на обміні

байтами (вивід на пристрій друку, дисплей, диск; ввід з клавіатури, диска).

Кожна програма під час своєї роботи має доступ до стандартних потоків

stdin (вхідний потік байтів з клавіатури ), stdout (вихідний потік байтів на дисплей),

stderr  (потік повідомлень про помилки).  Функція scanf працює з  stdin,

printf — з stdout, повідомлення про помилки  (потік stderr) виводяться на дисплей.

         Для роботи з файлами використовують структуру FILE, визначену у стандартному

файлі stdio.h. Цю структуру позвязують з вказівником на файл рядком опису

 

FILE *імя_файлової_змінної;

 

         Для відкриття файла використовують функцію fopen(ім’я_файла, режим_відкриття). Параметр режим_відкриття може мати значення:

         “w” — відкриття нового файлу для запису;

         “wt” — відкриття нового текстового файлу для запису;

         “r”  — відкриття файлу для читання;

         “rt”  — відкриття текстового файлу для читання;

         “a” — відкриття файлу для додавання інформації в кінець файлу;

         “w+” відкриття файлу для запису і багаторазових виправлень, відкриття існуючого

файлу з таким режимом призводить до втрати його вмісту;

         “r+”  відкриття файлу для читання з можливістю змін його вмісту без збільшення

його розміру (дописування в кінець файлу неможливе!);

         “a+” відкриття файлу для читання і запису, на відміну від “w+” відкриття існуючого

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

 

         Під час відкриття файлу вказівник файлу встановлюється на його початок,

для роботи з режимами “w+”, “r+”, “a+” використовують функцію

задання позиції вказівника файлу fseek(вказівник_на_файл, зміщення, початок_відліку), 

початок_відліку задають константами, які означені у файлі stdio.h:

         SEEK-SET початок файлу;

         SEEK-CUR — поточна позиція вказівника;

         SEEK-END  кінець файлу.

 

Для форматного виводу у файл використовують функцію

 

fprintf (файлова_змінна, “керуючий рядок”, список виводу);

 

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

 

fscanf (файлова_змінна, “керуючий рядок”, список вводу);

 

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

 

fclose(файлова_змінна );

 

          Для прикладу розглянемо програму запису  у файл zn_x.txt значень змінної x 

та у файл zn_y.txt значень змінної y з подальшим читанням інформації з цих файлів і виводом їх на екран дисплею

 

#include <stdio.h>

#include <math.h>

void main()

{

            float a,b,x,y,rx,ry;

            FILE *fx,*fy;

/*відкриття нового текстового файлу для запису */

fx=fopen("zn_x.txt","wt");

/*відкриття нового текстового файлу для запису */

            fy=fopen("zn_y.txt","wt");

            a=-5.0; b=5;

            x=a;

            while (x<=b)

{

                       y=x*x;

                       /*вивід у файл zn_x.txt значення x */

                       fprintf(fx," %f\n ",x);

                       /*вивід у файл zn_y.txt значення y */

                       fprintf(fy," %f\n ",y);

                       x+=0.2;

}

            /*закриття файлу zn_x.txt */

            fclose(fx);

            /*закриття файлу zn_y.txt */

            fclose(fy);

/*відкриття текстового файлу zn_x.txt для читання */

 fx=fopen("zn_x.txt","rt");

/*відкриття текстового файлу zn_x.txt для читання */

            fy=fopen("zn_y.txt","rt");

/* ПОКИ НЕ(КІНЕЦЬ(файлу zn_x.txt) */

            while (!feof(fx))

            {

                       /*читання з файлу zn_x.txt значення x */

                       fscanf(fx,"%f",&rx);

                        /*вивід на дисплей прочитаного значення x */

                        printf("x=%f",rx);

/*читання з файлу zn_y.txt значення y */

                       fscanf(fy,"%f",&ry);

/*вивід на дисплей прочитаного значення y  */

                       printf(" y=%f\n",ry);

            }

            /*закриття файлу zn_x.txt */

 fclose(fx);

            /*закриття файлу zn_y.txt */

            fclose(fy);

}

 

Для форматного виводу у  потік stdout (на дисплей) використовують функцію

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

вводу з клавіатури, яка вибирає з вхідного потоку stdin потрібну кількість байтів

і перетворює їх відповідно до специфікацій, внесених у керуючий рядок

 

scanf (“керуючий рядок”, список вводу);

 

Специфікації перетворення потоку байтів у значення змінних описані у  п.5. Розглянемо

приклад програми з читанням значень змінних  із клавіатури

 

#include <stdio.h>

#include <conio.h>

#include <math.h>

#include <stdlib.h>

void main()

{

float r,s;

int i,n;

printf("\n введи ціле значення ");

/*читання з stdin  значення для i */

scanf("%d",&i);

printf("\n введено %d", i);

printf("\n введи два цілі значення ");

/*читання з stdin  значеннь для i та n  */

scanf("%d %d",&i,&n);

printf("\n введено %d %d ", i,n);

printf("\n введи дробове значення ");

/*читання з stdin  значення для r  */

scanf("%f",&r);

printf("\n введено %f ", r);

printf("\n введи ціле і дробове значення ");

/*читання з stdin  значеннь для i та s  */

scanf("%d %f",&i,&s);

printf("\n введено %d %f ", i,s);

}

 

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

які вказують на те, що з вхідного потоку потрібно зчитувати і не враховувати всі

прогалини аж до появи байта, відмінного від символа прогалини (використовують для

розділення значень у вхідному потоці символами прогалини).

У специфікаціях перетворення можна задавати максимальну кількість символів

для перетворення за цією специфікацією, наприклад:

%4d — специфікація для введення чотирицифрового цілого значення;

%6f — специфікація для введення шестицифрового дробового значення.

 

Окрім значень для змінних, згідно із списком  вводу функція:

 

scanf (“керуючий рядок”, список вводу);

 

повертає кількість уведених значень, якщо всі перетворення виконано успішно,

або ж -1 при виникненні помилок перетворення. Це означає, що у програмі мовою

Сі можна записати таку команду присвоєння:

 

kontr=scanf("%d %f",&i,&s);

 

Після успішного виконання цієї команди змінна kontr матиме значення 2,

якщо ж уведені значення не відповідатимуть специфікаціям керуючого рядка,

то змінна kontr матиме значення -1.

         Для читання інформації з вхідного потоку можна використовувати і такі функції:

 

         ім’я змінної=getchar(); - ввід одного символа

         gets(ім’я рядкової змінної); - ввід одного рядка символів

 

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

 

         putchar(змінна); - вивід значення змінної типу char;

         puts(ім’я рядкової змінної); - вивід одного рядка символів.

 

         Нижче подано приклад програми читання значень з клавіатури, в якій для виведення

запрошення до введення значень використано функцію puts

 

#include <stdio.h>

#include <conio.h>

/*потрібно для виконання перетворень значень типу float */

#include <math.h>

#include <stdlib.h>

void main()

{

float r,s;

int i,n;

puts(" введи ціле значення ");

 /*читання з stdin  значення для i */

scanf("%d",&i);

printf("введено %d\n ", i);

puts(" введи два цілі значення ");

/*читання з stdin  значеннь для i та n  */

scanf("%d %d",&i,&n);

printf(" введено %d %d\n ", i,n);

puts(" введи дробове значення ");

 /*читання з stdin  значення для r  */

scanf("%f",&r);

printf(" введено %f\n ", r);

puts(" введи ціле і дробове значення ");

/*читання з stdin  значеннь для i та s  */

scanf("%d %f",&i,&s);

printf(" введено %d %f \n ", i,s);

}

 

 

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

 

Для додавання до тексту програми текстів із файлів на магнітних дисках використовують

команду #include. Ця команда має три форми:

 

#include <імя файла.h>

#include ”імя файла.c”

#include ім’я макроса

        

         Файли з розширенням .h називають заголовковими і використовують для означення

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

         stdio.h — засоби вводу/виводу;

         stdlib.h — функції загального призначення;

         math.h — функції для математичних обчислень;

         graphics.h — графічні функції (для MS DOS);

         conio.h — функції для роботи з клавіатурою і дисплеєм ( MS DOS);

         dos.h — функції для роботи з системними засобами  MS DOS.

 

Друга форма директиви #include ”ім’я файла.c” дає змогу „зібрати” текст програми

з окремих текстових файлів. ЇЇ використовують під час колективної розробки великих програм.

Наприклад, директиви

 

#include ”main.c”

#include ”count.c”

#include ”estimate.c”

         #include ”compare.c”

         #include ”gauss.c”

         #include ”pseudo.c”

 

дозволяють створити текст програми, у яку ввійдуть тексти з файлів

main.c, count.c,  estimate.c,  compare.c, gauss.c,  pseudo.c.

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

з курсу „Чисельні методи”, який будете вивчати на третьому курсі.

 

 

Основні етапи створення і виконання  програм на ЕОМ

 

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

 


 Процес створення програми

        

         Текст програми створюють за допомогою  текстового редактора (у багатьох оболонках

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

(компіляції або трансляції) тексту програми, записаного мовою програмування високого рівня

(Паскаль, Сі, Фортран і ін.) використовують спеціальну програму-компілятор (транслятор).

Якщо текст програми не відповідає синтаксису мови програмування, яку використано для

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

 виправити синтаксичні помилки і знову запустити процес компіляції програми. Якщо текст

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

на магнітному диску (або в оперативній пам'яті [залежно від налаштування компілятора]).

Для отримання виконуваної програми (програми у машинних командах) до результатів компіляції

додають (команда Link) програми вводу/виводу інформації, обчислення стандартних функцій

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

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

(команда Run). Після отримання результатів рахунку програми їх треба проаналізувати.

Якщо отримані результати не відповідають поставленій задачі (наприклад, після запуску

програми методу Ньютона корінь нелінійного рівняння не знайдено), потрібно проаналізувати

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

програми виявлені помилки, потрібно виправити їх і повторити процеси компіляції, рахунку і

аналізу результатів.

 

Структури вибору і переходів

 

Конструкція if

 

   Розглянемо синтаксис цієї конструкції:

if (<Лог. Вираз>

{ блок 1 ;}

else

{ блок 2 ;}

<Лог. Вираз> в дужках повертає значення true або false, тобто значення типу boolean.

Якщо вираз істинний(тобто має значення true або ≠0), то виконуються оператори, які стоять в блоці 1,

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

Оператора if можна використовувати і без оператора else:

if (лог. вираз)

{ блок 1; }

В цьому випадку виконуються оператори, що стоять в блоці 1, якщо вираз істинний; якщо вираз помилковий,

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

 

Конструкція switch

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

Синтаксис цієї конструкції:

switch (вираз)

{

case значение1:

. . . .

break;

case значение2:

break;

case значениеЗ:

break;

default:

. . . .

break;

}

Під виразом розуміється будь-який вираз, який має цілий тип або тип даних char, або enum, або string.

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

із значенням виразу.

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

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

мітку default. Мітка default може бути відсутня, тоді перехід здійснюється відразу в кінець оператора switch.

 

Конструкція goto

         Використовується для переходів(передачі контролю) на певний рядок коду.

         Синтаксис цієї конструкції:

                   goto <мітка>;

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

Приклад:             

         label1:

         . . . ;

         . . . ;

         . . . ;

         goto label1;

 

Конструкція try... catch

Ця конструкція служить для відділення дій, в яких можуть бути  незаплановані помилки, з подальшою можливістю перехоплення

виключень, які проводяться в секції catch, що згенерували.

В загальному вигляді оператор try... catch виглядає таким чином:

try

{

сумнівні дії

catch(помилка)

{

дії обробки помилки

}

final 

{

завершальні дії

}

Отже, в тілі try знаходяться деякі "сумнівні дії", виконання яких може призвести

до помилки. У разі її виникнення  буде проведений перехід в секцію catch для

її подальшої обробки. В секції final знаходяться дії, які повинні бути виконаний

незалежно від того чи виникло виключення чи ні.

 

Оператор throw

За допомогою оператора throw можна генерувати свої власні  виключення для їх подальшого

перехоплення в операторі try. .. catch. Виключення може бути числом, рядком або

навіть об'єктом власного класу.  Викид виключення в загальному вигляді виглядає

таким чином:  throw error;

 

 

Оператор break

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

Оператор continue

         Цей оператор використовується для дострокового переходу на новий виток циклу в операторах циклів.

Оператор return [<значення>]

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

Оператор sizeof(<змінна чи тип>)

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

 

Основи ООП у С++

 

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

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

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

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

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

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

цей інтерфейс.

         Одним словом, специфікація основного типу дозволяє визначити наступне:

•    Який об'єм пам'яті необхідний для розміщення відповідного об'єкту даних.

•    Які операції або методи можуть бути виконаний над об'єктом даних.

Для вбудованих типів даних ця інформація закладена в компілятор. Але коли в C++ задається тип, визначений користувачем, таку інформацію потрібно задавати самостійно. Нагорода за працю — виграш в продуктивності і гнучкості, тому ми і створюємо нові типи

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

Клас – це абстракція, тобто опис чого-небудь, причому цього «що-небудь» може і не існувати. Клас – це спосіб реалізації природного підходу до опису.

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

   ООП підтримує три основні принципи:

·        інкапсуляція;

·        поліморфізм;

·        наслідування.

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

Інкапсуляція в ООП складається з двох аспектів:

·        об'єднання даних і функцій по роботі з цими даними в єдину сутність;

·        контроль доступу до елементів цієї сутності.

 

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

·        використовуємо ключове слово class;

class <ім’я класу>[<:список батьківських класів>]

{

         опис полів і методів;

}

·        оголошуємо дані усередині класу;

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

·        оголошуємо методи усередині класу;

Методи є функціями, пов'язаними з конкретним класом. Це можуть бути або методи екземпляра, які працюють для конкретного екземпляра класу,

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

         Основні модифікатори методів:

                              static       Метод не призначений для роботи з певним екземпляром класу.

virtual      Метод може бути перевизначений в похідному класі.

abstract     Віртуальний метод, який визначає сигнатуру методу, але не містить реалізацію.

override     Метод перевизначає успадкований віртуальний або абстрактний метод.

extern                  Метод реалізований поза програмою на іншій мові.

 

·        розставляємо модифікатори доступу для даних і методів.

Модифікатори доступу:

                   public       доступний звідусіль, зокрема ззовні класу.

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

private      доступний тільки з класу, до якого він належить.

 

 

 

Ключове слово this

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

 після виділення пам'яті під об'єкт.

 

 

 

 Повернутись в головне меню