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.
* Затова параметрите-псевдоними се наричат входно-изходни
параметри - те "пренасят" данни от извикващата функция (main)
към извиканата функция (raise_salary) и обратно.
*
Използват се за да се избегне копирането - особено нежелателно,
ако параметърът е обект, съдържащ много данни.
* Тъй като стойността на константния псевдоним не може да се
променя, той не "пренася" данни от извиканата функция (print_employee)
в извикващата функция (main).
Пример: Функция ца
отпечатване на данните на обект от тип Employee
void print_employee(const
Employee & e)
{
cout <<
"Name: " << e.get_name()
<< "Salary: " << e.get_salary();
}
int main()
{
Employee harry("Hacker, Harry", 45000.00);
print_employee(harry);
return 0;
}
Параметри-променливи | Параметри-псевдоними | Константни псевдоними |
Входни параметри за функцията | Входно-изходни параметри за функцията | - |
Предаване на параметри чрез копиране | Предаване на параметри по адрес (не се копира) |
Предаване на параметри по адрес (не се копира) |
Стойността на параметъра може да се променя (фактическия
параметър не се променя) |
Стойността на параметъра може да се променя (фактическия
параметър се променя) |
Стойността на параметъра не може да се променя |
Фактически параметър може да бъде константа, променлива
или израз (rvalue) |
Фактически параметър може да бъде само променлива (lvalue) |
Фактически параметър може да бъде константа, променлива
или израз (rvalue) |
** Област на действие на
променливите (scope), глобални променливи
* Ако едно и също име на променлива се използва в
две функции, то не съществува връзка между двете
променливи.
* Областта на действие на променлива, която е дефинирана в блока
на функция, се простира единствено в рамките на тази
функция.
Пример: Сложна лихва - променливи с едно и също име в две
функциии.
// 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.
* Променлива, дефинирана в блок на функция, се нарича локална променлива.
* Областта на действие на локална променлива е от мястото на
дефинирането до края на блока, в който е дефинирана
променливата (block scope).
* В тази област променливата е видима, т.е. може да бъде
използвана.
* Променлива, дефинирана извън
блок на функция, се нарича глобална
променлива.
* Областта на действие на глобална променлива е от мястото на
дефинирането до края на файла, в който е дефинирана
променливата (file scope).
* Досега са използвани глобалните променливи (обекти) cin и cout, които са дефинирани в
заглавния файл iostream.h.
Пример: Увеличаване на заплата с глобална променлина.
// 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 |
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 с директива на
препроцесора.
Пример: Сложна лихва - макрос assert.
// futval0.cpp
#include <iostream>
#include <cmath>
#include <cassert>
using namespace std;
nkirov@cpp % c++ futval0.cpp nkirov@cpp % ./a.out Please enter the interest rate in percent: 10 After 10 years, the balance is 2593.74 nkirov@cpp % ./a.out Please enter the interest rate in percent: -10 Assertion failed: (p > 0), function future_value, file futval0.cpp, line 9. zsh: abort ./a.out |
Ако
условието в assert е изпълнено, нищо не се случва. Ако обаче
изразът има стойност false,
програмата прекратява работата си със съобщение от макрос assert.