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;


 

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

45333. Конституционно-правовой статус члена Совета Федерации и депутата Государственной Думы 25.69 KB
  Конституционно-правовой статус члена Совета Федерации и депутата Государственной Думы Конституционно-правовой статус члена Совета Федерации и депутата Государственной Думы определяется Конституцией РФ ст. О статусе члена Совета Федерации и депутата Государственной Думы Федерального Собрания Российской Федерации. Депутатом Государственной Думы является избранный представитель народа уполномоченный осуществлять в Государственной Думе законодательные и иные полномочия предусмотренные Конституцией РФ и федеральным законом. Срок полномочий...
45334. Система законодательных (представительных) и исполнительных органов государственной власти субъектов Российской Федерации 20.8 KB
  Система законодательных представительных и исполнительных органов государственной власти субъектов Российской Федерации устанавливается ими самостоятельно в соответствии с основами конституционного строя Российской Федерации и ФЗ от 06. Об общих принципах организации законодательных представительных и исполнительных органов государственной власти субъектов Российской Федерации.Образование формирование деятельность законодательных представительных и исполнительных органов государственной власти субъектов Российской Федерации их...
45335. Законодательный процесс в РФ 25.93 KB
  В составе городского поселения также могут находиться сельские населенные пункты не имеющие статуса сельских поселений в которых местное самоуправление осуществляется населением непосредственно и или через выборные и иные органы местного самоуправления. Городской округ городское поселение которое не входит в состав муниципального района и органы местного самоуправления которого осуществляют полномочия по решению установленных законом вопросов местного значения поселения и вопросов местного значения муниципального района а также могут...
45336. Подходы к построению систем искусственного интеллекта 33 KB
  Структурный подход Под структурным подходом подразумевается попытки построить искусственный интеллект путём моделирования структуры человеческого мозга. Основной моделируемой структурной единицей в персептронах как и в большинстве других вариантов моделирования мозга является нейрон. Позднее возникли и другие модели которые обычно называют нейронные сети . Эти модели различаются по строению отдельных нейронов по топологии связей между ними и по алгоритмам обучения.
45337. Понятие дерева возможностей 36.5 KB
  Дерево быстро разрастается рис.1 – Дерево возможных продолжений шахматной игры Все вершины могут быть двух типов. Таким образом дерево возможностей представляет собой чередующиеся слои альфа и бетавершин. Если бы дерево можно было обследовать полностью т.
45338. Основные понятия искусственного интеллекта 40 KB
  Интеллектом называется способность мозга решать задачи путём приобретения запоминания и целенаправленного преобразования знаний в процессе обучения на опыте и адаптации к разнообразным обстоятельствам. Искусственный интеллект – это одно из направлений информатики целью которого является разработка аппаратнопрограммных средств позволяющих пользователюнепрограммисту ставить и решать свои традиционно считающиеся интеллектуальными задачи общаясь с компьютером на ограниченном подмножестве естественного языка. Понятие интеллектуальной задачи...
45339. Знания как часть любой интеллектуальной системы 38 KB
  При этом возникает естественный вопрос что такое знания и чем они отличаются от обычных данных обрабатываемых компьютером. Знания являются более сложной категорией информации по сравнению с данными. Они описывают не только отдельные факты но и взаимосвязи между ними поэтому знания иногда называют структурированными данными.
45340. Проблемная область искусственного интеллекта 35 KB
  Для этого разрабатываются специальные модели представления знаний и языки для описания знаний выделяются различные типы знаний. Изучаются источники из которых система может брать знания и создаются процедуры и приёмы с помощью которых возможно приобретение знаний интеллектуальными системами. Проблема представления знаний в системах искусственного интеллекта чрезвычайно актуальна поскольку функционирование данных систем опирается на знания о проблемной области хранящиеся на компьютере.
45341. Проблема распознавания образов 67.5 KB
  В своей повседневной жизни человек настолько легко справляется с задачами распознавания что это считается само собой разумеющимся. В целом проблема распознавания образов состоит из двух частей: обучения и распознавания. За обучением следует процесс распознавания новых объектов который характеризует действия уже обученной системы.