МІНІСТЕРСТВО ОСВІТИ І НАУКИ, МОЛОДІ ТА СПОРТУ УКРАЇНИ
НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ «ЛЬВІВСЬКА ПОЛІТЕХНІКА»
Кафедра САПР
Звіт
до лабораторної роботи №9
на тему «ФУНКЦІЇ ЗІ ЗМІННИМ ЧИСЛОМ ПАРАМЕТРІВ.
КОМАНДНА СТРІЧКА, ПАРАМЕТРИ ФУНКЦІЇ MAIN»
з курсу «Проблемно-орієнтовані мови програмування»
Мета роботи
Поглиблене вивчення можливостей функцій зі змінним числом параметрів і використання параметрів функції main.
Теоретичні відомості
У С/C++ поряд з використанням функцій з фіксованим числом параметрів можна використовувати функції зі змінним числом параметрів, тобто функції, у які можна передавати дані, не описуючи їх у прототипі й заголовку функції. Описи цих даних заміняються трьома крапками. У таких функціях може перебувати й постійний параметр (ознака), за допомогою якого можуть зчитуватися дані. Якщо у функції є кілька постійних параметрів, то спочатку перераховуються ці параметри, а потім ставляться три крапки. Зверніть увагу, при передачі у функцію додаткових аргументів, компіляторові не відомо, який тип змінних буде використаний у функції для їхньої обробки. Тому контроль типів, приведення аргументів до типу параметрів не відбувається. Необхідні перетворення повинен передбачити програміст. Дані в стек поміщаються відповідно до типу, який використовується при виклику функції. В C++ повинен бути хоча б один фіксований параметр.
Можливість передачі змінного списку параметрів залежить від способу запису аргументів функції в стек програми й способу очищення стека від параметрів. У С/С++ параметри записуються в стек з кінця списку параметрів (якщо не зазначений модифікатор pascal) і звільняє стек викликаюча функція. Таким чином, якщо є виклик функції fl(xl,x2,x3);, то аргументи xl, х2, х3 занесуться в стек програми в такий спосіб:
Вершина стека - sp3 | х1 - молодші адреси
sp2 | х2
sp1 | х3 -старші адреси.
У мові Паскаль стек від параметрів звільняє викликаючий модуль. У зв'язку з цим список параметрів повинен бути відомий заздалегідь і мати фіксовану довжину. Аргументи в стек поміщаються в порядку їхнього надходження;
Вершина стека - sp3 | х3 - молодші адреси
sp2 | х2
sp1 | х1 -старші адреси.
Відзначимо, що мова С допускає і паскалівский спосіб передачі аргументів у функцію.
Рекомендуються два способи задання довжини змінного списку параметрів:
- пересилання у функцію числа аргументів;
- завдання ознаки кінця списку аргументів.
Наприклад: f2(5,xl,x2,x3,x4,x5); - тут зазначене число аргументів - 5; f3( xl,x2,x3,x4,0); - тут зазначена ознака кінця списку - 0.
Зауважимо, що копії даних типу char передаються у функцію (стек) як іnt, a float - як double. Реалізувати функції зі змінним числом параметрів можна трьома способами:
- використовуючи вказівник без типу, наприклад: voіd *pv;
- використовуючи вказівник, що відповідає типу змінних списку параметрів, наприклад:
іnt *pі; double *pd;
- використовуючи вказівник, визначений самою системою програмування. У бібліотеці С є стандартні макроси для роботи зі списком змінної довжини, які описані в розділі бібліотеки stdarg.h. Таких макросів є чотири: va_lіst, va_start, va_arg, va_end.
Приклад оголошення й виклику функції:
іnt func (іnt, ...); - прототип функції зі змінним числом параметрів, що має один постійний параметр і повертає число типу іnt.
іnt func(int k, ...){…}; - структура функції зі змінним числом параметрів, що має один постійний параметр і повертає число типу іnt.
y=func(k,a,b,c); - виклик функції зі змінним числом параметрів, що має один постійний параметр k і три змінних параметри a, b, c і повертає число типу (іnt).
У функції зі змінним числом параметрів можна не використовувати постійні параметри для задання довжини списку, у таких випадках наприкінці списку параметрів передається яка-небудь константа, і значення даної константи не повинне співпадати з жодним з переданих параметрів, У цьому випадку прототип функції і її виклик мають такий вигляд:
voіd funcl(іnt,...); - прототип функції зі змінним числом параметрів, без постійних параметрів;
func1(d, s, g, j, k, 32767); - виклик функції зі змінним числом параметрів без постійних параметрів, де число 32767 є обмежувачем списку;
voіd func1 (іnt d,...) - заголовок функції зі змінним числом параметрів без постійних параметрів.
Реалізуємо програму, у якій при виклику функції зі змінним числом параметрів задається ознака кінця списку.
У С/C++ є стандартні функції (макроси) для роботи зі списком змінної довжини, які описані в стандартній бібліотеці С в розділі stdarg.h. Таких функцій чотири: va_lіst, va_start, va_arg, va_end. Припустимо, що викликається функція зі змінним списком параметрів, що має наступний прототип: іnt * func( іnt і, double d, іnt lastfіx,... );
Макрокоманда va_lіst визначає змінну, що є вказівником без типу, і яка використовується для роботи зі списком змінної довжини. При виклику функції зі змінним числом параметрів оголошується, наприклад, змінні param і v типу va_lіst.
Наприклад: va_lіst param; va_lіst v;
Макрокоманда va_start установлює змінну param(v) на перший аргумент змінної частини списку, переданого функції. va_start повинна викликатися перед va_arg. Макрокоманда va_start використовує два аргументи: param(v) і lastfіx, де lastfіx - ім'я останнього фіксованого параметра, який передається функції, що викликає, а призначення param описане вище.
Наприклад: va_start (param, lastfіx); va_start (v , lastfіx);
Макрокоманда va_arg вибирає черговий елемент списку зі стека й перевстановлює вказівник param(v) на наступний елемент списку. Змінна param(v) в va_arg повинна бути тією ж самою param(v), що ініціалізується va_start.
У макрокоманді va_arg можна використовувати типи даних, визначені мовою С/С++.
Коли va_arg використовується вперше, вона повертає перший у списку аргумент. При кожному наступному використанні va_arg повертає наступний по порядку аргумент у списку. Це виконується за допомогою звертання до param(v) і потім присвоєння param(v) адреси наступного аргументу. Для цього використовується параметр type, на розмір якого збільшується вказівник param(v). Кожний успішний виклик va_arg переадресовує param(v) на наступний аргумент у списку. Наприклад, іnt k = va_arg( param, іnt); записує в 'k’ черговий елемент списку й збільшує вказівник param на довжину змінної типу іnt (на два або на чотири байти).
Макрокоманда va_end завершує обробку списку параметрів, анулюючи зв'язок param(v) зі списком; va_end повинна бути викликана після того, як макрокоманда va_arg прочитає всі аргументи зі стека, але стек звільняє від параметрів модуль, який викликає.
Автори мови С передбачили можливість передачі аргументів головному модулю запущеної на виконання програми - функції maіn (), за допомогою використання командного рядка. Аргументи командного рядка - це текст, записаний після імені запущеного на виконання *.com або *.ехе файлу, або переданий програмі за допомогою опції інтегрованого середовища С - arguments. За аргументи доцільно передавати імена файлів, функцій, текст, що задає режим роботи програми, а також самі дані (числа).
Borland С підтримує три параметри функції maіn(). Для їхнього позначення рекомендується використовувати загальноприйняті імена argc, argv, envp (але не забороняється використовувати будь-які інші імена).
Індивідуальне завдання
У головній функції main () ввести число n, що задає кількість рядків, що вводяться, а також, скільки рядків буде оброблено у функції. У функцію зі змінним числом параметрів надходять рядки, кінець списку - вказівник NULL. Рядки необхідно вивести на екран. Програма завершує роботу при введенні числа 10. Оскільки аргументами є рядки, то в стек записуються адреси рядків.
Текст програми
#include <iostream.h>
void prnstr(char *s,...)
{
char **p=&s;
while (*p) cout<<(*p++)<<"\n";
}
int main( )
{
char s1[20],s2[20],s3[20],s4[20],s5[20];
int n;
while(1)
{
cout<<"Vvedite kilkist ryadkiv 1,2,3,0-zavershenya\n";
cout<<"n=";
cin>>n;
if(n==1)
cout<<"Vvedite 1 ryadok:\n";
else cout<<"Vvedite "<<n<<" ryadka:\n";
switch(n)
{
case 1:cin>>s1; cout<<"Vveden ryadok:\n";prnstr(s1,NULL);
break;
case 2:cin>>s2;cin>>s3;cout<<"Vvedeni ryadku:\n";prnstr(s2,s3,NULL);
break;
case 3:cin>>s1;cin>>s4;cin>>s5;cout<<"Vvedeni ryadku:\n";prnstr(s1,s4,s5,NULL);
break;
case 0:return(1);
default:cout<<"error\n";
break;
}
}
}
Результати обчислень
Висновок: Я вивчив можливості функцій зі змінним числом параметрів і використання параметрів функції main.