22944

Загальна структура Сі-програми

Лекция

Информатика, кибернетика и программирование

oператор ::= безлейбовий_ оператор лейба : безлейбовий_ оператор безлейбовий_ оператор ::= базовий оператор структурований опeрaтор лейба ::= ідентифікатор базовий_оператор ::= порожній_oператор oперато_переходу присвоєння виклик_функції oператор_вираз порожній_oператор ::= ; Сем. вихід_ з_функції ::= return[ значення_функції ] ; значення_функції ::= вираз Сем. присвоєння ::= Lvalue_вираз [ операція ]= вираз ; вираз ::= терм Lvalue_вираз ::= ідентифікатор індексація_покажчика розіменування_покажчика ...

Русский

2013-08-04

217.5 KB

0 чел.

ТЕМА: Загальна структура Сі-програми.

Програма – це набір ФУНКЦІЙ, ДИРЕКТИВ ПРЕПРОЦЕСОРА ТА ЗОВНІШНІХ  даних (=змінних та констант). Фізично вони можуть бути розміщені  в одному або декількох текстових файлах. Окрема функція має наступну синтаксичну структуру:

[<тип>] <ім’я_функції> ([<список_параметрів>]) 

{

[<cписок_операторів_та_описів змінних>]

}

і подає  певний алгоритм.

Обробка Сі-програм розпочинається  з фази ПРЕПРОЦЕСУВАННЯ, яка включає: 1)відкидання пари символів: \ та \n (=”склеювання” сусідних рядків програми),

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

3) виконання директив препроцесора. Вони розпочинаються символом # . Нпр.,  # include <stdio.h>,  #define n 100. В процесі препроцесування замість першої директиви в програму буде вставлено текст , що зберігається в текстовому файлі stdio.h, друга «наказує» препроцесору замінити всі наступні входження в програмі ідентифікатора n на лексему 100;

4) заміну в символьних константах і літералах  ескейп-послідовностей на їх еквіваленти. Сусідні літерали конкатенуються.

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

Серед функцій програми обов’язково має бути функція зі стандартним іменем name. Саме з неї розпочинається виконання програми.

Приклад Сі-програми (1.16).  

#include < stdio.h >

 double qpow(double x, unsigned int n)

 {double p,a; unsigned int q;

      a=x; q=n;

      if (n%2==0) p=1; else p=x;

       while (q>0) { a=a*a;

                              q=q/2;

                               if (q%2==1) p=p*a;

                            }

       return p;

   }

#define X 3.1428

#define N 48

void main ()

{ double a; int k;

printf(“\n%f ”, qpow(X,N) ); /* виведення на екран значення степені */

scanf(”%f%d”, &a,&k); /* введення з клавіатури значень основи та показника степені */

printf(“\n%е ”, qpow(a,k) ); /* виведення на екран значення степені у формі з рухомою крапкою*/

}

Структура операторів. Оператори – це конструкції, що безпосередньо задають  обробку даних (створюють нові дані або змінюють значення вже існуючих).

<oператор>::=  <безлейбовий_ оператор> |  <лейба> : <безлейбовий_ оператор>

<безлейбовий_ оператор>::=  <базовий оператор> |  <структурований опeрaтор>

<лейба>> ::=  <ідентифікатор>

<базовий_оператор>::= <порожній_oператор> | <oперато_переходу> | <присвоєння> | <виклик_функції> | <oператор_вираз>

<порожній_oператор>::=  ; 

Сем. Не впливає на стан памяті.

<oператор_переходу> ::= <безумовний_перехід>  |  <продовження> |<переривання>  | <вихід_ з_функції>

 

Сем. Оператори в програмах можуть мати лейби, які являють собою ідентифікатор, за допомогою яких на оператори може бути здійснена передача управління і ініційовано продовження подальшого виконання програми саме з данного оператора. Таку передачу управління  здйснює оператор безумовного переходу. Дані, з кими має справу программа, розподіляються на проблемні дані да службові дані. Службові дані використовуються для внутрішньої організації обчислень, а проблемні – це дані, над якими безпосередньо ведуться обчислення. До службових даних відноситься   лічильник команд PC (=Program Counter )(Див. тему : УМ).  На операційному рівні дія оператора goto М полягає в занесенні в лічильник команд адреси першої команди з групи команд, що відповідають  в машинному коді оператору з лейбою М.   

<продовження>::= continue ; 

Синт. Застосовується в  циклах.

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

<переривання>::= break ; 

Синт. Застосовується в  циклах і перемикачах.

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

<вихід_ з_функції>::= return[<значення_функції>] ; 

<значення_функції>>::= <вираз>

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

<присвоєння>::=   <Lvalue_вираз> [<операція>]= <вираз>;  

<вираз> ::=   <терм>  

<Lvalue_вираз>  ::=  <ідентифікатор >  | <індексація_покажчика>   | <розіменування_покажчика>   |<ідентифікація_поля_ структури>   

Синт. Типи Lvalue_виразу та виразу в операторі присвоєння мають співпадати або бути узгодженими.

Сем. 1) Обчислюється значення  виразу в лівій частині 2)  Обчислюється значення   Lvalue_виразу. 3) Якщо в поточному стані  немає змінної з іменем  , то до нього долучається нова змінна . У супротивному значення  змінної    замінюється  на .

Прикл.   x=x+a;

              x+=a;

              h=getchar();

<виклик_функції> ::= < імя_функції >([<список_фактичних_параметрів>]) ; 

<список_фактичних_параметрів> ::= <вираз >… < вираз >

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

Сем. Виконання виклику функції зводиться до наступних дій. 1)Ініціалізація параметрів та локальних даних.Параметрам функції, локальним даним (визначеним у тілі функції) та для збереження результату функції відводяться ділянки автоматичної памяті. Обчислюються значення  фактичних параметрів і присвоюються відповідним формальним параметрам. 2) Виконується модифіковане тіло функції, тобто тіло функції після етапу ініціалізації  параметрів та її власних даних. 3) Вихід. Реалізується або оператором  базовим оператором return або здійснюється автоматично відбувається після виконання останнього оператора в модифікованому тілі функціїї. В процесі виходу: а) припиняється доступ до автоматичної памяті, яка використовувалася в процесі виклику функції, б) у місце виклику повертається результат (=значення виразу в операторі return або «сміття», якщо в ньому відсутній вираз або  якщо вихід функції відбувається після останнього оператора в її тілі) і в) керування програмою повертається до функції, що містить даний виклик функції і  передається на наступний оператор за даним оператором виклику функції .

<oператор_вираз>::= < вираз > ; 

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

Прикл.   i++;  

              --k;

               2;

<структурований_опeрaтор>::= <cкладений_оператор> | <розгалуження>| <обхід> | <ітерація>    |<повторення> | <цикл> | <перемикач>

 

<cкладений_оператор>::= {<оператор><оператор> }

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

<розгалуження>::=if (<цілий_вираз>) <оператор> else <оператор>

Сем. Результат застосування до операторів  композиції розгалуження. При цьому нульове значення цілого виразу означає «лже», а всі інші – «істину».

<обхід>::=if(<цілий_вираз>)   <оператор> <oператор_вираз>::= < вираз > ; 

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

<ітрація>::= while (<цілий_вираз>)   <оператор>  <oператор_вираз>::= < вираз > ; 

Сем. 

Результат застосування до оператора  композиції ітерації. Оператор повторюється доки вираз не прийме значення 0

<повторення>::= do <оператор>  while (<цілий_вираз>) 

 

Сем. Результат застосування до оператора  композиції повторення. При цьому умовою  повторення оператора є ненульове значення(=«істина») цілого виразу.

<цикл>::= for ([<вираз1>];[<цілий_ вираз2>];[<вираз3>]) <оператор> 

Будь-який вираз і всі одночасно можуть бути відсутні. Відсутність другого виразу означає що він є  0.

Сем. Задається  складеним оператором :

{ ([<вираз1>]; while [(<цілий_вираз2>)] { <оператор>  >[<вираз3>;] } }   

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

<перемикач>::= switch (<цілий_вираз>) {  case <вираз_конст1 > : <оператор>оператор>

                                 …

                                        [default :<оператор><оператор>]

                                  

              case <вираз_констN > : <оператор><оператор>

                                                                       } 

        Всі вирази –константи мають бути попарно різні. Гілка з випадком default: має бути тільки одна ( якщо вона взагалі  присутня).

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

Прикл.   Обчислення  бі-факторіалу

#include < stdio.h >

 long bifactorial( unsigned int n)

 {unsigned long k,p;

       p= k= (n%2==0 ? 2 : 1);    /*  if (n%2==0) p=k=2; else p=k=1; */

       while (k<n) { k+=2;  /*  k=k+2; */

                            p*=k; /*  p=p*k; */

                          }

       return p;

   }

void main (void)

{ unsigned int m;

scanf(”%d”, &m); /* введення з клавіатури значення аргументу для обчислення бі-факторіалу */

printf(“\n%ld ”, bifactorial( m) ); /* виведення на екран значення  бі-факторіалу*/

}

long bifactorial2( unsigned int n)

 { unsigned long k,p;

     for ( p= k= (n%2==0 ? 2 : 1);  k<n;  k+=2)  p*=k;                            

    return p;

  }

Прикл.   В/В символів зі стандартніх потоків.  Копіювання файлу.

Аналіз

Вх: послідовність символів  у станд. вхідному потоці

Вих: та сама послідовність символів  тільки у станд. вихідному потоці

Зал:  (див. Вих.:)

Вим: Побудувати Сі – програму. Скористатися функціями getchar() та putchar().    

           int ch;

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

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

#include < stdio.h >

 void copyfile_kbd(void)

 {int ch;

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

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

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

                               }

 }

void main (void)

{ copyfile_kbd();

}

void copyfile_kbd2(void)

 {int ch;

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

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

 }

                                 

Прикл.   В/В символів зі стандартніх потоків.  Підрахунок слів.

Аналіз

Вх: послідовність символів  у станд. вхідному потоці

Вих:

Зал:   - кількість введених слів. Слово – це не порожня послідовність символів на вході, розташована між порожніми символами (), або на самому його початку - до першого порожнього символу.

Вим: Побудувати Сі – програму. Скористатися функціями getchar() та putchar().    

Проект. Ідея алгоритму полягає в том, щоб в процесі  введення символів контролювати ситуацію:  (1) чи знаходиться поточний символ в межах  чергового слова,  (2) чи за його  межами. Для цього вводиться змінна-прапорець state, яка має значення  ІN(=1)  у першому випадку і змінює його на OUT (=0) як тільки черговий символ виходить за межі поточного  слова. Лічильник слів  m  збільшується на 1, як тільки   змінна  state в черговий раз приймає значення ІN.

Прога.     

         /*  Підрахунок слів в потоці  stdin  */

#include < stdio.h >

#define ІN 1

#define OUT 0

long count_word(void)

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

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

       {

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

                                                          state=OUT;

           else /* прочитано непорожній символ */

                  if (state==OUT) { state=IN;

                                              m++;

                                            }                 

        }

    return m;

  }

void main (void)

{ printf(“\n%ld ”, count_word());

}

Прикл.   До Лабораторної роботи 2. Наближено протабулювати функцію  (*)  на інтервалі . При обчисленні значення функції враховувати тільки члени ряду, які не менші від машинного нуля в околі 1.0. Взяти точок табуляції, до числа яких включити і кінці інтервалу.

Аналіз

Вх:

Вих.: ,  

Зал: , де  ,     при   .

Вим:  Побудувати Сі – програму

Проект. З урахуванням особливостей машинної арифметики та повільного спадання ряду Тейлора  (*) для великих   функцію  є сенс подати  у вигляду добутку , де - відповідно ціла та дробова частини числа (). Покладемо , . Для обчислення функції  скористаємося  функцією qpow(x,n):

double qpow(double x, unsigned int n);   /*Швидке піднесення до степеня  */.

double exp1( double x)

{unsigned int k;

             k= x-floor(x);

             return ( qpow(exp(1), k)) ;

}

Для обчислення  функції   використаємо ряд (*). Рекурентні співвідношення будуть наступними.

Покладемо . ,

                  , .

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

double exp2( double x, double eps)

          { double s,a;

              for (s=a=1,k=0; a*x/(k+1)>=eps; a*= x/++k, s+=a);

              return s;

           }

Наступна функція dblnul (  x) обчислює числову константу – машинний нуль в околі  числа x  в  типі double, тобто найбільшу числову константу  в цьому типі, для якої виконується умова . Вона буде використана для обчислення машинного нуля в околі 1.0.

double dblnul ( double x)

 {double p;

           for (p=1; x+p!=x; p/= 2);       

    return p;

   }

Прога

        /*  Табулювання функціі   */

#include < stdio.h >

#define А  200.0

#define B  201.0

#define N  5

qpow(double x, unsigned int n);  /* швидке піднесення до степеня  */.

double exp1 ( double x)

{unsigned int k;

             k= x-floor(x);

             return ( qpow(exp(1), k)) ;

}

double exp2 ( double x, double eps)

          { double s,a;

              for (s=a=1,k=0; a*x/(k+1)>=eps; a*= x/++k, s+=a);

              return s;

   }

double exp_( double x)

{ return (exp1 (x) * exp2( floor(x), dblnul(1.0) ));}

double dblnul ( double x)

 {double p;

           for (p=1; x+p!=x; p/= 2);       

    return p;

   }

void main (void)

  { int i; double x;

     for ( i=1, x=a; i<=n ; i++ ) printf(\n\t%15e\t %15e”, x, exp_(x));

  }(”%...s

Впр.  Відлагодити   вище наведену  програму табулювання функціі

Прикл. Дія різних  форматів функції printf.

Розглянемо результат дії оператор printf(”%...s ”, ”hello, world” ); при різних варіантах керування полем виводу.

:%s:                :hello, world:   /* всього 14 символів */

”%10s               :hello, world:      

”%.10s              :hello, wor:   

”%-10s              :hello, world:   

”%.15s              : hello, world:   

”%-15s ”              :hello, world :   

”%15.10s”            :   hello, wor:   

”%-15.10 s         :hello, wor   :   

<безумовний_перехід> ::= goto <лейба_оператора>

P!

P := P * A;

Q mod 2 = 1

A := A*A;

    Q := Q div 2;

Q > 0

P := X;

P := 1;

N mod 2 = 0

N := !; X := !; Q := N; A := X;


 

А также другие работы, которые могут Вас заинтересовать

625. Практика проведения денежных реформ в странах Западной Европы 150 KB
  Денежные реформы Англии и выход из стерлинговых кризисов. Современное положение денежнной системы западноевропейских стран. Значение денежных реформ в развитии денежных систем. Средство выхода из кризисисного состояния и продолжения нормального функционирования национального хозяйства в целом.
626. Дефицитарность общения в детском и подростковом возрасте 154 KB
  Задачи медико-педагогической коррекции при дефицитарнсти общения у детей и подростков. Условия коррекционной работы в лечебно-педагогическом центре. Малая коррекционная группа. Особенности семей детей с дефицитарностью общения. Социально-психологическая работа с семьей аутичного ребенка.
627. Определение плотности горных пород методом гидростатического взвешивания 112 KB
  В ходе лабораторной работы мы определили плотность горных пород методом гидростатического взвешивания. В результате измерений получили, что σ ср= 0,12, максимальная погрешность при измерении образца составила 0,36.
628. Планування діяльності підприємства 584 KB
  Поряд із загальними принципами управління та планування. Планування об'єднує структурні підрозділи підприємства спільною метою. Виробничо-господарська діяльність підприємства, кадри в необхідній кількості і потрібної кваліфікації.
629. Работа с матрицами 159 KB
  Научиться работать с матрицами в MathCAD. Ввести заданные в столбце 1 матрицы. Транспонировать заданные матрицы.
630. Разработка микропроцессорного устройства управления шаговым двигателем 340.5 KB
  Расчет остальных элементов микропроцессорного устройства управления шаговым двигателем. Разработать систему управления двумя шаговыми двигателями семейства FL35ST и 25BYT на базе микроконтроллера Atmega16. Связь с верхним уровнем осуществить через протокол Bluetooth. Для обратной связи использовать датчик контрастной полосы.
631. Транспортные, информационные и документальные потоки ООО Викторг 140 KB
  Транспортно-технологическая схема доставки и грузопереработки. Характеристика транспорта предприятия. Обработка и анализ статистических данных работы транспорта. Схема укладки грузов на подвижном составе.
632. Расчет экстенсивных свойств в результате протекания химической реакции 2NO2=2NO+O2 3.8 MB
  ВЛИЯНИЕ ТЕМПЕРАТУРЫ НА ИЗМЕНЕНИЕ СТАНДАРТНЫХ МОЛЬНЫХ ЭНТАЛЬПИЙ, ЭНТРОПИЙ И ЭНЕРГИЙ ГИББСА. РАСЧЕТ ВЕЛИЧИН СТАНДАРТНОЙ МОЛЬНОЙ ИЗОБАРНОЙ ТЕПЛОЕМКОСТИ РЕАКЦИИ. РАСЧЕТ РАВНОВЕСНОГО СОСТАВА СИСТЕМЫ ГОМОГЕННОЙ ГАЗОВОЙ РЕАКЦИИ.
633. Безпека у надзвичайних ситуаціях 125 KB
  Безпека у надзвичайних ситуаціях – це стан захищеності населення, робітників та службовців, об'єктів економіки та довкілля від небезпеки у надзвичайних ситуаціях.