План:
Функциите като черни кутии
Писане на функции
Коментари и документиране
Връщане на стойност и оператор return
Параметри на функции
Деклариране на функции
Странични ефекти и процедури
Параметри-псевдоними
** Функциите като черни кутии
Функция е част от код, определен с име.
До сега сме използвали редица функции, които са предоставени:
-- от системните библиотеки на С++
sqrt(x) - пресмята корен квадратен на числото с
плаваща точка x
getline(cin, s) - чете
един ред от потока cin
-- като член-функции от класа string на Стандартната библиотека
с шаблони на С++
s.length() - връща дължината на низа s
-- като член-функции от потребителските класове Time
и Employee, дефинирани в учебника
t.get_second() - връща секундите от обекта t на класа Time
Функциите могат да се разглеждат като черни кутии, за които
знаем само вход и изход, без да се интересуваме как работи
функцията.
- Изпълнението на main() временно се прекратява докато се изпълнява функцията sqrt.int main()
{ cout << "Enter a positive number: ";
double x;
cin >> x;
x = sqrt(x); // sqrt is running
cout << "The result is " << x << "\n";
return 0;
}
|
|
Член-функция | Неявен параметър | Тип
на неявен параметър |
Явен параметър |
Тип на явен параметър |
harry.get_salary() | harry | Employee | няма |
- |
t.add_seconds(10) | t | Time | 10 |
int |
s.substr(0,num) | s | string | 0, num |
int, string |
Функция | Тип на върнатата стойност |
sqrt(x) | double |
c.substr(0, num) | string |
t.get_seconds() | int |
e.set_salary(s) | no return value |
Функция | Изисквания за
параметрите - тип и lvalue/rvalue |
fabs(w) | Параметърът w е от тип double
- константа, променлива, израз (rvalue) |
t.second_from(t1) | Параметърът t1 е обект от класа Time - константа, променлива |
getline(cin,s) | Първият параметър е обектът cin, вторият
параметър е променлива (lvalue) от тип string |
double future_value(double p)* Функцията се дефинира като се зададе:
{ double b = 1000 * pow(1 + p / 100, 10);
return b;
}
// futval1.cpp
#include <iostream>
#include <cmath>
using namespace std;
// дефиниция на функция
double future_value(double p)
{ double b = 1000 * pow(1 + p / 100, 10);
return b;
}
int main()
{ cout << "Please enter the interest rate in percent: ";
double rate;
cin >> rate;
// извикване на функция
double balance = future_value(rate);
cout << "After 10 years, the balance is "
<< balance << "\n";
return 0;
}
nkirov@cpp % c++ futval1.cpp nkirov@cpp % ./a.out Please enter the interest rate in percent: 8 After 10 years, the balance is 2158.92 |
double future_value(double initial_balance, double p, int n)
{ double b = initial_balance * pow(1 + p / 100, n);
return b;
}
futval.cppdouble balance = future_value(1000, rate, 10);
nkirov@cpp % c++
futval.cpp nkirov@cpp % ./a.out Please enter the interest rate in percent: 12 After 10 years, the balance is 3105.85 |
/**Може да се използва и показания формат за български език.
Computes the value of an investment with compound interest.
@param initial_balance - the initial value of the investment
@param p the interest rate per period in percent
@param n the number of periods the investment is held
@return the balance after n periods
*/
double future_value(double initial_balance, double p, int n)
{ double b = initial_balance * pow(1 + p / 100, n);
return b;
}
Всеки клон на функцията (вследствие на оператор if) трябва да връща някаква стойност.double future_value(double initial_balance, double p, int n)
{ if (n < 0) return 0;
if (p < 0) return 0;
double b = initial_balance * pow(1 + p / 100, n);
return b;
}
Последният оператор на всяка функция би трябвало да бъде оператор return.double future_value(double initial_balance, double p, int n)
{ if (p >= 0)
return initial_balance * pow(1 + p / 100, n);
/* Error */
}
Функция, която връща булева стойност се нарича предикат.bool approx_equal(double x, double y)
{ const double EPSILON = 1E-14;
if (x == 0) return fabs(y) <= EPSILON;
if (y == 0) return fabs(x) <= EPSILON;
return fabs(x - y) / max(fabs(x), fabs(y)) <= EPSILON;
}
// approx.cpp
#include <iostream>
#include <algorithm>
using namespace std;
/**
Tests whether two floating-point numbers are
approximately equal.
@param x a floating-point number
@param y another floating-point number
@return true if x and y are approximately equal
*/
bool approx_equal(double x, double y)
{ const double EPSILON = 1E-14;
if (x == 0) return fabs(y) <= EPSILON;
if (y == 0) return fabs(x) <= EPSILON;
return fabs(x - y) / max(fabs(x), fabs(y)) <= EPSILON;
}
int main()
{ double x;
cout << "Enter a number: ";
cin >> x;
double y;
cout << "Enter another number: ";
cin >> y;
if (approx_equal(x, y))
cout << "The numbers are approximately equal.\n";
else
cout << "The numbers are different.\n";
return 0;
}
nkirov@cpp % c++
approx.cpp nkirov@cpp % ./a.out Enter a number: 1 Enter another number: 1.0000000000000001 The numbers are approximately equal. nkirov@cpp % ./a.out Enter a number: 10 Enter another number: 10.001 The numbers are different. |
* Формални параметри - параметри-променливи, които се задават при дефиниране на функцията.
double future_value(double initial_balance, double p, int n)
* Фактически параметри (аргументи) -
представляват изрази за инициализация на
параметрите-променливи и се задават при извикване на
функцията.
b = future_value(total/2, rate, year2-year1);
Фактическите параметри съответстват по тип и брой на формалните параметри: променливите total и rate са от тип double, а year1 и year2 са от тип int .
Формалните параметри са променливи, които може да се променят
в тялото на функцията.
double future_value(double initial_balance, double p, int n)
{ p = 1 + p / 100;
double b = initial_balance * pow(p, n);
return b;
}
Често това се счита за лош стил на програмиране (bad
programming style).
// printime.cpp
#include <iostream>
#include <iomanip>
using namespace std;
#include "ccc_time.h"
/**
Print a time in the format h:mm:ss
@param t the time to print
*/
void print_time(Time t)
{ cout << t.get_hours() << ":" << setw(2) << setfill('0')
<< t.get_minutes() << ":" << setw(2)
<< t.get_seconds() << setfill(' ');
}
int main()
{ Time liftoff(7, 0, 15);
Time now;
cout << "Liftoff: ";
print_time(liftoff);
cout << "\n";
cout << "Now: ";
print_time(now);
cout << "\n";
return 0;
}
nkirov@cpp % c++ printime.cpp
ccc_time.cpp nkirov@cpp % ./a.out Liftoff: 7:00:15 Now: 11:00:00 |
** Параметри-псевдоними
Пример: Функция за увеличаване на заплата.
Процедурата raise_salary увеличава заплатата на служител e с by процента.
raise_salary(harry, 5);
void raise_salary(Employee& e, double by)
{ double new_salary = e.get_salary() * ( 1 + by / 100);
e.set_salary(new_salary);
}
// raisesal.cpp
#include <iostream>
using namespace std;
#include "ccc_empl.h"
/**
Raise an employee salary
@param e employee receiving raise
@param by the percentage of the raise
*/
void raise_salary(Employee& e, double by)
{ double new_salary = e.get_salary() * (1 + by/100);
e.set_salary(new_salary);
}
int main()
{ Employee harry("Hacker, Harry", 45000.00);
raise_salary(harry, 5);
cout << "New salary: " << harry.get_salary() << "\n";
return 0;
}
Формалният параметър Employee& e на функцията raise_salary е параметър-псевдоним на променливата harry от главната функция main.
Промяната на стойността на параметъра-псевдоним e във функцията raise_salary води до промяна и на стойността на фактическия параметър (променливата) harry от функция main.
Параметрите-псевдоними се наричат още входно-изходни параметри - те пренасят информация от извикващата функция към извиканата функция и обратно.