Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Способы описания строк в программе↑ Стр 1 из 3Следующая ⇒ Содержание книги
Поиск на нашем сайте
Описание функции Форма описания функции: тип имя (тип1 арг1, тип2 арг2,...) /*заголовок функции*/ { описание 1; /*описание ... внутренних переменных, описание M; массивов*/
оператор 1; /*выполняемая ... часть*/ оператор N; } Заголовок функции: тип– это тип возвращаемого функцией значения (результата) через ее имя. Определенный тип – int, float, char,... Неопределенный тип – void Если тип не указан, то по умолчанию – int. main() à int main() void main() имя – это идентификатор для обозначения функции типI аргI,...– описания аргументов функции типI – тип аргумента аргI – имя аргумента Функция может не иметь аргументов: тип имя () Примеры: float my_func1(int k, float c, float d, char q) { ... } void ftc(float a[], float *ptk, int n, long s) { ... } Нельзя написать: float my_func1(int k, float c,d, char q) {...} Описание функции может быть записано до или после функции main(), но не внутри ее: 1. До main(): При этом ничего дополнительно не надо записывать, т. к. компилятор сначала рассматривает f1(), а потом main(). 2. Функция – после main() void f1(int, float, chat, float *); /*прототип функции*/
void main() { /*прототип функции можно поместить здесь*/ ... вызов f1(...); ... }
/*описание функции f1*/ void f1(int k, float x, char p, float *ptm) { ... }
Вызов функции При вызове функции, ей задаются конкретные аргументы (фактические параметры), для которых функция выполняет вычисления. Есть 2 формы вызова функций: 1. Функция имеет тип void. Вызов является самостоятельным оператором: имя (факт_арг1,факт_арг2,...); Фактические аргументы должны соответствовать списку аргументов в описании функции (по количеству, порядку следования, типам). float z=1.5; float *pts; f1(20,z,’A’,&z); f1(30,*pts,’N’,pts); 2. Функция имеет определенный тип (не void). Вызов не является самостоятельным оператором. Он записывается внутри другого оператора (присваивания, if, printf,...): u=имя(факт_арг1,факт_арг2,...); if(имя(факт_арг1,факт_арг2,...)...){...} float fsum(float a, float b) { return a+b; } /*Вызов float fsum:*/ float x=5.5,y=7.1,z; z=fsum(x,y); /* z==12.6 */
Варианты описания и использования функций 1. Функция возвращает результат через свое имя. В описании функции указывается определенный тип возвращаемого функцией значения – int, float, double, char,... Внутри функции должен быть оператор return(a), где а –выражение для вычисления значения результата. Вызов функции не является самостоятельным оператором. Он записывается внутри другого оператора (присваивания, if, printf,...). Пример: вычислить функцию z=f(x,a,y) для исходных данных: 1) x=5.3; a=-2.1 2) x=3.7; a=7.6
#include<stdio.h> #include<math.h> #include<conio.h> /*Описание функции fz */ float fz(float x, float a) { float y; y=1.7*log(fabs(x+2.5*a)); if(a>=x) return(a*exp(y*sin(2*x))); else return(2.9*cos(a*y)); } /*Главная функция main() */ void main() { float d,h; d=fz(5.3,-2.1); h=fz(3.7, 7.6); printf(“x=5.3, a=-2.1, d=%3f\n”,d); printf(“x=3.7, a= 7.6, h=%3f\n”,h); printf(“fz(6.5,-3.4)=%3f\n”,fz(6.5,-3.4)); }
2. Функция возвращает одно или несколько значений через аргументы В описании функции указывается тип – void (неопределенный). Аргументы, через которые будут возвращаться результаты, описываются как указатели: void fun(int k, float *ptf, float z) Вызов функции будет самостоятельным оператором. В качестве фактических аргументов для возвращаемых значений записываются адреса переменных: float f; fun(20, &f, 5.25); Необходимость использования указателей, а не имен переменных связана с тем, что при вызове функции в стеке (специальная динамическая область памяти для временного хранения промежуточных данных) создаются копии аргументов функции. Все операции функция выполняет с этими копиями. При выходе из функции стек очищается, копии стираются. Если мы напишем: void f(int arg1, int arg2, int arg3) { arg3=arg1+arg2; } то фактически выполнится следующая операция: Копия_arg3 = Копия_arg1+Копия_arg2; и значение arg3 не изменится. Если же запишем следующим образом: void f(int arg1, int arg2, int *arg3) { *arg3=arg1+arg2; } То будет выполнена запись суммы по адресу, заданному в копии параметра *arg3: В результате значение суммы аргументов arg1 и arg2 будет вычислено правильно и сохранено в памяти. Пример: Составить функцию, которая меняет местами значения аргументов X и Y #include<stdio.h> #include<conio.h> /* Функция без указателей */ void obmen1(float x, float y) { float tmp; tmp=x; x=y; y=tmp; } /* Функция с указателями */ void obmen2(float *ptx, float *pty) { float tmp; tmp=*ptx; *ptx =* pty; *pty=tmp; } /* Главная функция */ void main() { float g=7.5, h=11.2; obmen1(g, h); printf(“Ф-ция без указателей\ng=%.1f h=%.1f\n”,g, h); obmen2(&g,&h); printf(“Ф-ция c указателями\n g=%.1f h=%.1f\n”,g, h); } На экране получим: Ф-ция без указателей g=7.5 h=11.2 Результат неправильный Ф-ция с указателями g=11.2 h=7.5 Результат правильный
3. Аргументом функции является одномерный массив. Описание функции. Такой аргумент можно описать двумя способами: 1) как массив с неопределенным количеством элементов: void fun(float a[], int n,…); где n – количество элементов массива a. Внутри функции элементы массива записываются как обычно: a[i] 2) как указатель на начало массива: void fun(float *pta, int n,…); где n – количество элементов массива. Внутри функции элементы массива записываются через указатель: *(pta+i) à a[i] Примечание: Возможен 3-й способ описания массива с указанием фиксированного количества элементов: void fun(float a[10],…); Этот способ имеет недостаток. Функция может работать только с массивами длиной 10 элементов. Вызов функции. При вызове функции для 1 и 2 способов на первом месте указывается имя массива, на втором – количество элементов: float z[40], t[200]; fun(z, 40,…); fun(t, 200,…); Пример. Заданы три массива f[8], g[12], h[15], элементы которых вычисляются по формулам: f[i]=1.7*i*cos(2.5*i) g[j]=2.9*j*cos(3.1*j) h[l]=3.5*l*cos(5.4*l) Для каждого массива вычислить: среднее значение его элементов (sf, sg, sh) и количество элементов, больших среднего значения (kf, kg, kh). В данной задаче целесообразно использовать функцию, которая будет выполнять следующие действия: а) формирование массива Х из n элементов по формуле: x[i]=a*i*cos(b*i), i=1..n б) вычисление среднего значения sx: в) подсчет Кх – количества xi>sx
Текст программы для 3-го варианта: #include<stdio.h> #include<math.h> #include<conio.h> /* Описание функции */ void fmas(float x[], int n, float a, float b, float *pt_sx, int *pt_kx) { int i, kx=0; float sx=0; for(i=0;i<n;i++) { x[i]=a*i*cos(b*i); printf(%.3f “,x[i]); sx+=x[i]; } printf(“\n”); sx/=n; for(i=0;i<n;i++) if(x[i]>sx) kx++; *pt_sx=sx; *pt_kx=kx; } /* Главная функция */ void main() { float f[8], g[12], h[15], sf, sg, sh; int kf, kg, kh; clrscr(); printf(“Массив F из 8 элементов\n”); fmas(f, 8, 1.7, 2.5, &sf, &kf); printf(“sf=%.3f kf=%d\n”,sf,kf); printf(“Массив G из 12 элементов\n”); fmas(g, 12, 2.9, 3.1, &sg, &kg); printf(“sg=%.3f kg=%d\n”,sg,kg); printf(“Массив H из 15 элементов\n”); fmas(h, 15, 3.5, 5.4, &sh, &kh); printf(“sh=%.3f kh=%d\n”,sh,kh); }
4.Аргументом функции является двухмерный массив (матрица) Описание функции.Такой аргумент можно описать 3-мя способами: 1) как массив с заданным количеством строк и столбцов void fun(float c[5][10],…) Внутри функции элементы массива обозначаются: c[i][j] Недостаток этого способа – функция может работать только с матрицами 5*10 2) как массив с неопределенным количеством строк и заданным количеством столбцов void fun(float c[][10], int m,…) где m – количество строк Внутри функции элементы массива обозначаются: c[i][j] Достоинство – функция может работать с матрицами, имеющими разное количество строк: A[5][10], B[8][10], C[20][10]. Недостаток – длина строки (2-й параметр) фиксирована – 10. 3) как указатель на начало массива: void fun(float *ptc, int m, int n,…) где m – количество строк n – количество столбцов Элементы массива: *(ptc+i*n+j) à c[i][j] Этот способ является универсальным, так как функция может работать с массивами любых размеров. Вызов функции. При вызове функции первым аргументом указывают имя массива для 1-3 способов, а далее – другие аргументы в зависимости от способа: 1) float d[5][10], v[5][10]; fun (d,…); fun(v,…); 2) float a[7][10], b[12][10]; fun(a, 7,…); fun(b, 12,…); 3) float s[4][6], u[9][7]; fun(s, 4, 6,…); fun(u, 9, 7,…);
Пример для 4-го варианта. Заданы три матрицы A[3,4], B[5,6], C[4,7], элементы которых вычисляются по формулам: a[i,j]=1.9ij2-3.7i2j b[k,l]=2.5kl2-4.1k2l c[i,j]=5.3ij2+3.1i2j Для каждой из матриц определить сумму элементов строки и произведение элементов столбца, на пересечении которых находится максимальный элемент. Решение задачи. Необходимо использовать функцию, которая будет выполнять следующие действия: 1) формировать матрицу X[M,N] по формуле: X[i,j]=fij2+gi2j 2) определять Хmax и его индексы imax, jmax
3) a) вычислять сумму элементов строки imax б) вычислять произведение элементов столбца jmax
Программа примера для 4-го варианта: #include<stdio.h> #include<conio.h> /* Описание функции fmatr */ void fmatr(float *ptx, int m, int n, float f, float g, float *pt_sx, float *pt_px, char name) { int i,j,imax,jmax; float xmax,sx,px; printf(“Матрица %c размером %dx%d\n”,name,m,n); for(i=0;i<=m-1;i++) { for(j=0;j<=n-1;j++) { *(ptx+i*n+j)=f*i*j*j+g*i*i*j; printf(“%.1f “, *(ptx+i*n+j)); } printf(“\n”); } imax=jmax=0; xmax=*ptx; for(i=0;i<=m-1;i++) for(j=0;j<=n-1;j++) if(*(ptx+i*n+j)>xmax) { xmax=*(ptx+i*n+j); imax=i; jmax=j; } printf(“%cmax=%.1f imax=%d jmax=%d\m”, name, xmax, imax, jmax); sx=0; for(j=0;j<=n-1;j++) sx+=*(ptx+imax*n+j); px=1; for(i=0;i<=m-1;i++) p*=*(ptx+i*n+jmax); *pt_sx=sx; *pt_px=px; } /* Главная функция */ void main() { float a[3][4], b[5][6], c[4][7], sa, sb, sc, pa, pb, pc; clrscr(); fmatr(a, 3, 4, 1.9, -3.7, &sa, &pa, ’A’); printf(“sa=%.1f pa=%.1f\n”, sa, pa); fmatr(b, 5, 6, 2.5, 4.1, &sb, &pb, ’B’); printf(“sb=%.1f pb=%.1f\n”, sb, pb); fmatr(c, 4, 7, 5.3, 3.1, &sc, &pc, ’C’); printf(“sc=%.1f pc=%.1f\n”,sc,pc); }
5. Аргументом функции является другая функция Описание функции. Такой аргумент описывается как указатель на функцию void f1(тип (*fun)(тип1 арг1,…),…); Внутри функции записывается вызов этой другой функции: fun(x, y, z,…); При вызове функции указывается только имя конкретной функции-аргумента: f1(f2,…) где f2 – имя конкретной функции. Функция f2 должна иметь одинаковый список аргументов с функцией fun. Пример:. Составить программу для вычисления и вывода на экран значений функций: f1=1.1*x*sin(2.9x) для –5<=x<=5, Dx=0.2 f2=1.5ecos(1.8y) для 0<=y<=4, Dy=0.1 f3=3.7tg(4.2z) для 1<=z<=6, Dz=0.05 Обозначим: xmin=xn, xmax=xk, Dx=dx Программа для 5-го варианта: #include<stdio.h> #include<math.h> #include<conio.h> /* Описание функций f1, f2, f3 */ float f1(float x) { return(1.1*x*sin(2.9*x)); } float f2(float y) { return(1.5*exp(cos(1.8*y))); } float f3(float z) { return(3.7*tan(4.2*z)); } /* Описание функции ff, которая вычисляет и выводит значения любой из функций f1, f2, f3 */ void ff(float (*fun)(float x), float xn, float xk, float dx, char fname) { float x1,f; printf(“Значения функции f%c для x Є[%.1f, %.1f] dx=%.2f\n”, fname, xn, xk, dx); for(x1=xn; x1<=xk; x1+=dx) { f=fun(x1); printf(“%.3f “,f); } printf(“\n”); } /* Главная функция */ void main() { clrscr(); ff(f1, -5, 5, 0.2, ’1’); ff(f2, 0, 4, 0.1, ’2’); ff(f3, 1, 6, 0.05, ’3’); }
7. Работа со строками В языке С есть тип данных char, который можно использовать как для работы с отдельными символами, так и со строками. Символ – один символ, заключенный в апострофы: 'A', '!', '+', занимает 1 байт памяти Строка – один и более символов, заключенных в кавычки "…". При записи в памяти, в конце строки автоматически записывается специальный символ конца строки '\0' – нуль-символ. "А" – строка в памяти занимает 2 байта: 'A'+'\0' "ABCDEF" ("ABCDEF\0") "Results of calculations" В памяти: "Results of calculations\0"
Ввод-вывод строк 1. Для ввода строк можно использовать следующие 2 функции: - scanf(“%s”,имя_строки); - универсальная функция ввода - gets(имя_строки); - специальная функция для ввода строк с клавиатуры Различие между scanf и gets состоит в том, что scanf вводит строку до 1-го пробела, в то время как gets вводит строку полностью, до нажатия клавиши ENTER. Пример: char fio[30]; scanf(%s”,fio); gets(fio); Вводим с клавиатуры: Калашников И.П.ENTER В результате работы функции scanf() в переменную fio запишется только фамилия (строка до первого пробела): “Калашников” В результате работы функции gets() в переменную fio запишется вся введенная с клавиатуры строка (до нажатия ENTER): “Калашников И.П.” 2. Для вывода строк на экран можно использовать 2 функции: - printf() c форматом %s printf(“%s”,fio); - puts(имя_строки); puts(fio); Эти функции выводят в строку полностью, но puts() всегда выводит курсор на начало следующей строки, а printf() переводит, если есть символ ‘\n’: “%s\n”.
Описание структур Структура – это средство для объединения нескольких разнотипных величин в одно целое. Например, данные о сотруднике фирмы: - фамилия – char[]; - имя – char[]; - отдел – int; - должность – char[] - зарплата – float Способы описания структур: 1-й способ. Использование шаблона структуры: /* Описание шаблона структуры */ struct <имя_шаблона> { тип1 имя_поля1; ... типN имя_поляN; }; /* Объявление переменных, массивов через шаблон структуры */ struct <имя_шаблона> перем1,..., перемN, массив[K]; где <имя_шаблона> - идентификатор для обозначения шаблона типI имя_поляI – описание поля, входящего в структуру Пример. Описать в виде структуры информацию о товарах, хранящихся на складе: struct Рrod { char name[30]; int code; float price; int num; }; struct Рrod pr1, pr2, mpr[20];
2-й способ. Создание нового типа данных в виде структуры. /* Создание нового типа */ typedef stuct { тип1 имя_поля1; ... типN имя_поляN; } имя_типа; /* Объявление переменных, массивов с новым типом в виде структуры */ имя_типа перем1,..., перемN, массив[k]; где typedef – это ключевое слово языка С, которое используется для создания новых (нестандартных) типов данных в программе имя_типа – это обозначение нового типа данных в программе, имеющего вид структуры. Рекомендуется задавать имя типа с буквы Т... (от английского слова Type – тип). Пример: typedef struct { char name[30]; int code; float price; int num; } TProd; ... TProd pr1, pr2, mpr[20];
3-й способ. Одновременное описание структуры и объявление переменных, массивов struct { тип1 имя_поля1; ... типN имя_поляN; } перем1,...,перемN,массив[k]; Пример: struct { char name[30]; int code; float price; int num; } pr1, pr2, mpr[20]; Области применения способов 1-3. 1 и 2 способы используются, когда: а) структура является аргументом функции: void fst(TProd a,...); б) в разных функциях программы эта структура используется для описания переменных: void f1(...) { TProd f; ... } void f2(...) { TProd g; ... } 3-й способ применяется, когда структура используется только внутри одной функции main() или другой функции.
Инициализация структур Одновременно с описанием переменных в виде структур, можно задавать полям (элементам) структур начальные значения: TProd zp={“Компьютер P-IV 3000 MHz”, 2117, 3150.0, 5}; TProd mzp[5]={ {“Холодильник Nord 2910”,1521, 2130.0, 12}, {"Телевизор LG 21FX4RG”, 3462, 1175.0, 10}, ....... }; Структуры и указатели Для структур, описанных 1 или 2 способом можно создавать указатели на структуры: TProd b,*ptr_b; ptr_b=&b; /* присвоим указателю адрес структуры */ Для выделения элементов структуры через указатель используется форма записи указатель->имя_поля (‘->’ записывается как ‘минус’‘больше’) ptr_b->name ptr_b->price Можно использовать точку (‘.’): (*ptr_b).price Скобки нужны, так как операция. старше операции *. void fs(TProd *ptx,...) { ptx->code=1311; ... } Вызов функции: fs(&b,...); Указатели на структуры часто используются как аргументы функции, для передачи в функцию только адреса структуры, а не всей структуры.
Битовые поля в структурах В языке С целую переменную длиной 2 или 4 байта можно представить в виде структуры с разбиением на группы двоичных разрядов (битовые поля). Форма записи: (для 3-го способа) struct { тип1 имя1: N1; тип2 имя2: N2; ... типk имяk: Nk; } перем1, перем2,...; где тип – это тип битового поля, может быть int или unsigned; имя – обозначение поля; Ni – длина битового поля, количество двоичных разрядов SNi=16 (2 байта) или 32 (4 байта). перем – это имя переменной с битовыми полями Если группа битов не используется, то в структуре ей не назначается имя. тип: Ni; Для таких структур можно также использовать 1-й способ (через шаблон структуры) или 2-й способ (через typedef) описания. Пример: struct { int p1:4; unsigned p2:3; int:3; unsigned p3:2; unsigned p4:4; } vb;
Работа с битовыми полями: vb.p1=10; If (vb.p3==0)...; min P1==-7 (1111) max P1==7 (0111) min P4==0 (0000) max P4==15 (1111)
Объединения Объединение– это конструкция языка С, которая позволяет размещать на одном участке памяти данные разных типов. Форма записи: union { тип1 имя1; тип2 имя2; ... типN имяN; } перем1, перем2,...; где тип – обозначение типа поля (int, float, char,...) имя – обозначение поля перем – имя переменной, которая является объединением. Пример: union { char f1; int f2; float f3; double f4; } a, b; Также, как и структуры, объединения можно описывать 3-мя способами: 1 (через шаблон объединения), 2 (через typedef), 3 (одновременное описание шаблона объединения и объявление переменных).
Работа с полями объединения a.f2=276; a.f3=1342.751; if(b.f1==’+’)...;
Применение объединений 1. Для экономии памяти. На одном участке памяти размещают несколько переменных, массивов, с которыми работают в разное время. union { int art1[2000]; float fdr2[1000]; } z; 2. Для обеспечения доступа к участку памяти в целом и по частям (через битовые поля) Пример: #include <stdio.h> struct bf { unsigned p1:6; unsigned p2:4; unsigned p3:3; unsigned p4:3; }; union { int k; struct bf d; } m; void main() { m.k=0xfdb9; printf(“k=%x\n p1=%x p2=%x p3=%x p4=%x\n ”, m.k, m.d.p1, m.d. p2, m.d. p3, m.d. p4); m.d.p1=0x3e; m.d.p2=0xa; printf(“Значения полей после их изменения\n” printf(“k=%x\n p1=%x p2=%x p3=%x p4=%x\n ”, m.k, m.d.p1, m.d. p2, m.d. p3, m.d. p4);}
Запишем К, P1, P2, P3, P4 по битам: К
После изменения: К
P1 P3 P2 P1
Функции библиотеки graphics Графические функции Turbo C делятся на несколько категорий: - управления графической системой - черчения и заполнения - вывода текстов - управления цветами - обработки ошибок - запроса состояния Ниже приводится краткое описание некоторых графических функций. Более подробное описание этих функций приведено в документации по языку Turbo C. Черчение и заполнение Черчение выполняют следующие функции:
Заполнение выполняют следующие функции:
Управление цветом Функции получения информации о цвете:
Функции установки одного или более цветов:
Функции запроса состояния
Пример. Окружность радиусом 100 пикселей перемещается от левого края экрана к правому с шагом 10 пикселей, изменяя при этом цвет случайным образом. #include <graphics.h> #include <stdlib.h> #include <stdio.h> #include <conio.h> #include <dos.h> void main() { /* описание переменных для графического режима с автоопределением параметров */ int graphdriver = DETECT, gmode, errorcode; int x, maxx, midy, color; int radius = 100; /* инициализация графики и локальных переменных */ initgraph(&graphdriver,&gmode,""); /* получение результата инициализации */ errorcode = graphresult(); if(errorcode!= grOk) /* если ошибка */ { printf("Ошибка: %s\n", grapherrormessage(errorcode)); printf("Для останова нажмите любую клавишу\n"); getch(); exit(1); /* завершение с кодом ошибки */ } midy = getmaxy() / 2; /* определение середины экрана по вертикали */ maxx = getmaxx(); /* определение количества пикселей по горизонтали */ for (x= radius; x <= maxx - radius; x+=10) { color = random(getmaxcolor()); /* задание случайного значения цвета */ setcolor(color); /* рисование окружности */ circle(x, midy, radius); delay(700); /* Задержка выполнения программы на 0,7 сек. */ } closegraph(); /* закрытие графического режима */ } Пример использования графических функций приведен в приложении Г (пример №8). Директивы препроцессора
Директивы препроцессора представляют собой инструкции, записанные в тексте программы на С, и выполняемые до трансляции программы. Директивы препроцессора позволяют изменить текст программы, например, заменить некоторые лексемы в тексте, вставить текст из другого файла, запретить трансляцию части текста и т.п. Все директивы препроцессора начинаются со знака #. После директив препроцессора точка с запятой не ставятся.
Директива #include Директива #include включает в текст программы содержимое указанного файла. Эта директива имеет две формы: #include "имя файла" #include <имя файла>Имя файла должно соответствовать соглашениям операционной системы и может состоять либо только из имени файла, либо из имени файла с предшествующим ему маршрутом. Если имя файла указано в кавычках, то поиск файла осуществляется в соответствии с заданным маршрутом, а при его отсутствии в текущем каталоге. Если имя файла задано в угловых скобках, то поиск файла производится в стандартных директориях операционной системы, задаваемых командой PATH. Директива #include может быть вложенной, т.е. во включаемом файле тоже может содержаться директива #include, которая замещается после включения файла, содержащего эту директиву. Директива #include широко используется для включения в программу так называемых заголовочных файлов, содержащих прототипы библиотечных функций, и поэтому большинство программ на С начинаются с этой директивы. Наиболее часто используемые в программах директивы #include следующие: # include <stdio.h> /* Включение файла с описанием функций ввода-вывода */ # include <math.h> /* Включение файла с описанием математических функций */ # include <conio.h> /* Включение файла с описанием функций управления консолью*/
Директива #define Директива #define служит для замены часто использующихся констант, ключевых слов, операторов или выражений некоторыми идентификаторами. Идентификаторы, заменяющие текстовые или числовые константы, называют именованными константами. Идентификаторы, заменяющие фрагменты программ, называют макроопределениями, причем макроопределения могут иметь аргументы. Директива #define имеет две синтаксические формы: #define идентификатор текст #define идентификатор (список параметров) текстЭта директива заменяет все последующие вхождения идентификатора на текст. Такой процесс называется макроподстановкой. Текст может представлять собой любой фрагмент программы на СИ, а также может и отсутствовать. В последнем случае все экземпляры идентификатора удаляются из программы. Пример: #define WIDTH 80 #define LENGTH (WIDTH+10)Эти директивы изменят в тексте программы каждое слово WIDTH на число 80, а каждое слово LENGTH на выражение (80+10) вместе с окружающими его скобками. Скобки, содержащиеся в макроопределении, позволяют избежать недоразумений, связанных с порядком вычисления операций. Например, при отсутствии скобок выражение t=LENGTH*7 будет преобразовано в выражение t=80+10*7, а не в выражение t=(80+10)*7, как это получается при наличии скобок, и в результате получится 150, а не 630. Во второй синтаксической форме в директиве #define имеется список формальных параметров, который может содержать один или несколько идентификаторов, разделенных запятыми. Формальные параметры в тексте макроопределения отмечают позиции, на которые должны быть подставлены фактические аргументы макровызова. Каждый формальный параметр может появиться в тексте макроопределения несколько раз. При макровызове вслед за идентификатором записывается список фактических аргументов, количество которых должно совпадать с количеством формальных параметров. Пример: #define MAX(x,y) ((x)>(y))?(x):(y) Эта директива заменит фрагмент t=MAX(i,s[i]); на фрагмент t=((i)>(s[i])?(i):(s[i]);Как и в предыдущем примере, круглые скобки, в которые заключены формальные параметры макроопределения, позволяют избежать ошибок связанных с неправильным порядком выполнения операций, если фактические аргументы являются выражениями. Например, при наличии скобок фрагмент t=MAX(i&j,s[i]||j);будет заменен на фрагмент t=((i&j)>(s[i]||j)?(i&j):(s[i]||j);а при отсутствии скобок - на фрагмент t=(i&j>s[i]||j)?i&j:s[i]||j;в котором условное выражение вычисляется в совершенно другом порядке.
Директива #undef Директива #undef используется для отмены действия директивы #define. Синтаксис этой директивы следующий #undef идентификатор Директива отменяет действие текущего определения #define для указанного идентификатора. Не является ошибкой использование директивы #undef для идентификатора, который не был определен директивой #define. Пример: #undef WIDTH #undef MAXЭти директивы отменяют определение именованной константы WIDTH и макроопределения MAX.
Описание функции Форма описания функции: тип имя (тип1 арг1, тип2 арг2,...) /*заголовок функции*/ { описание 1; /*описание ... внутренних переменных, описание M; массивов*/
оператор 1; /*выполняемая ... часть*/ оператор N; } Заголовок функции: тип– это тип возвращаемого функцией значения (результата) через ее имя. Определенный тип – int, float, char,... Неопределенный тип – void Если тип не указан, то по умолчанию – int. main() à int main() void main() имя – это идентификатор для обозначения функции типI аргI,...– описания аргументов функции типI – тип аргумента аргI – имя аргумента Функция может не иметь аргументов: тип имя () Примеры: float my_func1(int k, float c, float d, char q) { ... } void ftc(float a[], float *ptk, int n, long s) { ... } Нельзя написать: float my_func1(int k, float c,d, char q) {...} Описание функции может быть записано до или после функции main(), но не внутри ее: 1. До main(): При этом ничего дополнительно не надо записывать, т. к. компилятор сначала рассматривает f1(), а потом main(). 2. Функция – после main() void f1(int, float, chat, float *); /*прототип функции*/
void main() { /*прототип функции можно поместить здесь*/ ... вызов f1(...); ... }
/*описание функции f1*/ void f1(int k, float x, char p, float *ptm) { ... }
Вызов функции При вызове функции, ей задаются конкретные аргументы (фактические параметры), для которых функция выполняет вычисления. Есть 2 формы вызова функций: 1. Функция имеет тип void. Вызов является самостоятельным оператором: имя (факт_арг1,факт_арг2,...); Фактические аргументы должны соответствовать списку аргументов в описании функции (по количеству, порядку следования, типам). float z=1.5; float *pts; f1(20,z,’A’,&z); f1(30,*pts,’N’,pts); 2. Функция имеет определенный тип (не void). Вызов не является самостоятельным оператором. Он записывается внутри другого оператора (присваивания, if, printf,...): u=имя(факт_арг1,факт_арг2,...); if(имя(факт_арг1,факт_арг2,...)...){...} float fsum(float a, float b) { return a+b; } /*Вызов float fsum:*/ float x=5.5,y=7.1,z; z=fsum(x,y); /* z==12.6 */
Варианты описания и использования функций 1. Функция возвращает результат через свое имя. В описании функции указывается определенный тип возвращаемого функцией значения – int, float, double, char,... Внутри функции должен быть оператор return(a), где а –выражение для вычисления значения результата. Вызов функции не является самостоятельным оператором. Он записывается внутри другого оператора (присваивания, if, printf,...). Пример: вычислить функцию z=f(x,a,y) для исходных данных: 1) x=5.3; a=-2.1 2) x=3.7; a=7.6
#include<stdio.h> #include<math.h> #include<conio.h> /*Описание функции fz */ float fz(float x, float a) { float y; y=1.7*log(fabs(x+2.5*a)); if(a>=x) return(a*exp(y*sin(2*x))); else return(2.9*cos(a*y)); } /*Главная функция main() */ void main() { float d,h; d=fz(5.3,-2.1); h=fz(3.7, 7.6); printf(“x=5.3, a=-2.1, d=%3f\n”,d); printf(“x=3.7, a= 7.6, h=%3f\n”,h); printf(“fz(6.5,-3.4)=%3f\n”,fz(6.5,-3.4)); }
2. Функция возвращает одно или несколько значений через аргументы В описании функции указывается тип – void (неопределенный). Аргументы, через которые будут возвращаться результаты, описываются как указатели: void fun(int k, float *ptf, float z) Вызов функции будет самостоятельным оператором. В качестве фактических аргументов для возвращаемых значений записываются адреса переменных: float f; fun(20, &f, 5.25); Необходимость использования указателей, а не имен переменных связана с тем, что при вызове функции в стеке (специальная динамическая область памяти для временного хранения промежуточных данных) создаются копии аргументов функции. Все операции функция выполняет с этими копиями. При выходе из функции стек очищается, копии стираются. Если мы напишем: void f(int arg1, int arg2, int arg3) { arg3=arg1+arg2; } то фактически выполнится следующая операция: Копия_arg3 = Копия_arg1+Копия_arg2; и значение arg3 не изменится. Если же запишем следующим образом: void f(int arg1, int arg2, int *arg3) { *arg3=arg1+arg2; } То будет выполнена запись суммы по адресу, заданному в копии параметра *arg3: В результате значение суммы аргументов arg1 и arg2 будет вычислено правильно и сохранено в памяти. Пример: Составить функцию, которая меняет местами значения аргументов X и Y #include<stdio.h> #include<conio.h> /* Функция без указателей */ void obmen1(float x, float y) { float tmp; tmp=x; x=y; y=tmp; } /* Функция с указателями */ void obmen2(float *ptx, float *pty) { float tmp; tmp=*ptx; *ptx =* pty; *pty=tmp; } /* Главная функция */ void main() { float g=7.5, h=11.2; obmen1(g, h); printf(“Ф-ция без указателей\ng=%.1f h=%.1f\n”,g, h); obmen2(&g,&h); printf(“Ф-ция c указателями\n g=%.1f h=%.1f\n”,g, h); } На экране получим: Ф-ция без указателей g=7.5 h=11.2 Результат неправильный Ф-ция с указателями g=11.2 h=7.5 Результат правильный
3. Аргументом функции является одномерный массив. Описание функции. Такой аргумент можно описать двумя способами: 1) как массив с неопределенным количеством элементов: void fun(float a[], int n,…); где n – количество элементов массива a. Внутри функции элементы массива записываются как обычно: a[i] 2) как указатель на начало массива: void fun(float *pta, int n,…); где n – количество элементов массива. Внутри функции элементы массива записываются через указатель: *(pta+i) à a[i] Примечание: Возможен 3-й способ описания массива с указанием фиксированного количества элементов: void fun(float a[10],…); Этот способ имеет недостаток. Функция может работать только с массивами длиной 10 элементов. Вызов функции. При вызове функции для 1 и 2 способов на первом месте указывается имя массива, на втором – количество элементов: float z[40], t[200]; fun(z, 40,…); fun(t, 200,…); Пример. Заданы три массива f[8], g[12], h[15], элементы которых вычисляются по формулам: f[i]=1.7*i*cos(2.5*i) g[j]=2.9*j*cos(3.1*j) h[l]=3.5*l*cos(5.4*l) Для каждого массива вычислить: среднее значение его элементов (sf, sg, sh) и количество элементов, больших среднего значения (kf, kg, kh). В данной задаче целесообразно использовать функцию, которая будет выполнять следующие действия: а) формирование массива Х из n элементов по формуле: x[i]=a*i*cos(b*i), i=1..n б) вычисление среднего значения sx: в) подсчет Кх – количества xi>sx
Текст программы для 3-го варианта: #include&l
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Последнее изменение этой страницы: 2016-12-17; просмотров: 320; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.188.76.209 (0.018 с.) |