void raise_salary(Employee& e, double
by)
/* ЦЕЛ:
увеличава заплатата на даден служител
RECEIVES: e - служител, получаващ
увеличение
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;
}
New salary: 47250 |
Формалният параметър Employee& e на функцията raise_salary е параметър-псевдоним на променливата harry от главната функция main.Промяната на стойността на параметъра-псевдоним e във функцията raise_salary води до промяна и на стойността на фактическия параметър (променливата) harry от функция main. Затова параметрите-псевдоними се наричат още входно-изходни параметри - те "пренасят" информация от извикващата функция към извиканата функция и обратно.
Константни
псевдоними.
Използват се за да се избегне копирането - особено
нежелателно, ако параметърът е обект, съдържащ много данни. Тъй като стойността
на константния псевдоним не може да се променя, той не "пренася" информация
от извиканата функция в извикващата функция.
void print_employee(Employee const &
e)
{
cout << "Name:
" << e.get_name()
<<
"Salary: " << e.get_salary();
}
параметри-променливи | параметри-псевдоними | константни псевдоними |
входни параметри за функцията | входно-изходни параметри за функцията | - |
предаване на параметри чрез копиране | предаване на параметри по адрес | предаване на параметри по адрес |
стойността на параметъра може да се променя | стойността на параметъра може да се променя | стойността на параметъра не може да се променя |
фактически параметър може да бъде константа, променлива или израз | фактически параметър може да бъде само променлива | фактически параметър може да бъде константа, променлива или израз |
Област на
действие на променливите, глобални променливи.
Ако едно и също име на променлива се използва в
две функции, то не съществува връзка между двете променливи.
Областта на действие на променлива, която е дефинирана в блока на функция,
се простира единствено в рамките на тази функция.
//futval1.cpp
#include <iostream>
#include <cmath>
using namespace std;
double f_val(double i_bal, double p, int
ny) /*дефиниции на параметрите-променливи
i_bal, p и ny*/
{
double r; /*дефиниция
на променливата r в блока на функцията future_value*/
r = i_bal*pow(1 + p/(12*100), 12*ny);
return r;
} /*край
на областта на действие на променливите i_bal, p, ny и r*/
int main()
{
cout << "Interest rate in
percent: ";
double r; /*дефиниция
на променливата r в блока на функцията main*/
cin >> r;
double bal = f_val(1000, r, 10);
/*дефиниция на променливата bal*/
cout << "After 10 years, the
balance is " << bal << "\n";
return 0;
} /* край
на областта на действие на променливите r и bal*/
В примера няма връзка между двете променливи с име
r
в
двете функции future_value и main.
Променлива, дефинирана в блок на функция, се нарича
локална
променлива. Областта на действие на локална променлива е от мястото
на дефинирането до края на блока, в който е дефинирана променливата. В
тази област променливата е видима, т.е. може да бъде използвана.
// global.cpp
#include <iostream>
using namespace std;
#include "ccc_empl.cpp"
double annual_raise; /*
дефиниране на глобална променлива */
void raise_salary(Employee& e)
{ double new_salary = e.get_salary()*(1
+ annual_raise/100);
e.set_salary(new_salary);
/*
използване на глобалната променлива */
}
int main()
{ Employee boss("Reindeer, Rudolf",
48000.00);
Employee harry("Hacker, Harry",
35000.00);
annual_raise = 5; /*
използване на глобалната променлива */
raise_salary(boss);
raise_salary(harry);
cout << boss.get_name()
<< " " << boss.get_salary() << "\n";
cout << harry.get_name()<<
" " << harry.get_salary()<< "\n";
return 0;
}
Reindeer, Rudolf 50400
Hacker, Harry 36750 |
Променлива, дефинирана извън блок на функция, се
нарича глобална променлива. Областта на действие на глобална променлива
е от мястото на дефинирането до края на файла, в който е дефинирана променливата.
Досега са използвани глобалните променливи (обекти) cin и
cout,
които са дефинирани в заглавния файл iostream.h.
Глобалните
променливи предават данни между функциите, което трябва да се избягва.
Използването им трябва да става само ако има основателна причина за това.
Нормалният обмен на данни между функциите става с помощта на параметрите
на функциите.
string digit_name(int n)
/* ЦЕЛ: превръща цифра в английското
й име
ПОЛУЧАВА: n - цяло число
между 1 и 9
ВРЪЩА: името на n ("one"
. . . "nine")
*/
{ if (n == 1) return "one";
else if (n == 2) return "two";
else if (n == 3) return "three";
else if (n == 4) return "four";
else if (n == 5) return "five";
else if (n == 6) return "six";
else if (n == 7) return "seven";
else if (n == 8) return "eight";
else if (n == 9) return "nine";
return "";
}
string teen_name(int n)
/* ЦЕЛ: превръща цяло число между
10 и 19 в английското му име
ПОЛУЧАВА: n - цяло число
между 10 и 19
ВРЪЩА: името на n ("ten"
. . . "nineteen")
*/
{ if (n == 10) return "ten";
else if (n == 11) return
"eleven";
else if (n == 12) return
"twelve";
else if (n == 13) return
"thirteen";
else if (n == 14) return
"fourteen";
else if (n == 15) return
"fifteen";
else if (n == 16) return
"sixteen";
else if (n == 17) return
"seventeen";
else if (n == 18) return
"eighteen";
else if (n == 19) return
"nineteen";
return "";
}
string tens_name(int n)
/* ЦЕЛ: дава английското име на
десетиците между 20 и 90
ПОЛУЧАВА: n - цяло число
между 2 и 9
ВРЪЩА: името на 10*n
("twenty" . . . "ninety")
*/
{ if (n == 2) return "twenty";
else if (n == 3) return "thirty";
else if (n == 4) return "forty";
else if (n == 5) return "fifty";
else if (n == 6) return "sixty";
else if (n == 7) return "seventy";
else if (n == 8) return "eighty";
else if (n == 9) return "ninety";
return "";
}
string int_name(int n)
/* ЦЕЛ: превръща цяло число в английското
му име
ПОЛУЧАВА: n - цяло положително
число < 1000000
ВРЪЩА: името на n (т.е.
"two hundred seventy four")
*/
{ int c = n; /* оставащата
за превръщане част */
string r; /* стойността
на функцията */
if (c >= 1000)
{ r = int_name(c /
1000) + " thousand";
c = c %
1000;
}
if (c >= 100)
{ r = r + " " + digit_name(c
/ 100) + " hundred";
c = c %
100;
}
if (c >= 20)
{ r = r + " " + tens_name(c
/ 10);
c = c %
10;
}
else if (c >= 10)
{ r = r + " " + teen_name(c);
c = 0;
}
if (c > 0)
r = r +
" " + digit_name(c);
return r;
}
int main()
{ int n;
cout << "Please enter
a positive integer: ";
cin >> n;
cout << int_name(n);
return 0;
}
Please enter a positive integer: 20119
twenty thousand one hundred nineteen |
Предусловия
и макрос assert.
Какво трябва да направи една функция, ако е извикана
с неподходящ вход? Има два варианта - да завърши нормално или да прекъсне
работата на програмата. Първият вариант е подходящ, когато функцията може
да върне нещо разумно на извикващата функция - напр. digit_name
от
предишния пример връща празен низ. Стандартните аритметични функции прекъсват
работата на програмата със съобщение за грешка.
Едно решение на проблема е да се използва макрос
assert.
Когато
се тества програмата, той дава мястото на "грешката" (некоректни входни
данни на функция) в текста на програмата. Когато програмата е готова, може
да се изключи проверката на assert с директива на
препроцесора.
//fincalc.cpp
#include <iostream>
#include <cmath>
#include <assert.h>
using namespace std;
double future_value(double initial_balance,
double p, int nyear)
{ assert(nyear>=0 && p>=0);
return initial_balance*pow(1 +
p/(12*100), 12*nyear);
}
int main()
{ cout << future_value(1000,6,-5);
return 0;
}
fincalc.cpp:8: failed assertion `nyear>=0
&& p>=0'
abnormal program termination |
Ако условието в assert
е
изпълнено, нищо не се случва. Ако обаче изразът има стойност false,
програмата прекратява работата си със съобщение от макрос assert.
* Функцията n! (n факториел),
n! = 1.2.3.4...n. Рекурентна дефиниция на същата функция е:
0! = 1, n! = n(n-1)! Ако трябва да се пресметне например 4! по тази дефиниция, трябва да се направи следното: Записва се 4! = 4.3! 3! = 3.2! 2! = 2.1! 1! = 1.0! 0! = 1 и връщайки се обратно по записа, се пресмята 1! = 1.0! = 1.1 = 1 2! = 2.1! = 2.1 = 2 3! = 3.2! = 3.2 = 6 4! = 4.3! = 4.6 = 24. |
|
long factorial(int n)
{ if (n == 0) return 1;
else
{ long result = n * factorial(n
- 1);
return result;
}
}
int main()
{ cout << "Please enter a
number: ";
int n;
cin >> n;
cout << n <<
"! = " << factorial(n) << "\n";
return 0;
}
Please enter a number: 12
12! = 479001600 |
Процесът, при който една функция вика себе си, се
нарича рекурсия, а самата функция се нарича рекурсивна функция. Тя трябва
да изпълнява две условия:
1. Всяко рекурсивно извикване трябва да опростява
пресмятанията по някакъв начин. В случая функцията се извиква с по-малка
стойност на параметъра.
2. Трябва да има специална обработка на най-простите
случаи. В нашия пример това е случаят когато входният параметър n
е нула.