Void func(int intg,float fltp) — КиберПедия 

Опора деревянной одностоечной и способы укрепление угловых опор: Опоры ВЛ - конструкции, предназначен­ные для поддерживания проводов на необходимой высоте над землей, водой...

Автоматическое растормаживание колес: Тормозные устройства колес предназначены для уменьше­ния длины пробега и улучшения маневрирования ВС при...

Void func(int intg,float fltp)

2021-03-18 68
Void func(int intg,float fltp) 0.00 из 5.00 0 оценок
Заказать работу

Содержание

1 Структуры и объединения.............................................................. 4

1.1 Структуры............................................................................... 4

1.2 Объединения............................................................................ 7

1.3 Битовые поля структур и объединений............................... 10

2 Функции.................................................................................... 11

2.1 Определение, описание, вызов функции............................. 11

2.2 Передача параметров в функции по значению и по указателю 13

2.3 Функции и массивы............................................................... 15

2.4 Функции с умалчиваемыми значениями параметров.......... 16

2.5 Функции с переменным числом параметров....................... 17

2.6 Передача параметров в функцию main().......................... 19

2.7 Рекурсивные и подставляемые функции.............................. 21

2.8 Функции, возвращающие указатель..................................... 22

2.9 Функции и структуры........................................................... 23

2.10 Перегрузка функций............................................................ 24

2.11 Шаблоны функций.............................................................. 25

2.12 Указатели на функции......................................................... 27

3 Работа с файлами.......................................................................... 30

3.1 Потоковый ввод-вывод......................................................... 30

3.2 Открытие и закрытие потока................................................ 31

3.3 Посимвольный ввод-вывод................................................... 34

3.4 Построчный ввод-вывод....................................................... 35

3.5 Форматированный ввод-вывод............................................. 37

3.6 Форматированные вывод в строку и ввод из строки........... 38

3.7 Блоковый ввод-вывод............................................................ 38

3.8 Произвольный доступ к файлу............................................. 39

3.6 Управление файлами и каталогами...................................... 41

4 Многофайловая компиляция........................................................ 44

5 Объекты и их атрибуты................................................................ 48

6 Ссылки........................................................................................... 51

Литература....................................................................................... 54


1 Структуры и объединения

1.1 Структуры

Структуры ‑ это совокупность поименованных объектов в общем случае разных типов. Каждая структура включает в себя один или несколько объектов (переменных, массивов, указателей, структур), называемых элементами структуры.

Структурный тип (шаблон) определяет, сколько элементов и какого типа входят в структуру. Определение шаблона структуры начинается со служебного слова struct, за которым помещаются описания входящих в структуру элементов, заключенные в фигурные скобки. Под шаблон память не выделяется.

Синтаксис определения шаблона структуры следующий:

struct имя_структурного_типа{type_1 элемент_1;

 type_2 элемент_2;

......;

 type_n элемент_n;};

После определения структурного типа с его помощью можно определить конкретные структуры следующим образом:

имя_структурного_типа имя_структуры; Например:

struct STR {char c;

float f;

int a[3];};

STR rec1, rec2, rec3[2];

Здесь определен структурный тип STR с элементами char c, float f, int a[3] и определены структуры: rec1 и rec2, а также массив из 2-х структур rec3. Каждая из определенных структур rec1, rec2, rec3 содержит в качестве элементов свои собственные данные, состав которых определяется структурным типом с именем STR.

Для доступа (обращения) к элементам структуры используются уточненные имена. Используется следующая конструкция языка: имя_структуры.имя_элемента_структуры.

Например:

rec1.c='z'; rec1.f=3.2;

rec1.a[0]=1; rec2.ch='w';

rec2.f=4.5; rec2.a[1]=10;

rec3[0].c='d'; rec3[1].a[2]=100;

Допустимо определять структуры вместе с определением структурного типа. Например:

struct ABC{int a1;float a2;long a3;}str1, str2;

Выделение памяти под структурную переменную осуществляется по шаблону. Например, для структур rec1, rec2 распределение памяти следующее:

1 байт 2 байт 3 байт 4 байт 5 байт 6 байт 7 байт 8 байт 9 байт 10 байт 11 байт
c

f

a[0]

a[1]

a[2]

Например, для структур rec3 распределение памяти следующее:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
c

f

a[0]

a[1]

a[2]

c

f

a[0]

a[1]

a[2]

Размер структуры можно определить с помощью операции sizeof().  

int n1=sizeof(rec1); // 11 байт

int n2=sizeof(STR); // 11 байт

int n3=sizeof(rec3); // 22 байта

При определении структуры возможна её инициализация, т.е. при­своение начальных значений элементам структуры. После определения структуры ставится знак = и далее в фигурных скобках через запятую задаются значения элементов структуры согласно структурному типу. Инициализация бывает полная и неполная:

struct STR { char ch; float f; int a [3];};

STR r 1={ 'a',1.1,1,2,3}; // полная

STR r 2={ ' с ',2.1}; // неполная

STR r 3[2]={{ 'w',6.6,10,20,30},{ 'v',7.7,40,50,60}};

Структурный тип можно ввести с помощью служебного слова typedef:

typedef struct RR{char ch;int b;}my_RR;

При этом RR и my_RR – равноправные первичное и вторичное имена структурного типа. Для определения структур можно использовать лю­бое из имен. Например, определены две одинаковые структуры a1, a2.

RR a1; my_RR a2;

Можно определять указатели на структуру. Если определен указатель структурного типа, то память выделяется только под указа­тель (4 байта). Поэтому необходимо указатель на структуру проини­циализировать адресом (или присвоить адрес) раннее определенной структуры этого же типа.

STR *pst1=&rec2,*pst2; pst2=&rec2;

После такого определения доступ к элементам структуры выпол­няется через разыменование указателя или с помощью операции ->.

(*pts1). f =8.8; (*pts2). a[0] =100;

 pts2-> f =9.9; pts1-> a[0] =1000;

Можно создавать и уничтожать динамические структуры.

Синтаксис определения динамической структуры с помощью функций malloc() и free() следующий:

struct имя_шаблона{…}; // определение структурного типа

имя _ шаблона *имя _ структуры; // определение указателя на структуру

// Запрос памяти под структуру

имя _ струк1=(имя_шаблона*)malloc(N*sizeof(имя_шаблона));

if(имя_струк1 ==NULL) // проверка выделения памяти

 {puts(" Ошибка выделения памяти "); return -1;}

// Программа...

free(имя_струк1); // освобождение памяти

Синтаксис определения массива динамических структур с по­мощью функций malloc() и free() следующий:

int N; scanf(" %d ",&N); // ввод количества структур

имя _ шаблона *имя _ струк2; // определение указателя на структуру

// Запрос памяти под массив структур

имя_струк2=(имя_шаблона*)malloc(N*sizeof(имя_шаблона));

if(имя_струк2 ==NULL) // проверка выделения памяти

 {puts(" Ошибка выделения памяти "); return -1;}

// Программа...

free(имя_струк2); // освобождение памяти

При работе с операциями new и delete определение динамичес­ких структур аналогично, отличаются запрос и освобождение памяти:

// Запрос памяти для одной структуры

имя_струк1=new имя_шаблона;

...

delete имя_струк1; // освобождение памяти одной структуры

// Запрос памяти для массива структур

имя_струк2=new имя_шаблона[N];

...

delete[]имя_струк2; // освобождение памяти массива структур

Пример. Создать одну динамическую структуру согласно заданного структурного типа и присвоить значения элементам.

#include <stdio.h>

Int main()

{struct STD{char name[20]; float rating;};

 STD *st; // определение указателя

 st=(STD*)malloc(sizeof(STD)); // Запрос памяти

//st=new STD; // Запрос памяти

 if(st==NULL) // проверка выделения памяти

{puts(" Ошибка выделения памяти ");return -1;}

gets(st->name);// ввод имени

 st->rating=4.5; // присвоение значения

 printf("%s\n%.2f\n",st->name, st->rating);

free(st); // освобождение памяти

 // delete st; // освобождение памяти

 return 0;}

Пример. Создать массив динамических структур согласно заданному шаблону и ввести с клавиатуры значения элементов.

#include <stdio.h>

struct MYSTR{char name[20]; int age;};

Int main()

{MYSTR *b; int N;

puts(" Ведите размер массива ");

 scanf(" %d ",&N);

 b=(MYSTR*)malloc(N*sizeof(MYSTR); // Запрос памяти

//b=new MYSTR[N]; // Запрос памяти

 if(b==NULL) // проверка выделения памяти

{puts(" Ошибка выделения памяти "); return -1;}

for(int i=0;i<N;i++)

 scanf("%s %d",b[i].name, &b[i].age);

 for(i=0;i<N;i++)

 printf("%s\n%d\n",b[i].name,b[i].age);

free(b); // освобождение памяти

 //delete [] b; // освобождение памяти

 return 0;}

1.2 Объединения

Объединение – это совокупность объектов различных типов, все члены которой начинаются с одного адреса. Т ип объединения (шаб­лон) определяет, сколько элементов и какого типа входят в него. Опре­деление типа объединения начинается со слова union, за которым помещаются описания элементов, заключенные в фигурные скобки.

Если в структуре все элементы расположены последовательно, то объединение совмещает элементы несколько различных типов. При этом под объединение выделяется память, равная размеру максимального элемента объединения.

Для определения объединения сначала определяется тип объеди­нения, а затем само объединение:

union имя_типа_объединения {type_1 элемент_1;

type _2 элемент_2;

......;

type _ n элемент_ n;};

имя_типа_объединения имя_объединения;

Например:

union UN 1{ int a; char ch; long b; }; // определение типа

union UN 2{ double d; float f [3]; }; // определение типа

UN1 un1; UN2 un2; // определение объединений

Компилятор выделит под объединение un1 память, равную длине элемента типа long.

1 байт 1 байт 1 байт 1 байт
ch      

a

   

b

Компилятор выделит под объединение un2 память, равную длине массива f типа float.

4 байта 4 байта 4 байта
f[0] f[1] f[2]

d

 

Для доступа (обращения) к элементам объединения используются уточненные имена. Например:

un1.a=10; un1.ch=’k’; un1.b=1193046L; // 0x123456

un2.f[0]=1.2; un2.f[1]=3.2; un2.f[2]=4.5; un2.d=7.4;

В объединении в памяти храниться только одно значение, поэтому после таких присвоений для объединения un1 в памяти будет нахо­диться только un1.b= 1193046, а переменные изменят свои значения, un1.a=13398(0x3456), un1.ch = V (0x56). Для объединения un2 в памяти будут находиться un2.d=7. 4 и un2.f[2]=4. 5, а переменные un2.f[0], un2.f[1] свои значения изменят.

Объединения можно определять вместе с определением типа объединения. Например:

union N{char c[2];int a; long b;}un2;

Определять тип объединения можно с помощью typedef:

typedef union defun{double d; inti;}my_un;

defun un4; my_un un5;

В этом случае defun, my_un – имена типов объединения, un4, un5 – объединения, определенные с одинаковыми элементами.

Если имеется указатель на объединение и его значением является адрес объединения, то доступ к элементам этого объединения осуществляется через разыменование указателя или операцию ->.

union NN{int a; char c;};

NN un6, *ptru=&un6;

(*ptru).a=13; ptru->c='Y';

Инициализация объединений. При определении объединений их можно инициализировать, но в отличие от структур инициализируется только первый элемент. Например:

union{int i; char ch;} un7={200};

union UN3{char c[4]; int a[2];long g;};

union UN4{int a[2]; long g; char c[4];};

UN3 un8={'a','b','c','d'}; UN4 un9={8,9};

Элементы объединения занимают один и тот же участок памяти и могут использоваться для различных трактовок одного и того же кода:

union COM{int a; char c[2];};

// инициализация объединения com (24930=0х6162)

COM com={24930};

printf("%#x %#x\n",com.c[0],com.c[1]); // 0x62 0x61

printf("%c %c\n",com.c[0],com.c[1]);   // b a

Схема размещения элементов объединения в памяти приведена ниже:

a

c[0] Aдрес 0x62
c[1] Aдрес+1 0x61

Элементами объединений могут быть структуры. Например, в заголовочном файле <dos.h> определены структуры и объединение:

struct WORDREGS{unsigned int ax, bx, cx, dx;};

struct BYTEREGS{unsigned char al, ah, bl, bh;

           unsigned char с l, с h, dl, dh;};

union REGS{WORDREGS x; BYTEREGS h;};

Объекты типа объединение REGS совмещают в себе объекты типа структур WORDREGS и BYTEREGS. С помощью структуры BYTEREGS обеспечивается доступ к отдельным байтам регистров ax, bx, cx, dx. Например:

union REGS rg; // выделится память в 8 байт

rg.x.ax=0x4300;// запись в регистр ax функции прерывания

int86(0x2F,&rg,&rg);// прерывание 0x2F

printf("\n al=%#x",rg.h.al);

Если на печать выведется al=0х80, то драйвер himem.sys установлен.

Объединения могут быть элементами структур. Например:

union UN { int b; char c [2];}; // выделится память 2 байта

struct STR{char st; int a[4]; UN my_u;}str1;

str1.my_u.b=500; str1.st=’z’;

Для структуры str1 выделится память в 11 байт

1.3 Битовые поля структур и объединений

Внутри структур и объединений могут быть определены битовые поля. Без битовых полей можно получить доступ только к целому числу байтов. Битовые поля представляют собой целые (знаковые или беззнаковые) значения, занимающие в памяти фиксированное число битов (от 1 до 16), предназначенные для доступа к отдельным битам данных, а также для более рационального использования памяти.

Определение структуры с битовыми полями имеет формат:

struct имя_типа _ структуры { type_1 элемент_1: ширина_1;

               type_2 элемент_2: ширина_2;

.........;};

имя _ типа _ структуры имя _ структуры;

где type ‑ один из базовых типов: int, char, long, s hort, unsigned int, unsigned char, unsigned long, unsigned short;

ширина ‑ число от 1 до 16.

struct SS{int a:10; int b:3;};

SS st_b, *ptr=&st_b;

Доступ к элементам битовых полей, как и к элементам структуры:

st_b. а =12; st_b.b=2; (*ptr).a=10; ptr->b=3;

К битовым полям нельзя применять операцию взятия адреса, так как доступ возможен только к целому числу байт. Поэтому для ввода значений битовых полей с клавиатуры функцией scanf() можно использовать дополнительную переменную. Например:

scanf(" %d ",&st_b.b); // Ошибка

int flag; scanf (“% d ”,& flag); // Правильно

st_b.b=flag;

Пример объединения, содержащего структуру с битовыми полями:

union {char ch;

  struct{int a:5; // для а отвели 5 битов

         int b:3; // под b отвели 3 бита

}h;

}cod; // выделится 8 бит памяти (1 байт)

cod.h.a=4; cod.h.b=2;

printf("cod.ch=%c - %#x\n",cod.ch,cod.ch);

На печать выведется: cod.ch=D – 0x44

Пример фрагмента программы объединения с битовыми полями:

union {char ch; unsigned a:1; unsigned b:2;}y;

y.ch=43; //0010 1011 в двоичном коде или 2b в 16 СС printf("y.ch=%#x y.a=%#x y.b=%#x\n",y.ch,y.a,y.b);

На экран выведется: y.ch=0x2b y.a=0x1 y.b=0x3

Функции

2.1 Определение, описание, вызов функции

Каждая программа представляет собой либо одну главную функцию с именем main(), либо функцию main() и любое количес­тво других дополнительных функций, предназначенных для выполне­ния определенных действий (вычислений, обмена данными и т.д.).

Функция main() обеспечивает точку входа в откомпилирован­ную программу. Остальные функции, используемые в программе, явно или косвенно вызываются из главной функции. Функции, входящие в программу, могут бытьопределены, как в одном с главной функцией файле, так и в отдельных файлах.

Всем именам функций по умолчанию присваивается класс памяти extern, т.е. функции глобальны, имеют внешний вид компоновки, статическую продолжительность существования (до конца выполне­ния программы) и доступны при определенных условиях во всех модулях программы.

Любая функция, кроме главной функции main(), должна быть определена или описана до её использования (вызова) в конкретном модуле. Определение функции имеет следующий синтаксис

тип _ функции имя _ функции(список _ формальных _ параметров)

{ тело функции }

Первая строка функцииназывается заголовком функции:

тип _ функции имя _ функции(список _ формальных параметров)

Тип _ функции – это тип возвращаемого функцией значения, т.е. базовый (например, int, float, т.д.) или производный тип вычис­ленного в функции значения. Если функция ничего не возвращает, то тип функции обозначается void.

Имя _ функции – это любой уникальный допустимый идентифи­катор, например, myfunc, sum, mult, F1.

Список _ формальных _ параметров (или сигнатура функции) – это пусто или void, если в функцию не передаются параметры, либо список спецификаций отдельных параметров с указанием типов и имен, записанных черех запятую.

Тело функции – это последовательность определений, описаний переменных и операторов, заключенных в фигурные скобки.

Когда функция вызывается, управление передается в начало тела функции. Возврат в точку вызова функции выполняется опера­тором return выражение или return. В теле функции может быть несколько операторов return. При этом выход из функции может быть осуществлен в нескольких точках. Если функция не возвращает никакого значения, т.е. имеет тип void, то выражение в операторе return отсутствует и сам оператор return тоже может отсутствовать.

Пример. Функция вычисляет сумму трех переменных типа float. Функция имеет формальные параметры и один оператор return.

float sum(float a, float b, float c)

{float S=a+b+c;

 return S;}

Пример. Функция находит большее из двух переменных. Функция имеет формальные параметры и два оператора return.

Int max(int x, int y)

{if (x>y)return x;

else return y;}

Пример. Функция выводит значение переменной на экран. Функция имеет один формальный параметр и не имеет оператора return.

Void prn1(int x)

{ printf(" Заданное число =%d\n ", x);}

Пример. Функция выводит строку на экран. Функция не имеет фор­мальных параметров и оператора return.

Void prn2()

{ p uts (" Моя программа ");}

Вызов функции (обращение к функции) – это выражение, в котором указывается имя функции и список фактических параметров в круглых скобках. Результатом этого выражения является возвращаемое значение, тип которого соответствует типу функции:

имя_функции(список фактических параметров)

где список _ фактических _ параметров – это либо пусто, либо void, либо фактические параметры (константы или заранее определенные переменные, переменные с преобразованием типов, выражения).

При обращении к функции формальные параметры заменяются фактическими параметрами в строгом соответствии с типами параметров. Соответствие между формальными и фактическими пара­метрами устанавливается по их взаимному расположению в списках.

Например:

Int max(int x, int y)

{if (x>y)return x; else return y;}

Void main()

{int a=10,res1,res2; float f=55.9;

 res1=max(a, 20); // res1=20

 res 2= max (int(f), a +30); } // res2=55

Пример.

int func1(int a, int b) // Определение функции

{return a+b;}

float sqr(float f, float g) // Определение функции

{return f*g;}

Void main()

{int am=2,bm=3,res1;

 res1=func1(am,bm); // Вызов функции

 float em=2.5,gm=3.0,fm=4.2,res2,res3;

 res2=sqr(fm,gm); // Вызов функции

 res3=sqr(fm+0.5,sqr(em,gm)); // Вызов функции

 int res4=(int)sqr(em,float(am)); } // Вызов функции

Если функция определена после функции main() или в другом файле, то до первого обращения к функции она должна быть описана. Описание функции называется прототипом. Это необходимо для проверки компилятором соответствия типов передаваемых в функцию параметров и возвращаемых значений. В прототипе можно не указывать имена формальных параметров. В конце прототипа обязательна точка с запятой. Примеры прототипов:

float sum(float a, float b, float c);

Int max(int, int y);

float sqr(float, float g);

Пример. Функция определена ниже своего первого вызова, перед вызовом помещен прототип.

#include <stdio.h>

int sum(int, int);// Прототип функции – описание функции

Void main()

{int a, b=3, g=4;

 a=sum(b, g); // Вызов функции

 printf(" Сумма =%d\n", a); }

int sum(int arg1, int arg2) // Определение функции

{return arg1+arg2;}

2.2 Передача параметров в функции по значению и по указателю

В языке С++ передача параметров (кроме указателей и массивов) в функции при их вызове осуществляется по значению. Это означает, что для передаваемых (фактических) параметров в функции создаются копии этих параметров. Для формальных параметров выделяется память, в которую заносятся значения фактических параметров. Действия, производимые с этими параметрами (копиями) в функции не влияют на переменные вне функции, т.е. на фактические пере­менные. Формальные параметры недоступны вне тела функции. При выходе из функции выделенная для них память освобождается.

Пример.

#include <stdio.h>

Void main()

{int i=200; float f=100.25;

 func(i,f);

 printf("i=%d &i=%p f=%f &f=%p\n",i,&i,f,&f);}

В результате работы программы на экран выведется:

intg=200 &intg=8FD8:0FF2 fltp=100.25 &fltp=8FD8:0FF4

intg_n= 2 10 fltp_n=200.5

i=200 &i=8FD8:0FFC f=100.25 &f=8FD8:0FF8

При передаче в функцию указателей (адресов фактических пара­метров) в функции создаются копии этих адресов, и в теле функции становится известно, где располагаются фактические параметры, и, следовательно, их значения можно изменить.

Пример. В функцию передаются указатели на переменные и значения этих переменных меняются местами:

#include <stdio.h>

void swap(int *a, int *b) // Определение функции

{printf("&a=%p a=%p *a=%d\n",&a,a,*a);

 printf("&b=%p b=%p *b=%d\n",&b,b,*b);

 int tmp=*a; *a=*b; *b=tmp;

 printf("*a_n=%d *b_n=%d\n",*a,*b);}

Void main()

{int i=5,j=60;

 printf("&i=%p i=%d  &j=%p j=%d\n",&i,i,&j,j);

 swap(&i,&j); // Вызов функции

 printf("i=%d j=%d\n",i,j);}

В результате работы программы на экран выведется:

&i=8FD8:0FFE i=5  &j=8FD8:0FFC j=60

&a=8FD8:0FF4 a=8FD8:0FFE *a=5

&b=8FD8:0FF8 b=8FD8:0FFC *b=60

*a_n=60 *b_n=5

i=60 j=5

2.3 Функции и массивы

При передачемассива в функцию в качестве параметра указыва­ется имя массива. Поскольку имя массива – это указатель-константа, то в функцию передается адрес начала массива и все действия внутри функции производятся именно с элементами массива оригинала. При этом список формальных параметров в заголовке функции имеет две равноправные формы: (покажчик-константа

int func1(int arr[]) {...}

или int func2(int *mass) {...}

В обоих случаях в функции создается копия указателя соответст­вующего типа, который действует внутри функции как обычный ука­затель-переменная и может изменять свое значение. Например, arr++. Доступ к элементам массива внутри функции может осуществляться как с помощью индексов (arr[1], arr[i]), так и применяя опера­цию разыменования указателя (*(arr+1), *(arr+i)).

Для работы со всеми элементами массива необходимо знать количество элементов в массиве. При этом в самой функции узнать размер массива невозможно, т.к. в функцию передается указатель на первый элемент массива и размер этого указателя равен 4 байта.

Есть два способа определения конца массива: 1) в качестве одного из параметров в функцию передается размер массива; 2) последний элемент массива задается каким-либо уникальным значением, которое анализируют в функции.

Пример. Функция вычисляет сумму элементов массива, в качестве одного из параметров в функцию передается размер массива.

#include <stdio.h>

int sum (int N, int x []) // Определение функции

{int S=0;

 for(int i=0;i<N;i++) S+=x[i];

 return S;}

Void main()

{int a[5]={1,3,5,10,2},c[3]={2,1,6},res1,res2;

 res1=sum(5,a); // Вызов функции

 printf ("сумма элементов массива a =% d \ n ", res 1); // 21

res 2= sum (3, c); // Вызов функции

printf ("сумма элементов массива c =% d \ n ", res 2);} // 9

Пример. Функция вычисляет количество символов в слове, в качестве признака конца массива используется '\0'.

#include <stdio.h>

int len(char *); // Прототип функции

Void main()

{char *name="TERMINATOR";

 printf(" Длина 1- ой строки =%d",len(name)); // 10

 char *str=" Высшая математика ";

printf("Длина 2-ой строки=%d",len(str)); } // 17

int len (char * c) // Определение функции

{int i=0;

while(c[i++]);

 return i-1; } // длина строки без учета символа ' \0 '

Пример. Функция изменяет значения элементов массива, поменяв их на квадраты этих значений, тип функции void

#include <stdio.h>

void exch(int, int []); // Прототип функции

Void main()

{int a[5]={1,3,5,8,2};

 printf(" Массив до изменения: ");

 for(int i=0;i<5;i++) printf(" %d",a[i]);

exch(5,a); // Вызов функции

 printf("\nМассив после изменения: ");

 for(int i=0;i<5;i++) printf(" %d",a[i]);

}

void exch (int N, int x []) // Определение функции

{for(int i=0;i<N;i++)  x[i]*=x[i];}

В результате на экран выведется:

Void main()

{int am=2, bm=5, res1,res2,res3;

 res1=def();    // 10*3=30

 res2=def(am); // 2*3=6

 res3=def(am,bm); // 2*5=10

 printf(" res1=%d res2=%d res3=%d\n ",res1,res2,res3); }

В результате работы программы на экран выведется:

res1=3 0 res2= 6 res3=1 0

Если функция с умалчиваемыми параметрами определена после функции main(), то значения умалчиваемых параметров указыва­ются обязательно в прототипе этой функции, а в определении функ­ции (в списке формальных параметров) эти значения не указываются.

Пример. Функция находит сумму 3-х переменных

#include <stdio.h>

int sum(int,int=5,int=10); // Прототип функции

Void main()

{int am=20, bm=50, cm=100, s1,s2,s3,s4;

 s1=sum(am);  // 20+5+10=35

 s2=sum(am,bm); // 20+50+10=80

 s3=sum(am,bm,cm); // 20+50+100=170

 printf(" s1=%d s2=%d s3=%d\n ",s1,s2,s3);}

int sum(int a,int b,int c) // Определение функции

{return a+b+c;}

В результате работы программы на экран выведется:

s1=35 s2=80 s3=170

2.5 Функции с переменным числом параметров

Функции с переменным числом параметров – это функции, в ко­торых количество и типы параметров определяются только во время их вызова. Синтаксис определения прототипа таких функций:

тип имя(спецификация явных параметров,...);

Последняя запятая необязательна. Многоточие сообщает компи­лятору, что не нужно проводить дальнейший контроль соответствия количества параметров и их типов при обработке вызова. Переход в списке от параметра к параметру осуществляется с помощью указате­ля, тип которого является типом переменной. При увеличении указа­теля на единицу осуществляется переход к следующей переменной такого же типа. В ВС31 функции с переменным числом параметров не работают с типами char, unsigned char, float.

В таких функциях существуют два способа определения коли­чества параметров: 1) передача в функцию в списке фактических параметров информации об их количестве; 2) добавление параметра–индикатора в конец списка фактических параметров.

Пример. В функцию передается в списке явных параметров количес­тво элементов, которые суммируются.

#include <stdio.h>

int sumi (int i,...) // Определение функции

{int *num=&i; // 1-й параметр – число переменных в списке

 int sum=0;

 for(;i;i--) sum+=*(++num);// вычисляем сумму со 2-го элемента

return sum;}

double sumd(int i,double d...) // Определение функции

{double *ptr=&d; // указатель на 2-й параметр типа double

 double sum=0.0;

 for(;i;i--) // 1-й параметр – число переменных в списке

sum+=*(ptr++);

 return sum;}

Void main()

{int a1=10,a2=20,a3=30,s1,s2;

 s1=sumi(3,a1,a2,a3); // сумма 3-х чисел a1,a2,a3

 s2=sumi(6,1,a 1,3,a 2,a3,4); // сумма 6-и чисел

 double d1=5. 7, d2=1. 3,s3;

 s3=sumd(4,d1,1.25,d2,2.5); // сумма 4-х чисел

 printf("s1=%d s2=%d s3=%.2lf\n",s1,s2, s3);}

В результате работы программы на экран выведется:

s1=60 s2=68 s3=10. 75

Пример. В функции вычисляется произведение элементов, при этом каждый элемент сравнивается с параметром–индикатором, который находится в конце списка явных параметров.

#include <stdio.h>

#define term 0. 0

double mult(double arg...) // Определение функции

{double a=1.0, *ptr=&arg;

 if(*ptr==0.0) return 0. 0;

 for(;*ptr!=term;ptr++)

a*=*ptr;

 return a;}

Void main()

{double a=2. 5,b=2. 0,md1,md2;

 md1=mult(a,b,0. 3,term);

 md2=mult(0. 5,a,4. 0,b,1. 1,term);

 printf("md1=%.2lf md2=%.2lf\n",md1,md2);}

В результате работы программы на экран выведется:

md1=1. 50 md2=11. 00

При работе с функциями, имеющими переменное параметров, имеется набор макроопределений, помещенных в заголовочном файле stdarg.h:

Макрокоманда void va_start (va_list param, последний явный параметр) связываетвспомогательный параметр param с последним явным параметром в списке.

Макрокоманда type va_arg (va_list param,type) переме­щает указатель param на число байтзаданного типа type.

Макрокоманда va_end (va_list param) вызывается после обработки списка и организует корректный возврат из функции (вместо оператора return).

2.6 Передача параметров в функцию main()

В функцию main(), как и в любую другую функцию, могут передаваться параметры. Для передачи параметров в функцию main() ее следует описать в таких формах:

[ тип ] main(int argc, char **argv){...}

[ тип ] main(int argc, char **argv, char **envp){...}

[тип] – тип функции main может быть void или int.

Параметр int argc определяет число слов в командной строке.

Параметр char **argv ‑ указатель на массив строк, вводимых из командной строки. Массив строк –это массив указателей, являющихся адресами первых символов этих строк. Размер этого массива строк равен argc. Нулевое слово, на которое указывает указатель argv[0], всегда является спецификацией запускаемой на выполнение програм­мы (именем программы с расширением .exe).

Параметр char **envp ‑ это указатель на массив указателей на строки среды программы. С помощью этого параметра в программу можно передать всю информацию среде окружения программы, ко­торая определяет некоторые особенности операционной системы и др.

В следующих примерах демонстрируется передача параметров в функцию main. Для работы программ их необходимо запустить из командной строки, например в среде FAR, NC, VC, DN и др.

Пример.

#include <stdio.h>

#include <conio.h>

int main(int argc,char**argv,char**envp)

{clrscr();

 for(int i=0;i<argc;i++)

 printf("argv[%d]=%s\n",i,argv[i]);

 getch();

 puts(" Среда окружения ");

 while(*envp) puts(*envp++);

getch();

 return 0;}

Пусть исполняемый файл этой программы prog1.exe располо­жен в корневом каталоге диска C:\. Тогда, если в командной строке набрать c:\>prog1.exe my age 19, то результат работы программы может быть такой:

argv[0]=C:\PROG1.EXE

argv[1]=my

argv[2]=age

argv[3]=19

Среда окружения

PROMPT=$p$g

COMSPEC=C:\WINDOWS\COMMAND.COM

PATH=C:\BC31\BIN

Proccessor_ArcHitecture=x86

Proccessor_identifier=x86 Family 15 Model 47

Proccessor_Level=15

...

В следующей программе для ее выполнения необходимо набрать заданное слово в командной строке.

Пример.

#include <stdio.h>

#include <conio.h>

#include <string.h>

int main(int argc,char **argv)

{clrscr();

 char str[]="Secret";

 if(strcmp(argv[1],str)!=0)// сравнение 2-х строк

{printf("Error\n"); getch(); return 1;}

 printf("Programma ");

 printf("%s %c.%c.\n",argv[2],argv[3][0],argv[4][0]);

int x, a=5, b=7,res1;

sscanf (argv [5], " % d",& x); // преобразование строки в целое число

res1=(a+b)*x; //(5+7)*100

 printf("res1=%d\n",res1);

getch();

 return 0;}

Пусть исполняемый файл этой программы prog2.exe распо­ложен в корневом каталоге диска C:\. Для правильной работы этой программы в командной строке надо набрать вторым словом Secret. Если в командной строке набрать:

c:\>prog1.exe Secret Petrov Ivan Ivanovich 100:

то на экран выведется:

Programma Petrov I.I.

res1=12 0 0

Если второе слово в командной строке будет другим, то на экран выведется Error, и программа завершится.

2.7 Рекурсивные и подставляемые функции

Рекурсивная функция – эта такая функция, которая содержит в себе вызов этой же функции, т.е. самовызывающая функция.

Рекурсивные функции желательно не использовать, если есть очевидное итерационное решение.

Пример. Вычисление факториала неотрицательного целого числа

long fact (int k) // Определение функции

{if(k<0) return 0;

if (k==0} return 1;

return k* fact(k-1);}

Void main()

{int n=5; long F_n=fact(n);

 printf (“%d!=%ld”,n,F_n);}

На экран выведется: 5!=120

Функция прерывается при k == 0, последнее выражение(1 * fact (1-1)),вычисляет k*(k-1)*(k-2)*(k-3)*(k-4)*1.

Подставляемая функция (inline -функция) – это функция, тело которой подст


Поделиться с друзьями:

Индивидуальные и групповые автопоилки: для животных. Схемы и конструкции...

История развития пистолетов-пулеметов: Предпосылкой для возникновения пистолетов-пулеметов послужила давняя тенденция тяготения винтовок...

Архитектура электронного правительства: Единая архитектура – это методологический подход при создании системы управления государства, который строится...

Семя – орган полового размножения и расселения растений: наружи у семян имеется плотный покров – кожура...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.351 с.