Главная Случайная страница Контакты | Мы поможем в написании вашей работы! | ||
|
Программы на языке СИ обычно состоят из большого числа отдельных функций (подпрограмм). Как правило, они имеют небольшие размеры и могут находиться как в одном, так и в нескольких файлах.
Связь между функциями осуществляется через аргументы, возвращаемые значения и внешние переменные.
Вызов функции осуществляется следующим образом:
<тип функции >(параметр 1, параметр 2, …);
Если функция имеет переменное число параметров, то вместо последнего из них указывается многоточие.
Передача одного значения из вызванной функции в вызвавшую происходит с помощью оператора возврата, который записывается в следующем виде:
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=abs(a); /*обращение к функции abs*/
b=abs(b);
f=abs(c);
printf(“%d %d %d”,d,b,f);
}
#include “abc.c” /*включение файла abc.c с функцией abs*/
/*Функция, вычисляющая абсолютную величину числа */
abs(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 поменять местами элементы: первый со вторым, третий с четвертым и т.д. Оформить этот алгоритм в виде функции 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[][]. В описании двумерного массива во второй квадратной скобке должно быть указано количество столбцов, например: 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.
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)
Рисунок 1- Область действия внешних переменных
Это стало возможным потому, что переменные объявлены внешними, а значит они известны всему файлу, в том числе и функции.
Внешние переменные должны быть описаны до функции main(). Только в этом случае они становятся внешними.
Приведем программу для этого же примера, рассмотрев случай, когда основная программа и функция расположены в разных файлах.
#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 вызывающей программе*/
}
Как было сказано выше, если основная программа и функция расположены в разных файлах, то переменные в функции должны быть вписаны при помощи ключевого слова extern.
Регистровые переменные относятся к последнему классу. Ключевое слово register указывает, что переменная, о которой идет речь, будет интенсивно использоваться. Если это возможно, значения таких переменных помещаются во внутренние регистры процессора, благодаря чему программа будет более быстрой.
Тема 6: Структуры.
Структура – это объединение одного либо более объектов(переменных, массивов, указателей, других структур). Как и массив, она представляет собой совокупность данных, но отличается от него тем, что к ее элементам необходимо обращаться по имени, и ее различные элементы не обязательно должны принадлежать одному типу.
Структуры удобно использовать там, где разнообразные данные, относящиеся к одному и тому же объекту, необходимо объединять. Например, ученика средней школы характеризуют следующие данные: фамилия, имя, дата рождения, класс, возраст.
Объявление структуры осуществляется с помощью ключевого слова struct, за которым следует ее тип, список элементов, заключенных в фигурные скобки. Ее можно представить в следующем общем виде:
struct тип {тип элемента 1 имя элемента 1;
тип элемента n имя элемента n; };
Именем элемента может быть любой идентификатор. В одной строке можно записывать через запятую несколько идентификаторов одного типа.
Например:
struct date { int day;
int month;
int year;};
Русские буквы использовать в идентификаторе в языке СИ нельзя.
Следом за фигурной скобкой, заканчивающей список элементов, могут записываться переменные данного типа, например:
struct date {…} a, b, c;
При этом выделяется соответствующая память.
Выведенное имя типа можно использовать для объявления записи, например: struct date day;. Теперь переменная day имеет тип date.
Разрешается вкладывать структуры одна на другую. Для лучшего восприятия структуры используем русские буквы в идентификаторах, в языке СИ этого делать нельзя.
Например:
struct УЧЕНИК { char Фамилия [15];
имя [15];
struct DATA ДАТА РОЖДЕНИЯ;
int класс, возраст;};
определенный выше тип DATA включает три элемента: День, Месяц, Год, содержащие целые значения (int). Запись УЧЕНИК включает элементы: ФАМИЛИЯ [15]; ИМЯ[15]; ДАТА РОЖДЕНИЯ, КЛАСС, ВОЗРАСТ. ФАМИЛИЯ [15] и ИМЯ [15] – это символьные массивы из 15 компонент каждый. Переменная ДАТА РОЖДЕНИЯ представлена составным элементом (вложенной структурой) ДАТА. Каждой дате рождения соответствуют день месяца, месяц и год. Элементы КЛАСС и ВОЗРАСТ содержат значения целого типа (int). После введения типов ДАТА и УЧЕНИК можно объявить переменные, значения которых принадлежат этим типам.
Например:
struct УЧЕНИК УЧЕНИКИ [50];
массив УЧЕНИКИ состоит из 50 элементов типа УЧЕНИК.
В языке СИ разрешено использовать массивы структуры; записи могут состоять из массивов и других записей.
Чтобы обратиться к отдельному компоненту структуры, необходимо указать ее имя, поставить точку и сразу за ней написать имя нужного элемента.
Например:
Ученики [1]. КЛАСС = 3;
Ученики [1]. ДАТА РОЖДЕНИЯ. ДЕНЬ=5;
Ученики [1]. ДАТА РОЖДЕНИЯ. МЕСЯЦ=4;
Ученики [1]. ДАТА РОЖДЕНИЯ. ГОД=1979;
Первая строка указывает, что 1-й ученик учится в третьем классе, а последующие строки – его дату рождения: 5.04.79.
Каждый тип элемента структуры определяется соответствующей строкой объявления в фигурных скобках. Например, массив УЧЕНИКИ имеет тип УЧЕНИК, год является целым числом. Так как каждый элемент записи относится к определенному типу, его составное имя может появляться везде, где разрешено использовать значение этого типа. Рассмотрим пример программы:
/* Демонстрация записи */
#include < stdio.h >
struct computer { int mem;
int sp;
char model [20]; };
/* Объявление записи типа computer, состоящей из трех элементов: mem, sp, model */
struct computer pibm =
{512, 1, “ПЭВМ ЕС 1840.05”}
/* Объявление и инициализация переменной pibm типа computer */
main ()
{ printf (“ персональная ЭВМ % s\n\n “, pibm.model);
printf (“объем оперативной памяти - % d К байт \n”, pibm.mem);
printf (“производительность - % d млн. операций в секунду \n”, pibm.sp);
/* вывод на экран значений элементов структуры */
}
В данной программе объявляется запись computer, которая состоит из трех элементов: mem (память ЭВМ), sp (быстродействие), model [20] (модель ПЭВМ). Переменная pibm имеет тип computer и является глобальной. Строки pibm.model, pibm.mem, pibm. sp в операторе printf вызывают обращение к соответствующим элементам записи pibm типа computer, которым ранее были присвоены определенные значения.
Результат работы программы имеет вид:
Дата публикования: 2014-11-28; Прочитано: 772 | Нарушение авторского права страницы | Мы поможем в написании вашей работы!