Использование ссылок для передачи параметров функции 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Использование ссылок для передачи параметров функции



Перепишем приведенную выше программу, но вместо указателей используем ссылки.

void swap (int&,int&);

int main (){

int x=1; y=2;

cout<< " x= " <<x<< " y= " <<y);// x=1 y=2

swap (&x,&y);

cout<< " x= " <<x<< " y= " <<y); // x=2 y=1

}

void swap (int&a,int&b){

int c;

c=a; a=b; b=c;

}

В случае, когда ссылка является формальным параметром функции, связывание происходит в момент, когда вызывается функция.

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

double x=1.0;

int f1(){

int y=1;

cout<<y; //1

}

int main (){

double x=2.0;

cout<<x<<" "<<::x; // 2.0 1.0

float y=2;

cout << y; //2

}

Пример. Найти наибольшее из трех чисел.

int z;

void MAX(int x; int y){

if (x>y) z=x;

else z=y;

}

int main (){

int a,b,c;

a= 1; b=2; c=3;

MAX (a,b);

MAX (c,z);

cout << z;

}

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

#include <iostream>

using namespace std;

int * p 1, * p 2; // Глобальные указательные на тип int переменные

void allocate () {

/* функция выделяет память для глобальых указателей и присваивает значения по адресам*/

p 1 = new int; // Выделить память

* p 1 = 88;    // Присвоить значение по указателю p 1

p 2 = new int (99); // Выделить память и присвоить значение

}

int main() {

allocate();

cout << *p1 << endl; // 88

cout << *p2 << endl; // 99

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

delete p1;

delete p 2;

return 0;

}

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

Использование библиотечных функций. Библиотечными называются вспомогательные функции, хранящиеся в отдельных файлах. Стандартные библиотеки входят в стандартную среду программирования на языках C, C++.

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

#include <iostream>

#include "myfuncs.h"

Если подключаемый файл указан в <>, то поиск будет происходить в стандартных каталогах, предназначенных для хранения заголовочных файлов. В случае, если подключаемый файл заключен в двойные кавычки, поиск будет происходить в текущем рабочем каталоге. Если файл не найден, то поиск продолжается в стандартных каталогах.

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

В С++ определены следующие библиотеки и соответствующие заголовочные файлы:

- <ios>, <iostream>, <istream>, <ostream>, <fstream>, <sstream>

- <iomanip>

- <string>

- <regex>

- <random>

- <limits>

- <stdexcept>, <exception>

- <complex>, <tuple>, <valarray>

- <locale>

- <typeinfo>

- <chrono>

- <codecvt>, <new>, <ratio>, <system_error>, <type_traits>.

Стандартная библиотека C ++ не поддерживает работу с датами. С++ наследует структуры и функции для работы с датой и временим с языка С. Чтобы получить доступ к данным функциям и структурам, необходимо подключить заголовочный файл <ctime>.

Существует четыре структурных типа данных, предназначенных для работы со временем: clock _ t, time _ t, size _ t, и tm. Типы clock _ t, size _ t и time _ t имеют возможность представлять системное время, а data это целочисленный тип.

Тип tm содержит дату и время в форме С-структуры со следующим набором элементов:

struct tm {

int tm_sec; // секунды 0 до 61

int tm _ min; // минуты 0 до 59

int tm_hour; // часы 0 до 24

int tm _ mday; // дни месяца 1 до 31

int tm _ mon; // месяцы 0 до 11

int tm_year; // year since 1900

int tm _ wday; // дни недели, начиная с воскресения

int tm _ yday; // номер дня, начиная с 1 января

int tm _ isdst; // часы с учетом «летнего времени»

}

Наиболее часто используемые функции для работы с датой и временем приведены в таблице 1.2.

 

Таблица 1.2 – Функции для работы с датой и временем

 

Функция Назначение
time_t time(time_t *time); Возвращает количество секунд между текущей календарной датой системы и 01.01.1970 г. Если системного времени нет, то возвращает 1.
char *ctime(const time_t *time); Возвращает указатель на строку следующего формата: day month year hours: minutes: seconds year \ n \0.
struct tm *localtime(const time_t *time); Возвращает указатель на структуру tm, в которой представлено текущее время.
clock_t clock(void); Возвращает количество времени, прошедшего с запуска программы. Если время не определено, то возвращает 1.
char * asctime (const struct tm * time); Возвращает указатель на строку, которая содержит информацию, хранящуюся в структуре * time, время ковертировано в форму: day month date hours:minutes:seconds year\n\0
struct tm *gmtime(const time_t *time); Возвращает указатель на время в форме tm-структуры. Время представлено в Coordinated Universal Time (UTC).
time_t mktime(struct tm *time); Возвращает указатель на метку времени, полученную на основании данных tm-структуры.
double difftime (time_t time2, time_t time1); Вычисляет разницу между time1 и time2 в секундах.
size_t strftime(); Используется, чтобы отформатировать дату и время в специальный формат.

В следующем примере продемонстрирован вывод на экран текущей даты и времени, а также Coordinated Universal Time.

#include <iostream>

#include <ctime>

using namespace std;

int main (){

// текущие дата и время, полученные на основе системного времени

time _ t now = time (0);

// текущая метка времени конвертируется в строку

char* dt = ctime(&now);

cout << "The local date and time is: " << dt << endl;

// текущая метка времени конвертируется tm -структуру для UTC

tm *gmtm = gmtime(&now);

dt = asctime(gmtm);

cout << "The UTC date and time is:"<< dt << endl;

}

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

The local date and time is: Sat Jan 8 20:07:41 2011

 

The UTC date and time is:Sun Jan 9 03:07:41 2011

В следующем примере продемонстрировано как можно выводить отдельные элементы даты и времени, например, день недели, месяц, год, часы, минуты и т.д.

#include <iostream>

#include <ctime>

using namespace std;

int main (){

// // текущие дата и время, полученные на основе системного времени

time_t now = time(0);

cout << "Number of sec since January 1,1970:" << now << endl;

tm * ltm = localtime (& now);

// вывод на экран различных компонент tm -структуры.

cout << "Year" << 1900 + ltm->tm_year<<endl;

cout << "Month: "<< 1 + ltm->tm_mon<< endl;

cout << "Day: "<< ltm->tm_mday << endl;

cout << "Time: "<< 1 + ltm->tm_hour << ":";

cout << 1 + ltm->tm_min << ":";

cout << 1 + ltm->tm_sec << endl;

}

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

Number of sec since January 1, 1970:1294548238

Year: 2011

Month: 1

Day: 8

Time: 22: 44:59

Рекурсивные определения функции. В математике рекурсивным называется определение любого понятия через само себя. Рассмотрим пример функции, которая вычисляет значение факториала для числа n.

long Fact (int n){

if (n<0) return 0;

if (n==0) return 1;

returnn*Fact (n-1);

}

Известный факт 0!=1 в нашем случае это будет опорное значение от которого начинается раскручивание всех последующих значений факториала. Последовательность рекурсивных обращений функции должна обязательно выходить на определенное значение. Весь маршрут последовательных вхождений компьютер запоминает в специальной области памяти называемой СТЭКОМ.

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

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

void func 1(int * x, int n) { /* указатель */

/*  */

}

или как

void fun c 1(int x [10]) { /* массив определенного размера */

/*  */

}

или

void funс1(int х[]){ /* массив без определенного размера */

/* */

}

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

int x [10];

func 1(x);

Следует помнить, что внитри функции работа происходит с оригиналом массива, а не с его копией.

Пример. Найти Евклидову норму строк матрицы.

double Norma (double *X; int n);{

int i;

double S=0;

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

S+=X[i]*X[i];

return sqrt(S);

}

int main(){

doubleA[5][10];

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

cout << Norma (A [ i ], 10);//передаем в функцию строку мартицы

}

//Упражнение определить функцию вывода двумерного массива

Указатели на функции. В языке С++, функции, как и другие элементы данных имеют адреса. Имя функции является начальным адресом, где функция находится в памяти, и, следовательно, может рассматриваться как указатель. Указатель на функцию объявляется следующим образом:

return-type (* function-ptr-name) (parameter-list)Примеры объявлений: double (* fp)(int, int) // fp указатель на функцию, которая принимает два параметра типа int и возвращает тип double double *dp;        // dp указатель на тип double (double-pointer) double * fun (int, int) // fun функция, которая принимает два параметра типа int и возвращает указатель на тип double double f (int, int); // f функция, которая принимает два параметра типа int и возвращает тип double fp = f;            // присваивается указателю fp адрес функции fВ следующем программном коде продемонстрирован вызов функции через указатель и по имени: int number1 = 5, number2 = 6; int (*fp)(int,int)=&add;    // вызов функции через указатель cout << fp(number1,number2) << endl; // вызов функции по имени cout << add(number1,number2) << endl; В следующем примере в зависимости от введенного знака операции выполняется то или иное действие над двумя переменными типа int: #include <iostream.h> int add(int n1, int n2) { return n1 + n2; } int sub(int n1, int n2) { return n1 - n2; } int mult(int n1, int n2) { return n1 * n2; } int main() { int number1 = 5, number2 = 6; int (* fp)(int, int); char c;// знак операции cout <<"Введите знак операции"; cin>>c; switch(c){ case '+': fp=&add; break; case '-': fp=&sub; break; case '*': fp=&mult; break; default: cout <<"Такая операция не реализована."; return 0; }; cout << number1<<c<<number2<<"="<<fp(number1,number2) << endl; } Указатель на функцию можно передавать как параметр в другую функцию. Пример: #include <iostream> using namespace std; int arithmetic(int, int, int (*)(int, int)); /*функция принимает три аргумента, 2 типа int и указатель на функцию, которая принимает два целочисленных аргумента и возвращает значение типа int */ int add(int, int); int sub(int, int); int add(int n1, int n2) { return n1 + n2; } int sub(int n1, int n2) { return n1 - n2; } int arithmetic(int n1, int n2, int (*operation) (int, int)) { return (*operation)(n1, n2); } int main() { int number1 = 5, number2 = 6; // выполняется сложение number1 и number2 cout << arithmetic(number1, number2, add) << endl; // выполняется вычитание number1 и number2 cout << arithmetic(number1, number2, sub) << endl; }

Встраиваемые (Inline) функции. В С++ можно задать функцию, которая на самом деле не вызывается, а ее тело встраивается в программу на этапе компиляции в месте ее вызова (подобно макроопределениям с параметрами в языке С). Inline-функции могут выполняться гораздо быстрее, чем обычные функции, т.к. выполнение машинных команд, которые генерируют вызов функции, передачу параметров, возврат значения, занимает определенное время. Если же встраниваеме функции состоят из большого объема кода, то это приведет к существенному увеличению объема программы вцелом. Из-за этого применение встраиваетмых функций ограничивается короткими функциями. Чтобы функция было объявлена как встраиваемой, перед ее объявлением необходимо написать ключевое слово inline.

Пример.

inline isEven(int x) {return!(x%2);}

int main(){

int n=10;

cout<< " Число "<<n;

if(isEven(n)) cout<< " четное.";

else cout << " нечетное.";

}

На экран будет выведено:

Число 10 четное.

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

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

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

   тип main(){/*…*/}

                           или

   тип main(intargc, char*argv[]){/*…*/}

Функция main() может иметь два параметра. Имена параметров в программе могут быть любыми, но принято использовать argc и argv.

- a rgc определяет количество параметров, передаваемых функции, включая имя самой программы.

- a rgv является указателем на массив указателей типа char. Каждый элемент массива содержит указатель на отдельный параметр командной строки, хранящееся в виде С-строки, оканчивающейся null-символом.

Первый элемент массива argv[0] ссылается на полное имя, запускаемого на выполнение файла.

Следующий argv[1] указывает на первый параметр; argv[2] – на второй и т.д. Параметр argv[argc] должен быть равен 0. Если функция main() ничего не возвращает, вызвавшая система получит значение,означающее успешное завершение. Ненулевое значение означает аварийное завершение. Оператор возврата из main() можно опускать.

Использование в программном коде параметоров функции main (). В качестве примера напишем программу сложения двух чисел, которую назовем, например, sumToArg. Программный код сохраняем в файле sumToArg. cpp, следовательно, исполнимый код программы будет находиться в файле sumToArg. exe.

/*Программа выполняет сложение двух чисел, введенных из командной строки*/

#include<stdlib.h>

#include<stdio.h>

int main(intargc, char*argv[]){

   float a,b;//слагаемые

   /*Массив argv[] содержит значения параметров в виде строк. argv [0]- название программы; argv [1] – первое слагаемое; argv [2] – второе слагаемое.*/Ч

   //Для выполнения сложения их надо перевести в тип float

               a=atof(argv[1]);

               b=atof(argv[2]);

               cout<<a<<"+"<<b<<"="<<a+b);

   return 0;

}

   Как сказано выше параметры, в функцию приходят как строки. Но для выполнения арифметических действий значения параметров нужно перевести к нужному нам типу данных. Для этого имеется ряд функций в библиотеке stdlib. h.

atof(argv[1]) – переводит аргумент к типу float;

atoi(argv[1]) – переводит аргумент к типу int.

Запуск программ из командной строки. Для того чтобы запустить программу воспользуемся командной строкой cmd. С помощью команды cd пе реходим в директорию, где находится программа sumToArg. exe. Далее пишем название программы, параметры (разделяются пробелами) и нажимаем клавишу Enter, чтобы запустить программу.

Рассмотрим еще один пример. Через командную строку передается последовательность чисел. Написать программу, которая определит, сколько отрицательных значений содержится в данной последовательности.

 

#include<stdlib.h>

#include<stdio.h>

int main(int argc, char*argv[]){

int count=0;

for(i=1;i<argc;i++)

if(atof(argv[i])<0) count++;

if(count==0)cout<<"No";

else cout<<"otric - "<<count; return 0;

}

Количество членов последовательности можем вычислить исходя из значения параметра argc. Сами значения последовательности располагаются в массиве argv [] начиная с индекса 1. Элемент argv [0] содержит имя программы.

 

Контрольные вопросы и задания

1. Раскройте суть понятия функция.

2. Приведите синтаксис объявления, определения и вызова функции.

3. Какие виды передачи параметров в функцию имеются в С++?

4. Изобразите в виде блок-схемы алгоритм выполнения функции

5. Объясните назначения прототипа функции.

6. Какие библиотеки функций имеются в языке С++? Как их подключить к разрабатываемому программному коду?

7. В чем особенность встроенных функций?

8. Какие параметры имеет функция main()? Приведите пример их использования в программе. 


 

 

Классы и объекты



Поделиться:


Последнее изменение этой страницы: 2019-05-20; просмотров: 162; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.21.248.47 (0.081 с.)