- •Введение
- •Достоинства и недостатки языка c
- •Типы данных в с
- •Модификаторы
- •Константы
- •Арифметические операции
- •Логические операции
- •Оператор присваивания
- •Организация множественных выражений
- •Комбинированные операции
- •Локальные и глобальные объекты
- •Модификатор extern
- •Статические и динамические объекты
- •Регистровые переменные
- •Описание неизменяемых объектов
- •Указатели
- •Явное преобразование типа
- •Оператор if
- •Операторы циклов Оператор while
- •Оператор do ... While
- •Оператор for
- •Оператор switch (переключатель)
- •Операторы передачи управления
- •Прототипы функций
- •Передача данных в функцию
- •Структуры и определения типов пользователя
- •Битовые поля
- •Объединения
- •Псевдофункция sizeof
- •Основные директивы препроцессора
- •Основные директивы условной компиляции
- •Дополнительные данные по Turbo-c
- •Организация памяти на машинах класса pc. Виды указателей
- •Работа с указателями на функцию
- •Основные регистры общего назначения процессора
- •Модели памяти
- •Использование стека
- •Организация прерываний в программе. Модификатор volatile
- •Порядок передачи данных в функцию. Модификатор pascal
- •Передача данных в программу. Функция main
- •Разбор типовых ошибок и недочетов при программировании
- •Некоторые функции библиотеки Turbo-c
- •Функции работы с оперативной памятью эвм
- •Функции работы с клавиатурой
- •Работа с дисплеем в символьном режиме
- •Работа с дисплеем в графическом режиме
- •Функции работы с дисками
- •Функции работы с временными интервалами и звуком
- •Функции преобразования данных
- •Функции работы со строками
- •Математические функции
- •Функции работы с файлами и каталогами
- •Функции работы со временем и датой
- •Функции процессов
- •Функции работы с портами машины
- •Интерфейс с дос
- •Задачи на практические занятия
- •Литература
- •Оглавление
Прототипы функций
Если функция определяется до ее использования (как это делается в примерах, приведенных в предыдущем параграфе), то при вызове функций производится синтаксический разбор их вызова, определяются ошибки (например, несоответствие количества параметров), производится преобразование типов передаваемых данных. Если же функция определена ниже места ее использования или она транслируется отдельно, то могут возникнуть ошибки при определении типа функции и типа параметров. Чтобы избежать этого, необходимо произвести описание этой функции до ее использования. Для этого применяются прототипы функций.
Классический формат:
<тип> <имя функции>();
При таком прототипе функции осуществляется правильная передача только вычисленного значения, но не проверяются параметры. Дело пользователя правильно передать параметры, позаботиться о соответствии типов передаваемых данных и их количестве.
Пример: вычисление факториала из предыдущего параграфа.
main()
{
int i=10;
long fact(); /* это и есть прототип функции fact */
printf("\n%d! = %ld",i,fact(i));
}
long fact(int i)
{
int j;
long k;
k=1;
for (j=2; j<=i; j++) k*=j;
return(k);
}
Современный формат:
<тип> <имя функции>(информация о параметрах через запятую);
Информация о параметрах может быть здесь в виде:
тип
тип и имя параметра
имя параметра
В последнем случае проверяется при вызове только количество параметров, а в первых двух проверяются также типы параметров и при необходимости делается преобразование типов.
Пример: вычисление факториала из предыдущего параграфа.
main()
{
int i=10;
long fact(int);
printf("\n%d! = %ld",i,fact(i));
}
long fact(int i)
{
int j;
long k;
k=1;
for (j=2; j<=i; j++) k*=j;
return(k);
}
Передача данных в функцию
В С при передаче данных типа одномерный объект в функцию передается копия объекта, поэтому при возврате из функции исходный переданный объект не меняется.
Пример:
int a2(int a)
{
a*=a;
return(a);
}
main()
{
int a,b;
a=15;
b=a2(a);
printf("\n%d * %d = %d",a,a,b); /* напечатано 15 * 15 = 225 */
}
Если необходимо, чтобы измененное значение параметра передалось в вызывающую подпрограмму, то при вызове необходимо передать адрес объекта, а в функции описать указатель. В этом случае при вызове функции будет инициализировано значение описанного указателя адресом объекта.
Пример: функция, вычисляющая значения синуса и косинуса от заданного аргумента.
1. Классический стиль
scarg(a,s,c)
double a,*s,*c;
{
*s=sin(a); *c=cos(a);
return; /* необязательный оператор */
}
main()
{
double a,b,c;
printf("\nВведите значение аргумента: ");
scanf("%lg",&a);
scarg(a,&b,&c);
printf("Аргумент: %lg Sin: %lg Cos: %lg\n",a,b,c);
}
2. Современный стиль
scarg(double a,double *s,double *c)
{
*s=sin(a); *c=cos(a);
return; /* необязательный оператор */
}
main()
{
double a,b,c;
printf("\nВведите значение аргумента: ");
scanf("%lg",&a);
scarg(a,&b,&c);
printf("Аргумент: %lg Sin: %lg Cos: %lg\n",a,b,c);
}
Если при вызове функции мы передает в качестве параметров имя массива, то это приведет к передаче адреса первого элемента массива. В подпрограмме в качестве формального аргумента может быть тоже описан массив. В этом случае все изменения элементов массива передаются вызывающей функции.
Пример: вычисление массива факториалов из известного массива аргументов. Современный стиль, Борланд-С. В программе вводится число вычисляемых факториалов (до 100), сами числа (от 1 до 15), от которых берутся факториалы, программа же печатает значения факториалов.
fact(int a,int arg[],long fun[])
{
int i,j;
for (i=0; i<a; i++)
{
fun[i]=1;
for (j=2; j<=arg[i]; j++) fun[i]*=j;
}
}
main()
{
int i,a;
int arg1[100];
long fun1[100];
do
{
printf("\nВведите количество элементов массива: ");
scanf("%d",&a);
}
while ((a<=0)||(a>100));
printf("\nВведите элементы массива\n");
for (i=0; i<a; i++)
{
do
{
printf("%d-й: ",i+1);
scanf("%d",&arg1[i]);
}
while ((arg1[i]<0)||(arg1[i]>15)); /* ограничение */
}
/* вычисляем значения факториалов */
fact(a,arg1,fun1);
/* печатаем результат */
for (i=0; i<a; i++) printf("\n%d!= %ld",arg1[i],fun1[i]);
}
Примечание: функцию вычисления массива факториалов можно написать, используя не массивы, а указатели. При этом она будет иметь вид:
fact(int a,int *arg,long *fun)
{
int i,j;
for (i=0; i<a; i++)
{
*(fun+i)=1;
for (j=2; j<=*(arg+i); j++) *(fun+i)*=j;
}
}
Пример: умножение двух матриц. Современный стиль, Борланд-С. Если , то .
umn(double a[10][10], double b[10][10], double c[10][10],int l, int m, int n)
{
int i,j,k;
for (i=0; i<l; i++)
{
for (j=0; j<n; j++)
{
c[i][j]=0.;
for (k=0; k<m; k++) c[i][j]+=a[i][k]*b[k][j];
}
}
}
main()
{
int i,j,k,l,m;
double a[10][10],b[10][10],c[10][10],x;
do
{
printf("\nВведите границы массивов: ");
scanf("%d%d%d",&i,&j,&k);
}
while ((i<=0)||(i>10)||(j<=0)||(j>10)||(k<=0)||(k>10));
for (l=0; l<i; l++)
for (m=0; m<j; m++)
{
printf("Введите a[%d][%d]: ",l+1,m+1);
scanf("%lg",&x);
a[l][m]=x;
}
for (l=0; l<j; l++)
for (m=0; m<k; m++)
{
printf("Введите b[%d][%d]: ",l+1,m+1);
scanf("%lg",&x);
b[l][m]=x;
}
umn(a,b,c,i,j,k);
printf("Массив А:\n");
for (l=0; l<i; l++)
{
for (m=0; m<j; m++)
printf("%13.5e ",a[l][m]);
printf("\n");
}
printf("Массив B:\n");
for (l=0; l<j; l++)
{
for (m=0; m<k; m++)
printf("%13.5e ",b[l][m]);
printf("\n");
}
printf("Массив C:\n");
for (l=0; l<i; l++)
{
for (m=0; m<k; m++)
printf("%13.5e ",c[l][m]);
printf("\n");
}
}