Учебная работа. Лабораторная работа: Работа с функциями в языке программирования Си
«Работа с функциями в языке программирования Си++»
Цель работы: ознакомиться с чертами внедрения функций в языке Си++, с понятием макета и областью его внедрения, с понятием автоматических наружных, статических и регистровых переменных и их применением при составлении программ с внедрением функций.
1. Теоретические сведения
Функции
Программки на языке СИ обычно состоят из огромного числа отдельных функций (подпрограмм). Как правило, они имеют маленькие размеры и могут находиться как в одном, так и в нескольких файлах.
Связь меж функциями осуществляется через аргументы, возвращаемые значения и наружные переменные.
Вызов функции осуществляется последующим образом: <тип функции >(параметр 1, параметр 2 , …);
Если функция имеет переменное число характеристик, то заместо крайнего из их указывается многоточие.
Передача 1-го значения из вызванной функции в вызвавшую происходит при помощи оператора возврата, который записывается в последующем виде:
return (выражение);
В этом случае значение выражения (в личном случае быть может просто переменная) передается в основную программку и подставляется заместо воззвания к функции.
Пусть вызывающая программка обращается к функции последующим образом:
a=fun(b,c);
Тут b и c – аргументы, значения которых передаются в вызываемую подпрограмму.
Если описание функции начинается так: fun(i,j) , то переменные i и j получат значения a и b соответственно.
Пример 1. Оформить получение абсолютной величины числа в виде функции. Сама функция быть может оформлена в виде отдельного файла. В этом случае производится его включение процедурой #include.
программка имеет последующий вид:
#include <stdio.h>
main()
{int a=10,b=0,c=-20;
int d,e,f;
d=абс(a); /*воззвание к функции абс*/
b=абс(b);
f=абс(c);
printf(«%d %d %d»,d,b,f);
}
#include «abc.c» /*включениефайла abc.c сфункцией абс*/
/*Функция, вычисляющая абсолютную величину числа */
абс(x)
int x; /*Описание переменных, работающих в функции */
{int y;
y=(x<0)?–x:x; /*Определение абсолютной величины числа*/
return (y); /*Возвращает
}
В приведенной программке описание типа функции было опущено. Это может быть лишь в том случае, если возвращенное значение имеет целый тип. Во всех других вариантах описание типа функции непременно. приведем пример, когда результатом работы функции будет число двойной точности.
Пример 2. Оформить в виде функции вычисление f=Öx + y/z.
В первом примере функция хранилась в виде отдельного файла и врубалась процедурой #include. Функция быть может включена в один файл с вызывающей программкой. В этом случае процедура #include не требуется, а сама функция обязана быть объявлена в главный программке, если она имеет не целый тип. Приведем программку для примера 2, оформленную таковым методом.
программка имеет вид:
#include <stdio.h>
main()
{ double f,x=5.5,y=10.1,z=20.5, vv() /*объявлены переменные и функция vv*/
f=vv(x,y,z); /*воззвание к функции vv*/
printf(«lf»,f); /*вывод результата */
}
/*функция */
double vv(x,y,z)
double x,y,z; /*объявление переменных функции */
{double f;
f=sqrt(x)+y/z; /*вычисление значения функции */
return(f); /*возврат вычисленного значения функции */
}
В языке СИ аргументы функции передаются по значению, т.е. вызванная функция получает временную копию всякого аргумента, а не его адресок. Это значит, что функция не может изменять уникальный аргумент в вызвавшей ее программке. Но это просто создать, если передавать в функцию не переменные, а их адреса.
Пример 3. В приведенной ниже программке вводятся некие значения переменных а и b, позже в функции izm они изменяются местами.
#include <stdio.h>
main()
{int a,b;
scanf («%d %d», &a, &b);
izm (&a, &b); /*воззвание к функции izm; аргументами являются адреса переменных a и b*/
printf(«%d, %d»,a, b); /*вывод на экран модифицированных значений */
}
#include «izm.c» /*включение файла izm.c с функцией izm */
/*функция*/
izm(a, d); /*аргументы a и b являются указателями */
int *a, *b; /* *a и *b – значения, на которые указывают указатели */
{int c;
c=*a;
*a = *b;
*b=c; /*обменместами */
}
Функция izm получает копию адресов переменных a и b, меняет местами значения, записанные по сиим адресам, и передает управление в основную программку. Адреса &a и &b в главный программке не изменялись, а вот значения, на которые они указывают, поменялись местами.
Если в качестве аргумента функции употребляется имя массива, то ей передается адресок начала массива, а сами элементы не копируются. Функция может изменять элементы массива, сдвигаясь (индексированием) от его начала.
Пример 4. В массиве S поменять местами элементы: 1-ый со вторым, 3-ий с четвертым и т.д. Оформить этот метод в виде функции reverse.
#include <stdio.h>
main()
{int i,j,s[6]; /* описание переменных i,j и массива s целого типа */
for (i=0; i<6; i++)
scanf(«%d»,&s[i]); /*вводэлементовмассива s*/
reverse(s); /*обращениекфункции reverse*/
for (i=0; i<6; i++)
printf(«%d»,s[i]); /*вывод приобретенного массива */
}
include «reverse.c» /*включениефайла reverse.c сфункцией reverse */
/*функция*/
reverse(s)
int s[]; /*описание работающего в подпрограмме массива */
{
int a,i;
for (i=1; i<5; i+=2)
{a=s[i]; s[i]=s[i+1]; s[i+1]=a;} /*обменэлементовместами*/
}
Разглядим индивидуальности работы функции с двумерным массивом. В прошлом примере в функции массив был описан как int s[]; для двумерного массива а недозволено записать a[][]. В описании двумерного массива во 2-ой квадратной скобке обязано быть обозначено количество столбцов, к примеру: a[][3].
Пример 5. Прирастить все элементы массива а(5,5) вдвое. Оформить этот метод в виде подпрограммы.
#include <stdio.h>
main()
{int a[5][5]; /*описаниемассива a*/
int i,j; /*объявление переменных i,j*/
for (i=0;i<5;i++)
for (j=0; j<5; j++)
scanf(«%d»,a[i][j]); /*вводмассива*/
mas(a); /*воззвание к функции mas*/
for (i=0; i<5; i++)
for (j=0; j<5; j++)
printf(«%d», a[i][j]); /*вывод приобретенного результата*/
}
/*функция*/
mas(a)
int a[][5]; /*описание массива а*/
{int i,j; /*описание переменных i,j*/
for (i=0; i<5; i++)
for (j=0; j<5; j++)
a[i][j] = 2*a[i][j]; /*повышение частей массива в 2 раза*/
}
Классы памяти
В языке СИ различают четыре главных памяти: внешнюю (глобальную), автоматическую (локальную), статическую и регистровую.
Наружные переменные определены вне хоть какой из функций, как следует, доступны для почти всех из их. Область наружной переменной простирается от точки во входном файле, где она объявлена, и до конца файла. Если наружная переменная определена в другом файле, то вступает в силу описание extern (наружный). На рис.1 показано, где объявляются и на что распространяется область деяния наружных переменных, если программка main и вызываемая функция находятся в данном файле. На рис. 2 демонстрируются отличия, имеющие пространство, когда main и вызываемая функция находятся в различных файлах. В файле с вызываемой функцией наружные переменные будут доступны опосля их описания при помощи главного слова extern.
Пример 5. Оформить в виде функции вычисление выражения:
f=a×x2
+b×x+c;
В приведенной ниже программке данные переменные объявлены как наружные, при этом основная программка и функция находятся в одном файле.
#include <stdio.h>
int a=5, b=7, c=10,x; /* Объявление наружных переменных a,b,c,x целого типа*/
main ()
{ int f;
scanf («%d», &x); /*Ввод значения переменной x*/
f=kv(); /*воззвание к функции*/
printf («%d»,f); /*вывод на экран значения переменной f*/
}
/*функция*/
kv()
{int f;
f=a*x*x+b*x+c; /*вычисление значения f*/
return (f); /*возвращает значение f вызывающей программке*/
}
Если сопоставить эту программку с программкой, приведенной в примере 2, то можно найти два различия:
1) опосля имени функции в скобках отсутствуют аргументы;
2) в функции не объявлены переменные, с которыми работает функция.
Это сделалось вероятным поэтому, что переменные объявлены наружными, а означает они известны всему файлу, в том числе и функции.
Наружные переменные должны быть описаны до функции main(). Лишь в этом случае они стают наружными (см. рис. 1).
Приведем программку для этого же примера, рассмотрев вариант, когда основная программка и функция размещены в различных файлах.
#include <stdio.h>
int a=5, b=7, c=10,x,f; /* Объявление наружных переменных a,b,c,x,f целого типа*/
main ()
{
scanf («%d», &x); /*Ввод значения переменной x*/
f=kv(); /*воззвание к функции*/
printf («%d»,f); /*вывод на экран значения переменной f*/
}
#include «kv.c» /*включение файла kv.c функцией kv*/
/*функция*/
kv()
{extern int a,b,c,x,f;
f=a*x*x+b*x+c; /*вычисление значения f*/
return (f); /*возвращает значение f вызывающей программке*/
}
Как было сказано выше (см. рис. 2), если основная программка и функция размещены в различных файлах, то переменные в функции должны быть вписаны с помощью главного слова extern.
Разглядим сейчас статические переменные. Статические переменные имеют такую же область деяния, как автоматические, но они не исчезают, когда содержащая их функция окончит свою работу. Компилятор хранит их значения от 1-го вызова функции до другого. Статические переменные объявляются при помощи главного слова static. Можно статические переменные обрисовать вне хоть какой функции. Это делает внешнюю статическую переменную. Разница меж наружной переменной и наружной статической переменной заключается в области их деяния. Рядовая наружная переменная может употребляться функциями в любом файле (при помощи главного слова extern), в то время как наружная статическая переменная может употребляться лишь функциями такого же самого файла.
Регистровые переменные относятся к крайнему классу. Ключевое слово register показывает, что переменная, о которой идет речь, будет активно употребляться. Если это может быть, значения таковых переменных помещаются во внутренние регистры микропроцессора, по этому программка будет наиболее резвой.
2. Задание
Взять задачку из лабораторной работы №4 и оформить ее решение в виде функции последующими методами:
1. функция размещена опосля ее вызова;
2. функция размещена опосля до ее вызова;
3. функция размещена опосля в другом файле;
Литература
1. Подбельский В.В. язык Cu ++: Учебное пособие. — М.: Деньги и статистика,1995, — 560 с.
2. Страуструп Б. язык программирования Сг ++. — М.: Радио и связь, 1991. — 352 стр.
3. Собоцинский В.В. Практический курс TurboCu ++. Базы объктно- нацеленного программирования. — М.: свет, 1993. — 236 с.
4. Романов В.Ю. Программирование на языке Cu ++. Практический подход. — М.: Компьтер, 1993. — 160 с.
5. Уинер Р. язык турбо Cu . — М.: Мир, 1991. — 384 с.
6. Юлин В.А., Булатова И.Р. Приглашение к Cu. — Мн.: Высш. Шк., 1990,- 224 с.
7. Котлинская Г.П., Галиновский О.И. Программирование на языке Cu. -Мн.: Высш. Шк., 1991. — 156 с.
]]>