通过计算圆的面积熟悉函数的写法,我们知道圆的面积公式如下
或者f(r) = PI * r*r
则C++函数就能实现数学的函数计算功能,下面的计算圆的面积的函数:
#include <iostream> using namespace std; #define PI 3.14159265358979323846 double circle_area(double r) { return PI*r*r; } int main()
{double s = circle_area(10.0); cout << "area = " << s << "\n"; return 0; }
PI定义的小数点越多,计算的面积越准确
C++函数有多个参数,返回一个值,注意如果返回多个值,可以用引用,例如下面计算圆的面积对半径范围有要求,比如
如果半径大于1e6, 则返回false, 面积为-1, 说明半径太大了,否则返回true及计算的面积
则实现为
#include <iostream> using namespace std; #define PI 3.14159265358979323846 bool circle_area(double r, double& s) { if (r > 1e6 || r < 0.0) { s = -1.0; return false; } else { s = PI*r*r; return true; } } int main()
{double s = 0.0; bool res = circle_area(10000000.0, s); if (res == true) { cout << "area = " << s << "\n"; } else { cout << "r range should be [0.0, 1000000.0]" << "\n"; } return 0; }
很显然,这个版本的函数对输入参数有检查,实际的参数是有范围和特殊要求的,所以更程序化而不是只是数学公式的C语言描述
参数引用一般讲的是传地址,所以s在函数内被赋值,其实是函数外面的s在内存里被修改, 非引用则是拷贝,例如第一个参数,其实有个 把10000000.0这个常数参数赋值到函数参数
r的隐藏的过程,我们可以看到(脑补)这个过程:
内存上一个double类型的内存块拷贝到r这个double类型的内存块
所以如果参数是个很大的类,比如std::vector<double>, 这个vector的double又非常多,那这个拷贝过程就很耗时,所以要小心,改为传地址的引用或者指针来改善。
对于函数如果特别长,而且内部能有些部分计算是重复的,那就要把整个函数拆出子函数,俗称模块化的,数学公式上也是这样的,比如
有三种硬币,每种硬币的数量半径和高度已知,求这些硬币的体积总和
那我们先有个硬币参数的信息结构体
struct tipinfo
{
int type; ///<类型
double r; ///<半径
double h; ///<高度
};
计算硬币体积
double tip_vol(tipinfo& tip)
{
return circle_area(tip.r) * tip.h;
}
下面的map是类型表,作为全局表
std::map<int, tipinfo> tipTypeInfoMap;
下面的参数是每个类型的tip数量表
std::map<int, int> tipTypeNumbererMap;
计算体积和的函数为
double tips_volumn_sum()
{
double sum = 0.0;
for (std::map<int, int>::iterator i = tipTypeNumbererMap.begin(); i != tipTypeNumbererMap.end(); i++)
// c++11 的for可以简化为
// for(auto& i : tipTypeNumbererMap)
{
int n = tipTypeInfoMap[i->first];
double v = n * tip_vol(tipTypeInfoMap[[i->first]);
sum += v;
}
return sum;
}
写成一个double tips_volumn_sum函数肯定能编译过,但是调试及维护难度加大,什么意思,就是几个月后不要说别人你自己都看不懂了,所以虽然程序是一段文字
一个长的字符串,其实程序就像小说,是有构造的, 看的时候是动态的,浮想连篇的,好的代码和好的小说一样是有世界感的有故事的,啊这篇随笔,明说了,要睡觉了,
所以后面的代码就没在http://www.dooccn.com/中编译通过了,只是手打的。