Інтернет Windows Android

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

61.1K

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

Верстка сайту - ремесло для присвячених

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


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

У процесі верстки кодом html відбувається розбивка «скелета» сайту на частини. А з допомогою css (каскадних таблиць стилів) Задаються розміри його «кісток», колір і розташування.

Розрізняють декілька видів верстки:

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

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


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

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

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

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

II. Блокова - в даний момент є основним способом верстки. На відміну від табличній блокова верстка має ряд переваг:

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

Основним недоліком блокової верстки є якась « двозначність»Розуміння її коду різними браузерами. Тому часто html сторінки доводиться «доводити» шляхом використання спеціальних хаков.

З появою блокової верстки народилося таке поняття, як «кроссбраузерность». Через відмінності відображення одного і того ж елемента в різних браузерах верстальщикам доводиться вставляти в основний html цілі шматки коду (хакі).

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

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

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

Як відбувається блокова верстка?

Перед початком верстки готовий psd макет сайту в графічному редакторі розрізають на блоки (шари). В окрему папку поміщають вирізані фонові картинки, Які будуть прикріплюватися окремо до кожного шару:


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

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

Більш детально ознайомитися з усіма властивостями css можна з технічної документації до мови.

Повний код прикладу index.html:

Приклад блочної верстки

контент



Вміст файлу style.css:

body (background: # f3f2f3; color: # 000000; font-family: Trebuchet MS, Arial, Times New Roman; font-size: 12px; ) #Container (background: # 99CC99; margin: 30px auto; width: 900px; height: 600px;) #header (background: # 66CCCC; height: 100px; width: 900px;) #navigation (background: # FF9999; width: 900px; height: 20px;) #menu (background: # 99CC99; float: left; width: 200px; height: 400px;) #content (background: # d2d0d2; float: right; width: 700px; height: 400px;) # clear (clear: both;) #footer (background: # 0066FF; height: 80px; width: 900px;)

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

Процедури і функції. блокова структура програми. Параметри.

приклад

приклад

приклад

Дан масив дійсних чисел А (10). впорядкувати даний масив по зростанню його елементів, ᴛ.ᴇ. зробити так щоб кожен наступний елемент масиву виявився б більше попереднього.

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

Ідея цього алгоритму полягає по суті в тому, що елементи вихідного масиву порівнюються попарно - спочатку a 1 c a 2, потім a 2 c a 3, далі a 3 з a 4 і т.д. У разі якщо перший елемент в парі більше другого, то змінюють їх чисельні значення, завдяки чому перший елемент отримує значення другого, а другий - першого. В іншому випадку ніяких замін в парі не виробляють, а переходять до порівняння елементів другої пари.

Τᴀᴋᴎᴍ ᴏϬᴩᴀᴈᴏᴍ, відбувається як би поступове "проштовхування" найбільшого елемента в кінець масиву, причому функцію "штовхача" в алгоритмі виконує внутрішній цикл. Як тільки найбільший елемент масиву займе призначеного йому останнє 10-е місце, описану процедуру повторюють з рештою неврегульованими 9-ю елементами, завдяки чому найбільший з решти елемент займе передостаннє місце в масиві і т.д.

Для отримання бажаного результату таку процедуру потрібно виконати дев'ять разів, причому з кожним разом число повторень внутрішнього циклу має зменшуватися на 1.

Це завдання вирішує зовнішній цикл. Його параметр, пробігаючи від повторення до повторення значення 9,8,7, ..., 1 служить не тільки лічильником числа виконаних повторень, але, в той же час, і найбільшим значенням параметра внутрішнього циклу.

program sort;

var

i, k: intege r;

b: real ;

a: array ofreal ;

begin

write ( 'введіть масив -');

for i: \u003d 1 to 10 do readln (a [i]);

writeln ( "вихідний масив");

for i: \u003d 1 to 10 do writeln (a [i]: 5: 2);

for i: \u003d 9 downto 1 do

for k: \u003d 1 to i doif a [k]\u003e a then

begin

b: \u003d a [k]; a [k]: \u003d a; a: \u003d b

end

writeln ( "впорядкований масив");

for i: \u003d 1 to 10 do write (a [i]: 5: 2)

end .

Дана матриця В (20 * 20). Сформувати вектор С (20), кожен елемент якого є твір елементів стовпця матриці за винятком елемента͵ лежачого на головній діагоналі. Індексацію рядків і стовпців початкової матриці почати з нуля, індексацію елементів вектора з 10.

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

program massiv;

b: array ofreal ;

c: array ofreal ;

p: real ;

m, n: integer ;

begin

for m: \u003d 0 to 19 do

for n: \u003d 0 to 19 do readln (b);

for n: \u003d 0 to 19 do

begin

p: \u003d 1; for m: \u003d 0 to 19 do

if m<>n then (Формування твори)

p: \u003d p * b; (Елементів стовпця матриці)

(За винятком діагонального)

c: \u003d p; (Запис сформованого)

(Елемента вектора в осередок пам'яті)

end ;

for n: \u003d 10 to 19 do writeln (c [n]: 10: 3)

end .

Дана матриця МАТ (5 * 5), що складається з речових елементів. Поміняти місцями рядки матриці, що містять максимальний і мінімальний елементи.

program MinMax;

type

m \u003d array ofreal ;

var

mat: array of m;

maxi, mini, i, j, i1, j1: integer ;

begin

write ( 'введіть матрицю -');

for i: \u003d 1 to 5 dofor j: \u003d 1 to 5 do read (mat);

i1: \u003d 1; j1: \u003d 1; (Індекси мінімального елемента)

i2: \u003d 1; j2: \u003d 1; (Індекси максимального елемента)

for i: \u003d 1 to 5 do

for j: \u003d 1 to 5 do

if mat\u003e mat

then

begin

i2: \u003d i; j2: \u003d j (запам'ятати індекси нового максимуму)

end

else

if mat

then

begin

i1: \u003d i; j1: \u003d j; (Запам'ятати індекси нового мінімуму)

end ;

str: \u003d mat; (Заміна рядки матриці mat,)

mat: \u003d mat; (Містить максимальний)

mat: \u003d str; (Елемент, рядком з минималь-)

(Ним елементом і навпаки)

for i: \u003d 1 to 5 do

begin

for j: \u003d 1 to 5 do write (mat);

end

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

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

Відмінність від типової складається по суті в тому, що визначаються не самі максимальний і мінімальний елементи матриці, а їх індекси. Для зберігання індексів в процесі рахунку використовуються змінні i1, j1 - для мінімального елемента і i2, j2 - длямаксімального.

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

< Что такое подпрограмма и для чего она нужна >

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

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

Writeln ( "Це перевірка");

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

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

procedure ім'я-процедури (параметри);

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

function імя_функциі (параметри): тип даних;

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

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

Процедури і функції. Блокова структура програми. Параметри. - поняття і види. Класифікація та особливості категорії "Процедури і функції. Блокова структура програми. Параметри." 2017, 2018.

4.8. Блокова структура.

Мова "C" не є мовою з блочною структурою в смис-

ле PL / 1 або Алгола; в ньому не можна описувати одні функції

всередині інших.

Змінні ж, з іншого боку, можуть визначатися по

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

чаю ініціалізацію) можуть слідувати за лівою фігурною скоб-

кой, що відкриває будь-який оператор, а не тільки за тієї, з кото

рій починається тіло функції. Змінні, описані таким про-

разом, витісняють будь-які змінні із зовнішніх блоків, що мають

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

правою фігурної дужки. Наприклад, в

INT I; / * DECLARE A NEW I * /

FOR (I \u003d 0; I< N; I++)

Областю дії змінної I є "істинна" гілка

IF; це I ніяк не пов'язане ні з якими іншими I в програм-

Блокова структура впливає і на область дії зовнішніх

змінних. Якщо дано опису

Те поява X всередині функції F відноситься до внутрішньої пере-

тимчасової типу DOUBLE, А поза F - до зовнішньої цілої змінної.

це ж справедливо по відношенню до імен формальних параметрів:

Усередині функції F ім'я X відноситься до формального параметру, а

ні до зовнішньої змінної.

4.9. Ініціалізація.

Ми до сих пір вже багато разів згадували ініціалізацію, але

завжди мимохідь, серед інших питань. Тепер, після того

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

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

Якщо явна ініціалізація відсутня, то зовнішнім і ста-

тическим змінним присвоюється значення нуль; автомати-

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

поділені значення (сміття).

Прості змінні (НЕ масиви або структури) можна іні-

зованих при їх описі, додаючи слідом за ім'ям знак

рівності і константний вираз:

CHAR SQUOTE \u003d "\\";

LONG DAY \u003d 60 * 24; / * MINUTES IN A DAY * /

Для зовнішніх і статичних змінних ініціалізація вико-

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

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

в функцію або блок.

У разі автоматичних і реєстрових змінних ініціаліза-

тор не зобов'язаний бути константою: насправді він може бути

будь-яким значущим виразом, яке може включати определен-

ні раніше величини і навіть звернення до функцій. наприклад,

ініціалізація в програмі бінарного пошуку з глави 3 могла

б бути записана у вигляді

INT HIGH \u003d N - 1;

INT LOW, HIGH, MID;

За своїм результатом, ініціалізації автоматичних перемен-

них є скороченим записом операторів присвоєння.

Яку форму віддати перевагу - в основному справа смаку. ми зазвичай

використовуємо явні привласнення, тому що ініціалізація в

описах менш помітна.

Автоматичні масиви не можуть бути ініційовані. внеш-

ня і статичні масиви можна ініціалізувати, поміщаючи

слідом за описом укладений у фігурні дужки список на-

чільного значень, розділених комами. наприклад програма

підрахунку символів з глави 1, яка починалася з

INT C, I, NWHITE, NOTHER;

NWHITE \u003d NOTHER \u003d 0;

FOR (I \u003d 0; I< 10; I++)

Ожет бути переписана у вигляді

INT NDIGIT \u003d (0, 0, 0, 0, 0, 0, 0, 0, 0, 0);

MAIN () / * COUNT DIGITS, WHITE SPACE, OTHERS * /

Ці ініціалізації фактично не потрібні, так як все прісваі-

ваемие значення рівні нулю, але хороший стиль - зробити їх

явними. Якщо кількість початкових значень менше, ніж ука-

занний розмір масиву, то інші елементи заповнюються ну-

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

є помилкою. На жаль, не передбачена можливість

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

не можна ініціалізувати елемент в середині масиву без пере-

числения всіх попередніх.

Для символьних масивів існує спеціальний спосіб

ініціалізації; замість фігурних дужок і ком можна ис

використовувати рядок:

CHAR PATTERN \u003d "THE";

Це скорочення довшою, але еквівалентної записи:

CHAR PATTERN \u003d ( "T", "H", "E", "\\ 0");

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

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

цьому конкретному випадку розмір дорівнює чотирьом (три символи

плюс кінцеве \\ 0).


Підставах. При цьому філософська абстракція мови виявляється нерозривно пов'язана з основними темами і рухами філософії в цілому. Більш конкретно, на ранні стадії традиційно розглядається в рамках АФ аналізу буденної мови глибокий вплив справила філософія Дж. Е. Мура, особливо його вчення про здоровий глузд, згідно з яким такі поняття, як «людина», «світ», «я», « зовнішній світ", " ...

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

Рисуночное словесно-складовий лист). Пам'ятники среднееламского періоду (14-12 ст. До н.е.) виконані аккадської клинописом. Пам'ятники новоеламского періоду відносяться до 8-6 ст. до н.е. Була офіційною мовою в перській державі Ахеменідів в 6-4 ст. передбачається, що він, піддавшись впливу древнеперсидского, зберігся до раннього середньовіччя. 7. Бурушаскі мову Мова бурушаски (...

... / діалект), скіфський, согдийский, среднеперсідскій, таджицький, таджріші (мова / діалект), талиська, татський, хорезмійський, хотаносакскій, шугнано-рушанская група мов, ягнобська, язгулямскій і ін. Вони відносяться до індоіранської гілки індоєвропейських мов. Області поширення: Іран, Афганістан, Таджикистан, деякі райони Іраку, Туреччини, Пакистану, Індії, Грузії, Російської Федерації. Загальна ...

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

За допомогою модулів можна створювати бібліотеки підпрограм, які можуть зберігатися як у вигляді вихідного, так і у вигляді об'єктного коду (коду, вже готового до спільної компіляції та об'єднання з іншими модулями). У Delphi відкомпільований об'єктний код модуля зберігається в файлах з розширенням «.dpu».

Структура модуля аналогічна структурі програми на мові Паскаль. Тема для модуля обов'язковий і починається зі слова UNIT (замість PROGRAM як в звичайній програмі):

Unit<имя модуля>;

Ім'я модуля повинно співпадати з ім'ям файлу на мові Pascal. Коли Delphi автоматично генерує різні модулі, він робить так, щоб ім'я модуля збігалося з ім'ям файлу.

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

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

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

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

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

Uses M1, М2 ...;

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

Інтерфейсна частина закінчується з початком виконавчої частини. Виконавча частина починається з ключового слова Implementation. Вона містить тіла всіх процедур і функцій, описаних в інтерфейсній частини. Вона може включати локальні мітки функцій і розділів операторів. Після слова Implementation також може слідувати слово Uses зі списком модулів, які використовуються у виконавчій частині. Далі вказуються мітки, типи, константи, змінні, процедури і (Ьункпіі модуля.

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

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

Коротко синтаксис опису модуля виглядає так:

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

<имя модуля>. <имя переменной>.

Приклад 10.1. Розглянемо можливості взаємозв'язку модулів. Програма може вийти коротше, якщо дозволити модулів використовувати внутрішні елементи один одного.

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

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

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

Зазвичай результат модулярізаціі зображується у вигляді графа взаємозв'язку модулів і (або) підсистем. Основою ( «коренем») цього графа є головна програма. Кожна вершина графа являє собою модулі, а дуги, що з'єднують вершини, показують взаємозв'язок модулів між собою.

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

Тут основна програма Р розбивається на три основних модуля М1, М2, МЗ. З цих модулів в програмі використовуються інтерфейсні елементи А, В, С (з першого модуля), D (з другого модуля), F, G, K, L (з третього модуля). Кожен з цих модулів розбивається на більш дрібні, наприклад, М2 розбивається на М2.1, М2.2, М2.3 і т.д. З цієї схеми, наприклад, видно перехресні посилання між модулями М2 і М3, а також між М2.2 і М2.3.

Після завершення модулярізаціі кожен модуль розподіляться для кодування між програмістами з метою незалежного написання коду та налагодження. Однак в таких випадках часто виникає ситуація, коли в батьківському модулі передбачається використання процедур і функцій дочірніх модулів, але дочірні модулі ще не закодовані іншими програмістами. Наприклад, в модулі МОЗ використовуються елементи K, L з дочірніх модулів, але ці модулі поки не готові. Як бути програмісту, який реалізує код модуля МОЗ? Вихід з цієї ситуації здійснюється за допомогою написання в батьківському модулі процедур (або функцій) «заглушок», які по імені і параметрам повністю збігаються з елементами К, L. Заглушки дозволяють компілювати і виконувати програму в налагоджувальному режимі.

«Заглушка» - процедура представлена \u200b\u200bточної специфікації заголовка (назва та параметри) і порожнім тілом. «Заглушка» - функція представлена \u200b\u200bточної специфікації заголовка (назва та параметри) і має в тілі всього один оператор, який повертає значення функції. Наприклад, тіло функції-заглушки L може бути таким:

формула "src \u003d" http://hi-edu.ru/e-books/xbook691/files/ris-page173.gif "border \u003d" 0 "align \u003d" absmiddle "alt \u003d" (! LANG:

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

Можливості підключення модуля визначається як міра незалежності складових частин модуля. Чим вище зв'язність модуля, тим краще результат проектування. Типи зв'язності (в дужках вказано коефіцієнт сили зв'язності):

  • функціональний (сильна зв'язність) - 10;
  • послідовна - 9;
  • комунікативна - 7;
  • процедурна - 5;
  • тимчасова - 3;
  • логічна - 1;
  • за випадковим збігом (слабка зв'язність) - 0.

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

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

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

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

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

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

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

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

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

Часто у великих програмах використовуються підпрограми для реалізації допоміжних алгоритмів. У ЯА підпрограми оформляються у вигляді процедур.

опис процедур

(Ім'я проц.) PROC (параметр) (тіло проц.) (Ім'я проц.) ENDP де (ім'я проц.) - має повторюватися двічі і використовується для звернення до процедури; (Параметр) може приймати одне з двох значень - (За замовчуванням) або . До близької (внутрішньої) процедурі можна звертатися тільки з того сегмента команд, де вона описана. До далекої (зовнішньої) процедурі можна звертатися з будь-яких сегментів команд програми, в тому числі і з того, де вона описана. Імена і мітки, описані в процедурі, що не локалізуються всередині неї, тому повинні бути унікальними в програмі . Хоча в АЯ можна описати одну процедуру всередині іншої, ніякої вигоди це не дає і зазвичай не використовується.

виклик процедур

На ЯА всі переходи між основною програмою і процедурою потрібно організовувати самим. Якщо з процедури можливе повернення в DOS, то її можна викликати командою переходу на ім'я процедури JMP (ім'я проц.) Якщо потрібен повернення в зухвалу програму, то найпростіше використовувати команду звернення CALL (ім'я проц.) Тоді в тілі процедури повинна бути команда повернення RET Є інша можливість: запам'ятати адресу повернення з використанням стека і організувати повернення командами переходів. При виклику процедури слід враховувати параметри, що передаються процедурі, і її розташування відносно точки виклику, тобто тип переходу в команді CALL визначається автоматично, наприклад (Для процедури p). P CALL P Якщо це - близький виклик (NEAR), то робляться такі дії: Stack: \u003d AB, IP: \u003d offset P де АВ - адреса повернення, тобто ефективний адреса команди, наступної за викликом; Далекий виклик (FAR) забезпечує дії: Stack: \u003d CS, Stack: \u003d AB, CS: \u003d seg P, IP: \u003d offset P Якщо опис процедури знаходиться в сегменті нижче команди виклику, то слід вказати атрибут переходу оператором PTR. наприклад, CALL FAR PTR P; дальній виклик P

Розташування процедур в сегменті

    внутрішні процедури знаходяться в одному сегменті з викликає програмою.
При цьому можливі 3 варіанти розташування: а) Всі процедури розміщені раніше основний (викликає) програми, яка може бути також оформлена у вигляді процедури. наприклад: Text SEGMENT 'code' ASSUME CS: text, DS: data, SS: stack A1 PROC ... RET A1 ENDP Main PROC MOV AX, data MOV DS, AX ... CALL A1 ... MOV AX, C400h INT 21h Main ENDP Text ENDS Data SEGMENT ... Data ENDS Stack SEGMENT 'stack' ... Stack ENDS END Main б) всі процедури - нижче точки виклику. в) процедури - всередині основної процедури, можливо навіть, що процедура всередині іншої процедури (хоча ніякої вигоди це не дає) наприклад, ... Main PROC ... CALL A1 ... MOV AX, C400h INT 21h A1 PROC ... RET A1 ENDP Main ENDP Text ENDS 2) зовнішні процедурирозташовуються в інших сегментах або в інших файлах. например, текст основної програми знаходиться у файлі P.asm Text SEGMENT public 'code'; об'єднання модулів послідовно; до загального сегмент ASSUME CS: text, DS: data, SS: stack EXTRN stop: proc; оголошення зовнішнього імені Main PROC ... CALL Stop ... Main ENDP Text ENDS Data SEGMENT ... Data ENDS Stack SEGMENT 'stack' ... Stack ENDS END Main Оригінальний текст процедури знаходиться в файлі P1.asm Text SEGMENT public 'code' ASSUME CS: text PUBLIC stop; оголошення імені доступним ззовні Stop proc ...

Stop ENDP text ENDS END; кінець файлу без точки входу Об'єднання цих файлів відбувається на етапі компонування, тобто потрібно роздільна трансляція. Наприклад, для MASM MASM / ZI PR MASM / ZI P1 де ZI - опція, що дозволяє помістити в об'єктний файл повну інформацію про номери рядків і символах вихідного модуля (ІМ). Після утворення PR.obj і P1.obj їх потрібно скомпонувати в єдиний завантажувальний файл LINK / C0 PR P1, COMPOZ де С0 - опція, передає в завантажувальний файл символьну інформацію, що дозволяє отладчику CV виводити на екран повний текст ІМ, включаючи мітки та коментарі. Модуль COMPOZ.exe готовий до виконання. Можна, можливо підключити процедуру з бібліотеки. Для цього перед сегментами ІМ поміщається директива INCLUDE (ім'я файлу бібліотеки) например, для підключення файлу IO.asm слід записати INCLUDE IO.asm S SEGMENT 'stack' ... S ENDS D SEGMENT 'data' ... D ENDS C SEGMENT 'code' ASSUME CS: C, SS: S, DS: D Begin: ... ... C ENDS END Begin

Передача параметрів між процедурами (організовується за бажанням програміста)

    Передача параметрів через регістри МП
Передавати значення фактичних параметрів можна через регістри МП за бажанням програміста. наприклад,; процедура обчислення AX: \u003d max (AX, BX) max proc far CMP AX, BX JGE Max1 MOV AX, BX Max1: RET max endp ...; в основний процедурі ... MOV AX, A; підготовка параметрів MOV BX, B; до виклику процедури CALL max MOV C, AX; збереження результату ...
    Передача параметрів за посиланнямозначає передачу адреси (імені) осередки пам'яті, що відповідає фактичному параметру (передача іменованого значення з асемблера в Pascal). Для цього можна використовувати ім'я комірки пам'яті або завантажити адреса перед викликом процедури в регістр (BX, BP, SI або DI, тому що в процедурі можна використовувати ці регістри для адресації).
наприклад, Командою LEA BX, B CALL ......
    Передача параметрів через стек.
Передача параметрів через регістри обмежена їх невеликою кількістю. Якщо параметрів багато (більше 5-ти), їх передають через стек наступним чином: - Основна програма записує в стек фактичні параметри (значення або адреси); - У процедурі використовуються параметри, записані в стек. наприклад: ; виклик p (a1, ..., ak) PUSH a1 ... PUSH ak CALL p ... У процедурі можна використовувати додатковий покажчик стека BP, але на початку процедури слід зберегти значення BP, яке використовувалося в зухвалій програмі, тобто ; початок процедури Р P proc PUSH BP; збереження BP MOV BP, SP; настройка BP на вершину стека ... Потім можна використовувати базову адресацію. Наприклад, для близького виклику - адреса повернення, занесений в стек автоматично, - адреса останнього параметра ak. До повернення з процедури слід відновити BP командою POP BP потім очистити стек від переданих параметрів, щоб він не перевантажувався при багаторазовому виклику процедур, тобто встановити в SP значення, на 2 * k більше, ніж було після виклику процедури. Є 2 можливості коректного повернення з процедури. а) коригувати SP в зухвалій програмі
; кінець процедури ; в зухвалій програмі
POP BP CALL p
RET ADD SP, 2 * k; корекція SP
P ENDP
б) використовувати команду повернення з відновленням стека, що має вигляд для близького виклику RET (cnt) де (cnt) - лічильник (константний вираз), розміром слово. Команда виконує наступні дії: IP: \u003d Stack SP: \u003d SP + (cnt) Тоді кінець процедури має вигляд: POP BP RET 2 * kp ENDP Для далекого виклику процедури команда повернення має вигляд RET (cnt) і виконує наступні дії: IP: \u003d Stack CS: \u003d Stack SP: \u003d SP + (cnt) При такому поверненні з процедури в зухвалій програмі додаткові дії не потрібні.
    Проблема збереження регістрів при зверненні до процедури
Щоб процедура не псувала значення регістрів, які використовувалися в зухвалій програмі, потрібно в тексті процедури перед використанням будь-якого регістра зберегти його «старе» значення в стеку, а в кінці процедури всі збережені значення відновити. наприклад, Якщо в процедурі буде використовуватися регістр CH, то його слід зберегти в стеці, але стек запам'ятовує тільки зі слова, тому в процедурі буде фрагмент: PUSH CX; збереження «старого» CX MOV CX, 0; використання CX в процедурі ...; перед виходом з процедури POP CX; відновлення «старого» CX Таким чином, вийде узагальнена схема близькою (NEAR) процедури з параметрами, переданими через регістри і через стек

(Ім'я проц) proc

PUSH BP для обслуговування

Mov BP, SP стека

PUSH збереження регістрів,

використовуваних в процедурі

тіло проц.

РОР ... відновлення регістрів

РОР ВР відновлення BP