Использование функции как параметра значений
Иногда приходится в качестве формальных аргументов (параметров) функции использовать другие функции. Такая ситуация возникает, если в некоторой функции при обращении к ней, надо вызвать другую функцию. Параметр - функция записывается в виде прототипа, т.е. указывается тип функции, ее имя и в скобках перечень типов формальных аргументов, или типов и имен формальных аргументов.
Пример 5.4 Составить программу c использованием функции вычисления интегралов метoдом трапеций (точность вычисления е =10-3 ).
// P5_4.CPP – вычисление интеграла методом трапеции // использование функции как параметра значения # include < iostream . h> #include <math.h> const float e =1 e-3; float fn1 (float x ) // подынтегральная функция 1-го интеграла { return sgrt (1 + log ( x)); } float fn2 ( float x ) // подынтегральная функция 2-го интеграла { return log (1 +pow (x,2)) / (1+pow (x,2)); } float ft (int n, float a ,float b , float fun( float )) // функция метода трапеций { int i; float s1 ,h, s=0; do { s1 =s; h = (b -a ) /n; s = ( fun (a) +fun (b) ) / 2; for ( i = 1; i <= n-1; i++) s += fun ( a + i *h ); s *= h; n *= 2; } while ( fabs ( s-s1 ) > e ); return s; } main ( ) { float y; y = ft ( 20 , 2 , 2, 3.0, fn1 ) +ft ( 20, 0, 1.0, fn2 ); cout << "y=" << y << endl; } Результат выполнения программы : y = 1.29012 Обращение к функции и передача результата Для обращения к функции достаточно написать ее имя и в скобках записать значения либо перечень фактических аргументов. Фактические аргументы должны быть записаны в той же последовательности, что и формальные и иметь соответствующий тип (кроме аргументов по умолчанию и перегруженных функций). Если формальными аргументами функции являются параметры значения и в ней не используются глобальные переменные, то функция может передать в вызывающую программу лишь одно значение, которое записывается в операторе return . Это значение передается в точку вызова функции. Фрагмент программы , подтверждающий вышеизложенное может иметь вид : double sgr (double); main( ) { cout << "Квадрат числа =" << sgr ( 10 ) << endl; } double sqr ( double p) // Возврат по значению { return p* p; }
В результате будет выведено: Квадрат числа = 100. Используя оператор return можно также организовать досрочный выход из функции. Если из функции надо передать не одно, а несколько значений, то можно либо использовать глобальные переменные, либо массивы. Имя функции ¾ это константа - указатель на функцию, который указывает на адрес точки входа (адрес первой машинной команды) функции. Следует отметить, что возможно также описание и указателей переменных на функции. Для этого используется операция разыменования "*", функции описанные таким образом должны возвращать указатель на тип, т.е. его адрес. В С++ определено несколько способов передачи и возвращения результата вычислений, наиболее широко используемыми являются рассмотренные ранее: ¾ вызов функции с передачей параметров с помощью формальных аргументов - значений; ¾ вызов функции с передачей адресов с помощью параметров - указателей; ¾ вызов функций с использованием ссылок, когда доступ к передаваемым параметрам обеспечивается с помощью альтернативного имени (синонима); ¾ вызов функций с передачей данных посредством глобальных переменных, например: #include < iostream.h > int a, b, c; sum ( ) main ( ) { cin >> a >> b; sum (); cout << c << endl; } sum( ) { c = a + b ; } ¾ вызов функций с использованием параметров, заданных по умолча-нию, при этом можно использовать либо все аргументы, либо их часть. При вызове функции, у которой аргументы заданы "по умолчанию", соблюдается такое правило : если какой - либо аргумент используется по умолчанию, то и все последующие аргументы должны быть использованы со значениями по умолчанию.
Пример 5.5 Вычислить квадратную функцию общего вида для заданного значения аргумента x с использованием функции, в которую коэффициенты a, b и c могут быть введены по умолчанию. // P5_5.CPP ¾ вычисление квадратной функции // коэффициенты квадратной зависимости могут // вводиться в функцию "по умолчанию" #include < iostreа m.h > float ur ( float x, float а =0., floatb b =0.,float c=0.); Int main ( ) { float а =1., b = 2., c = 3., x = 0.5, y; cout << " Введены все аргументы " << endl; y = ur ( x, a, b, c); cout << " y = "<< y << endl; cout << " Введены аргументы x, a, b " << endl; y =ur ( x, a, b); cout << " y = "<< y << endl; cout << " Введен аргумент x " << endl; y =ur ( x ); cout << " y = "<< y << endl; } // Функция вычисления квадратной функции float ur ( float x, float a, float b, float c ); { return a * x * x + b * x + c; } Результаты выполнения программы: Введены все аргументы y = 4.25 Введены x, a и b y = 1.25 Введен аргумент x y = 0 Перегрузка функций В языке С++ можно использовать так называемую перегрузку функций, т.е. возможность определять функции с одним и тем же именем, но различным типом и количеством формальных параметров. Список формальных аргументов называют сигнатурой функции. Основное достоинство перегруженных функций ¾ это возможность определять несколько функций с одним и тем же именем, но с разными типами и числом параметров. Пример 5.6 Произвести программную реализацию с использованием перегрузки функций.
#include <iostream .h> #include <string.h> int funp (int x) // 1. { return x*x; } int funp (unsigned x) // 2. { return -x*x; } char funp (char x) // 3. { return x+3; } int funp (int x, char *y) // 4. { return x*strlen ( y); } int funp (int x , char y) // 5. { return x*y; } float funp (float r) // 6. { return r*r; } float funp (double r) // 7. { return r+r; }
Main ( ) { cout << funp(5) << endl ; // Будет 25 cout << funp ((unsigned)10) << endl ; // Будет 100 cout << funp ( 'a') << endl ; // Будет d cout << funp (4,"abc") << endl ; // Будет 12 cout << funp ( 4 , 'a') << endl ; // Будет 388 cout << funp( (float5) 1.2)<< endl ; // Будет 1.44 cout << funp( double) 4.5) << endl ; // Будет 9 return 0; }
В заголовке функции всегда указывается тип ее имени, а в самой подпрограмме этому имени должно быть присвоено значение, которое возвращается в главную программу вместо обращения к функции.
5.3 Контрольные вопросы 1. Что такое функция и какова ее структура? 2. Что означает передача параметров в функцию по значению, по ссылке и по указателю? 3. Что такое локальные и глобальные переменные? 4. Как использовать указатели на функцию? 5. Каковы способы передачи и возврата результата вычислений функции? 6. Как использовать одномерные массивы в качестве параметров функции? 7. Каковы особенности использования многомерных массивов в качестве аргументов функции? 8. Можно ли обрабатывать в функции массивы переменной длины? 9. Может ли функция передавать несколько результатов в точку вызов? 10. Что такое перегрузка функций? РАБОТА С ФАЙЛАМИ
В качестве элементов файла можно использовать любые данные языка С++ (числа, символы, строки, массивы и структуры). При использовании большого количества обрабатываемых в программе данных целесообразно их записывать на диск, т.е. создать на диске файл данных. Перед созданием, записью данных в файл или чтением их из файла, этот файл надо вначале открыть. В процессе ввода–вывода с использованием стандартных устройств (клавиатуры и экрана) в программу следует включить заголовочный файл iostream.h, в котором содержится описание соответствующего класса iostream, т.е в начале текста программы помещают директиву :
# include < iostream. h> Файловый ввод–вывод и необходимые функции–члены ввода–вывода описаны в заголовочном файле fstream, содержащем описание основных классов и методов. Существуют также дополнительные файлы библиотеки ввода–вывода, содержащие более специализированные функции – члены ввода–вывода. Для открытия файла на диске используется функция–член класса fstream, которая имеет следующий прототип (заголовок): void open (const char *filename, int mode, int m = flebuf :: openprompt); где filename ¾ имя открываемого файла, в котором при необходимости можно указать путь; mode ¾ параметр, задающий режим ввода , в файле fstream определены значения этого режима и их смысл; m ¾ параметр, задающий защиту файла, который по умолчанию принимает значение, заданное константой filebuf :: openprompt ; Параметр mode может принимать одно из значений, назначаемое в зависимости от цели открытия файла, либо комбинацию этих значений, полученную с использованием операции " ИЛИ " , т.е. "\" . Они имеют вид:
ios :: app ¾ файл (поток) открывается для добавления ("а"); ios :: in ¾ файл открывается для чтения (" r ") ; ios :: out ¾ файл открывается для записи ("w "); ios :: ate ¾ открыть файл и установить указатель потока на конец файла; ios :: binary ¾ открыть файл в двоичном режиме ("в"); ios :: trunc ¾ открыть файл и удалить содержимое файла ; ios :: nocreate ¾ открыть существующий файл, если он не существует ¾ операцию завершить отказом; ios :: noreplace ¾ если файл существует ¾ выдать сообщение об ошибке, за исключением случаев поиска конца файла или добавления в файл.
Рассмотрим некоторые примеры записей функций открытия файла :
# include < fstream. h> main ( ) { fstream fp; // описание файловой переменной;
// открывается файл myfile.dat для записи, т.е. создается новый файл; fp. open ( " a : \ cpp \ myfile.dat " , ios :: out)
// открывается ранее созданный файл file2.dat для чтения данных; fp.open (" c : \ vp \ file2.dat ", ios :: in );
// открывается файл для чтения или записи или с использованием // двоичного режима; fp .open (" myfile " , ios :: out | ios :: in | ios :: binary);
……………………………………………………………… }
Файловая переменная fp должна быть предварительно описана как объект класса fstream или ofstream . Если во время открытия файла происходит ошибка, то всегда fp = 0, т.е. файловая переменная-объект равна нулю (не NULL ). Это используется для определения результата открытия файла следующим образом :
#include <fstream.h> main ( ) {
ofstream . fp; fp.open ( " Filename " , ios :: app); // Добавить в файл if (!fp ) { cout << "Ошибка открытия файла " << endl;
Exit (0); } // Выход из программы Else { // Текст программы работы с файлом } }
Для организации цикла с целью просмотра всего файла, можно использовать оператор цикла в виде:
while ( ! fp. eof ( )) {…………… ………….}
Пример 6. 1 Записать в файл пять фамилий. //P5_1.CPP¾ запись в файл пяти фамилий #include < fstream .h > ofstream fp; main ( ) { fp.open ( " a : \ Myfile " , ios :: out); // Создание нового файла fp << " Авдеев А.И. " << endl; fp << " Бобров А.П. " << endl; fp << " Кузьмин И.В. " << endl; fp << " Попов Р.Л. " << endl; fp << " Яковлев Ю.Т. " << endl; fp. close ( ); // Закрытие файла } Этот фрагмент лучше записать в виде:
#include < fstream.h > ofstream fp; main ( ) { char s [ 5][15]; fp . open ( " a :\ Myfile1 " , ios :: out); for ( int i = 0; i < 5 ; i++ ) fp. getline ( s [ i ] ) fp. close; } Открывать файлы можно и иначе, например, используя классы ifstream ¾ для чтения из файла (т.е. ввода) и ofstream ¾ для записи в файл (т.е. вывода из ОЗУ) : ifstream in ( " Namefile "); // открытие файла для чтения из файла ofstream out ( " Namefile2 "); // открытие файла для записи в файл ,
где in и out ¾ файловые переменные соответствующего класса.
Пример 6. 2 Копирование одного текстового файла в другой файл.
// P5_2.CPP ¾ копирование текстового файла file1 в файл file2 #include <iostream.h> #include <fstream.h> void main ( ) { ifstream in ( ”file1") ; ofstream out ( "file2") ; char st [80]; while ( ! in.eof ( ) ) { in .getline ( st, 80 ) // in ¾ объект ifstream out << st << endl; } // запись st в файл file2 cout << st << endl; // вывод st на экран } Конструкторы ifstream и ofstream могут быть записаны в виде: ifstream in (const char *name, int mode = ios :: in, int prot = filebuf :: penprot); т.е. эти конструкторы могут включать те же аргументы, что и open. Пример 6. 3 Записать в файл заданную матрицу matr ( 2, 4) построчно.
//P5_3.CPP ¾ запись в файл матрицы построчно #include <iostream.h> #include <fstream.h> void main ( ) { int mas [4], matr [2] [4]; ofstream out ( " filemat " , ios :: out | ios :: binary ); for ( i = 0; i < 2; i++) { for ( j = 0; j < 4; j++ ) cin >> mas [j]; out << mas; } out . close( ); ifstream in ( " filemat ”, ios :: in | ios :: binary); for ( i = 0; i < 2 ; i++) { in >> mas ; // Чтение массива из файла for ( j = 0 ; j < 4; j++) matr [ i ] [ j ] = mas [ j ] ; // Запись массива в строку матрицы } in . close ( ); for ( i = 0; i < 2 ; i++ ) // Вывод матрицы на экран { cout << endl ; for ( j = 0; j < 4 ; j++) cout << matr [ i] [ j]; } } 6.3 Контрольные вопросы 1. Чем файл отличается от массива ? 2. С помощью какой функции можно распознавать конец файла ? 3. Как описывается файловая переменная ? 4. Какой порядок создания файла ? 5. Каковы способы открытия файлов ? 6. Какие параметры могут использоваться в качестве компонентов файла ?
ЛИТЕРАТУРА И ИСТОЧНИКИ
1. Романовская Л. М. и др. Программирование в среде Си для ПЭВМ ЕС / Л. М. Романовская, Т.В. Русс, С. Г. Свитковский. - М.: Финансы и статистика, 1992.- 352 с. 2. Макогон В. С. Язык программирования Си для начинающих: Учебное пособие / В. С. Макогон. - Одесса: 1993. 96 с 3. Подбельский В. В. Язык С++ : Учеб. Пособие. – 5 - е изд. - М.: Финансы и статистика, 2000. - 560 с 4. Проценко В. С. та ін. Техніка програмування мовою Сі: Навч. посібник / В. С. Проценко, П. И. Чаленко, А. Б. Ставровський. - К. Либідь, 1993. - 224 с 5. Программирование на С++. Учебное пособие / В. П. Аверкин, А. И. Бобровский, В. В. Веснин, В. Я. Радушинский, А. Д. Хомоненко; Под ред. проф. А. Д. Хомоненко – СПБ: КОРОНА принт,1999 – 256 с., ил. 6. Харви Дейтел, Пол Дейтел. Как програмировать на С++: Пер с анг. – М. ЗАО «Издательство БИНОН», 1998г. – 1024с., ил.
Популярное: Почему стероиды повышают давление?: Основных причин три... Почему люди поддаются рекламе?: Только не надо искать ответы в качестве или количестве рекламы... Как построить свою речь (словесное оформление):
При подготовке публичного выступления перед оратором возникает вопрос, как лучше словесно оформить свою... ©2015-2024 megaobuchalka.ru Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. (271)
|
Почему 1285321 студент выбрали МегаОбучалку... Система поиска информации Мобильная версия сайта Удобная навигация Нет шокирующей рекламы |