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;


 

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

30967. УПРАВЛЕНИЯ ЧЕЛОВЕЧЕСКИМИ РЕСУРСАМИ ОАО «СО–ЦДУ ЕЭС» 168.5 KB
  2 Проблемы обеспечения надежности профессиональной деятельности и сохранения здоровья персонала 8 2.3 Обеспечение полной профессиональной адаптации ведущая проблема надёжности деятельности и сохранения здоровья персонала 9 2.4 Психофизиологическое сопровождение подготовки и переподготовки персонала 9 2.5 Аттестация персонала 9 2.
30969. Закрытое акционерное общество «ПОЛИСОРБ» г.Челябинск 645 KB
  Создаваемое Предприятие должно обеспечить выпуск нового лекарственного препарата – сорбента широкого спектра действия для удовлетворения потребностей всех групп населения в эффективной профилактике и лечении отравлений, аллергии, кишечных инфекций, кожных заболеваний, дисбактериоза, интоксикации различного происхождения
30970. ЗАО «Консорциум – Транспортно-модульные системы» 809 KB
  Рисунок 1 Комплекс по переработке бобов сои 8 Рисунок 2 Производство текстурированного соевого белка 26 Рисунок 3 График окупаемости NPV 73 Рисунок 4 Анализ чувствительности проекта 75 Перечень информационных и расчетных таблиц Таблица 1 Уровень среднедушевого потребления основных продуктов питания в России 16 Таблица 2 Динамика среднедушевого потребления белков за счет основных продуктов питания в РФ 17 Таблица 3 Выход основных продуктов переработки сырых соевых бобов 23 Таблица 4 Состав соевой муки 23 Таблица 5 Содержание в...
30971. Бизнес-план “Internet-провайдера ООО “Lucky Net” 493 KB
  Эти условия определяются положительным ответом на два вопроса: Что я получу от успешной реализации бизнесплана и Какова опасность риска потери вложенных в дело денег Резюме Фирма Lucky Net создаваемая в виде общества с ограниченной ответственностью планирует работать в сфере Internetпровайдинговых услуг которые будут заключаться в предоставлении неограниченного 24 часа в сутки доступа в Internet по телефонным линиям частным лицам Чернигова. Размер этой суммы планируется в будущем снижать чтобы сделать Internet еще более...
30972. Бизнес-план “Фаст-фото” 365.5 KB
  Настоящий проект представляет собой создание нового предприятия “Фаст-Уссури”, путем учреждения общества с ограниченной ответственностью с тремя учредителями и участием заемного капитала в форме лизинга на покупку оборудования в сфере предоставления услуг фотопечати
30973. Бизнес-план модернизации технологической линии по производству асбестоцементных листов на ОАО «БелАЦИ» 700 KB
  В данной работе предстоит проанализировать структуру и жизнедеятельность ОАО «БелАЦИ», его положение на рынке, сильные и слабые стороны; разработать план маркетинга, включающего маркетинговую стратегию, каналы распространения и эффективные рыночные коммуникации, позволяющего занимать стабильное положение на рынке
30974. ИММУНОГЕНЕТИКА 16.11 KB
  Начало иммуногенетики животных связывают с работами по исследованию крови коз 1900 г. Еще больший интерес вызвали так называемые иммунные антитела которые образуются в сыворотке крови при попадании в нее эритроцитов других животных причем к тем антигенным факторам эритроцитов которых нет в собственных клетках. По этому признаку кровяные факторы распределяются по системам групп крови которые не изменяются в течение жизни т.