自定义函数是写大程序的前提
最开始写程序的时候,我们都会全部一股脑地写在main函数中,导致有的main函数有成千上万行,要调试起来,这就尴尬了。
这就引出了我们需要定义一些自定义函数,只需要将这些函数写在主函数就可以了。
是个什么意思呢,就是你秀给客户或者测试人员的main函数,是这个样子的(看一下百万量级规模的内核启动函数):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| int main(void) { printf("Linux/AXP bootloader for Linux \n");
pal_init();
openboot();
printf("Loading vmlinux ..."); load(dev, START_ADDR, KERNEL_SIZE); close(dev);
callback_getenv(ENV_BOOTED_OSFLAGS, envval, sizeof(envval));
runkernel();
}
|
虽然有些东西看不懂什么意思(因为我精简和修改了部分代码),没有问题,我们需要理解的就是Linux内核有百万行量级,而它的主函数也就短短的十几行,其他的就放在了自定义函数里实现,也就上面的openboot,runkernel等。
OK,任务来了,我想让你写个程序,计算出摄氏度和华氏度的转换,
两个的转换关系如下:
- 华氏度 = 32°F+ 摄氏度 × 1.8
- 摄氏度 = (华氏度 - 32°F) ÷ 1.8
这个简单呀,前面就写过(刷刷刷,码出如下代码):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| # include <stdio.h>
int main() { float f; float c;
f = 80.0; c = 27.0;
float ff; float cc;
printf ("Fahrenheit <=> Celsius\n"); ff = 32 + c * 1.8; cc = (f - 32) / 1.8;
printf("%f <=> %f\n",f, cc); printf("%f <=> %f\n",ff, c);
return 0; }
|
不错,孺子可教也,在加深一步,又来了一组数据,也是求两者的转换关系,代码继续累加,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| # include <stdio.h>
int main() { float f; float f1; float c; float c1;
f = 80.0; f1 = 90.0; c = 27.0; c1 = 36.0;
float ff; float ff1; float cc; float cc1;
printf ("Fahrenheit <=> Celsius\n"); ff = 32 + c * 1.8; cc = (f - 32) / 1.8;
printf("%f <=> %f\n",f, cc); printf("%f <=> %f\n",ff, c);
ff1 = 32 + c1 * 1.8; cc1 = (f1 - 32) / 1.8;
printf("%f <=> %f\n",f1, cc1); printf("%f <=> %f\n",ff1, c1);
return 0; }
|
如果我在来一组数据,是不是同样还需要在原来的代码基础上累加,我们就会发现:main函数越来越庞大,但是有效的代码就那么几行,其余的工作都是在重复叠加,这就引出一个问题,我们的华氏转摄氏度是比较简单的公示,如果算个麦克斯韦方程:
$\oiint_{\partial V}\mathrm{E}\cdot d \mathrm{a} = \frac{Q_V}{\epsilon_0}\ \oiint_{\partial S}\mathrm{E}\cdot d \mathrm{l} = \frac{d}{dt} \int_S \mathrm{B} \cdot d\mathrm{a}\ \oiint_{\partial V}\mathrm{B}\cdot d \mathrm{a} = 0 \ \oiint_{\partial S}\mathrm{B}\cdot d \mathrm{l} = \mu_0\epsilon_0\frac{d}{dt} \int_S \mathrm{E} \cdot d\mathrm{a} $$
其中$\oiint$为环路积分的符号
那么每一次计算都要重复这些操作,有没有一种方法可以简化呢,妥妥滴,这就带来了自定义函数。
我们以华氏度和摄氏度的转换为例,可以定义两个函数:
1 2
| float c2f(float c); float f2c(float f);
|
两个函数的含义为c2f就是将摄氏度c转换为华氏度返回,相反f2c为将华氏度f转换为摄氏度返回。
具体的代码如下:
1 2 3 4 5 6 7 8 9
| float c2f(float c) { return 32 + c * 1.8; }
float f2c(float f) { return (f - 32) / 1.8; }
|
我们把这两个代码片段加到程序中,最后的效果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| # include <stdio.h>
float c2f(float c); float f2c(float f);
int main() { float f; float f1; float c; float c1;
f = 80.0; f1 = 90.0; c = 27.0; c1 = 36.0;
float ff; float ff1; float cc; float cc1;
printf ("Fahrenheit <=> Celsius\n"); cc = f2c(f); ff = c2f(c);
printf("%f <=> %f\n",f, cc); printf("%f <=> %f\n",ff, c);
cc1 = f2c(f1); ff1 = c2f(c1);
printf("%f <=> %f\n",f1, cc1); printf("%f <=> %f\n",ff1, c1);
return 0; }
float c2f(float c) { return 32 + c * 1.8; } float f2c(float f) { return (f - 32) / 1.8; }
|
这个程序新加的东西有点多,不过可以清晰的看到,主函数通过使用自定义的函数已经将重复的东西结构化了,这是编写大程序的基础,希望你能掌握。
编译运行
直接输入make
就可以了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| ALL : function1 function2 function3
function1: function1.c gcc -o function1 function1.c
function2: function2.c gcc -o function2 function2.c
function3: function3.c gcc -o function3 function3.c
.PHONY : clean
clean: rm -f function1 function2 function3
|
运行输出如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| $ ./function1 Fahrenheit <=> Celsius 80.000000 <=> 26.666666 80.599998 <=> 27.000000
$ ./function2 Fahrenheit <=> Celsius 80.000000 <=> 26.666666 80.599998 <=> 27.000000 90.000000 <=> 32.222221 96.800003 <=> 36.000000
$ ./function3 Fahrenheit <=> Celsius 80.000000 <=> 26.666666 80.599998 <=> 27.000000 90.000000 <=> 32.222221 96.800003 <=> 36.000000
|