10.0 导入例子
程序中可能有多处需要计算连续个整数的和,比如1到10,5到20,6到18,
#include <stdio.h>
int main(){
int i, sum;
for(i = 1, sum = 0; i <= 10; i++){
sum += i;
}
printf("1到10的连续整数的和是%d\n", sum);
for(i = 5, sum = 0; i <= 10; i++){
sum += i;
}
printf("5到10的连续整数的和是%d\n", sum);
for(i = 1, sum = 0; i <= 100; i++){
sum += i;
}
printf("1到100的连续整数的和是%d\n", sum);
getchar();
return 0;
}
可以感觉到,程序中出现了重复的计算流程,有什么办法可以避免这种重复呢?通过函数。可以为计算从一个整数到另一个整数所有连续数的和定义函数sum_all,需要实际计算的话调用该函数即可,调用时输入两个数,并处理函数的输出值,即计算结果。
#include <stdio.h>
int sum_all(int a, int b){
int i, sum;
for(i = a, sum = 0; i <= b; i++){
sum += i;
}
return sum;
}
int main(){
int sum;
sum = sum_all(1, 10);
printf("1到10的连续整数的和是%d\n", sum);
sum = sum_all(5, 10);
printf("5到10的连续整数的和是%d\n", sum);
sum = sum_all(1, 100);
printf("1到100的连续整数的和是%d\n", sum);
// 需要计算1到4的和只要调用sum_all即可
sum = sum_all(1, 4);
printf("1到4的连续整数的和是%d\n", sum);
getchar();
return 0;
}
10.1 函数基础
- 函数是一块代码,接收零个或者多个参数,(最好)做一件事情,并返回零个或者一个值。
- 函数的定义:编写代码告诉编译器函数怎么用和怎么实现它的功能。程序中某个函数只需要定义一次,也只能定义一次。
- 函数的调用:编写代码使用这个函数。同一个函数可以被多次调用。
- 函数的声明:告诉编译器这个函数长什么样子。如果函数的定义放在了函数调用之后,那么函数调用之前要声明函数。
10.1.1 函数的定义、调用
-
函数的定义
函数定义的一般形式:
返回值类型 函数名(参数列表,各参数用逗号隔开){
函数中的代码;
}比如,找两个数最大值的函数max可以定义成,
// 函数的定义 int max(int num1, int num2){ int result; if (num1 > num2){ result = num1; }else{ result = num2; } return result; }
允许定义的函数没有返回值,没有参数列表,在后续小节会有介绍。
-
函数的调用
调用函数的一般形式:
函数名(传给参数列表中各参数的值,用逗号隔开);
如果函数有返回值,那么可以把函数调用语句当成一个表达式,函数的返回值就相当于表达式的值。可以把它赋值给变量或者直接输出。比如,
变量名 = 函数名(传给参数列表中各参数的值);
找两个数最大值的函数max可以像如下代码那样被调用,
int main(){ int x, y, r1; scanf("%d%d", &x, &y); r1 = max(x, y); // 函数调用,调用结束,函数的返回值会赋值给r1 printf("%d和%d之间的最大值是%d\n",x, y, r1); return 0; }
可以把找两个数最大值的代码封装到函数中,这样需要找两个数最大值的时候调用这个函数即可。
// 函数定义
int max(int num1, int num2){
int result;
if (num1 > num2){
result = num1;
}else{
result = num2;
}
return result;
}
int main(){
int x, y, r1;
scanf("%d%d", &x, &y);
r1 = max(x, y); // 函数调用
printf("%d和%d之间的最大值是%d\n",x, y, r1);
return 0;
}
函数定义分为函数头和函数体两部分,函数头指明了函数的返回值类型,函数名和函数的各个参数。函数头表达的内容也称为函数原型,告诉编译器怎样使用函数,相当于该函数与其它函数的交互界面。函数体包含了函数实现其功能的代码。函数被调用时,执行流程会转到函数中运行,首先,实际参数的值会赋值给函数的参数列表中的各个参数变量(随着函数的调用,参数变量会被创建出来),接着函数体中的代码会运行,直到遇到函数中的return语句,它将结束函数的运行,并且(可以)返回一个值到调用这个函数的函数中,执行流程继续从这里向下运行。
如果用VS2010跟踪程序运行流程,可以看到,程序的运行流程是:从main函数中的代码开始执行,执行到max函数调用语句后,转到max函数中执行,直到遇到return语句,返回到main函数中调用max函数的语句,main函数继续执行。如果在调试过程中注意值的变化,调用max函数时,x和y的值会赋给max函数参数num1和num2,函数调用结束,return语句返回的值会赋给r1。
main函数是被操作系统调用的,控制台下中用命令行运行程序过后,可以查看main函数的返回值。所以main函数本身也就是一个函数,只是它是程序运行的第一个函数,即程序的入口函数,它也是程序的出口函数,即main函数运行完毕,整个程序就运行完毕。
函数调用时传给它的是一些值,这些值可以来自常量、变量或者其它表达式,函数运行结束返回一个值。
r1 = max(5 , 10);
printf("%d\n", r1);
r1 = max(5 * x, 10 + y);
printf("%d\n", r1);
r1 = max(x, y) + 20;
printf("%d\n", r1);
r1 = 5 * max(5 * x, 10 + y) + 20;
printf("%d\n", r1);
printf("%d\n", 5 * max(5 * x, 10 + y) + 20);
函数头中返回值类型、参数类型有它们的作用:
int max(int num1, int num2){
int result;
if (num1 > num2){
result = num1;
}else{
result = num2;
}
return result;
}
int main(){
double x, y, r1;
scanf("%lf%lf", &x, &y);
r1 = max(x, y); // 函数调用
printf("%lf和%lf之间的最大值是%lf\n",x, y, r1);
return 0;
}
有这样的结果是因为max函数的参数类型和返回类型均是整型,所有参数变量只能接收到整数并且返回整数。函数调用过程中经历了隐式类型转换,将double类型的实际参数赋值给了int类型的形式参数,以及int类型返回值转换为double类型的值赋给了r1。可见,要找double类型的最大值,需要max函数的参数和返回类型均是double类型。
double max(double num1, double num2){
double result;
if (num1 > num2){
result = num1;
}else{
result = num2;
}
return result;
}
int main(){
double x, y, r1;
scanf("%lf%lf", &x, &y);
r1 = max(x, y); // 函数调用
printf("%lf和%lf之间的最大值是%lf\n",x, y, r1);
return 0;
}
10.1.2 定义和调用没有返回值的函数或者没有输入的函数
可以根据需要定义没有输入、或者没有返回值的函数。
- 有输入,没有返回值的函数,比如
// 函数定义 void print_int(int i){ printf("%d", i); } int main(){ print_int(10); // 函数调用 return 0; }
- 没有输入,有返回值的函数,比如,
int getint(void){ int x; scanf("%d", &x); return x; } int main(){ int x; x = getint(); printf("input int is %d\n", x); return 0; }
- 没有输入,没有返回值的函数
void print_fun(void){ printf("hello, world\n"); } int main(){ print_fun(); return 0; }
可以根据需要定义没有返回值函数,比如,像库函数srand就是这样的函数(srand函数)。再比如,下面的自定义函数的功能就是把输入的整数值输出出来,
void print_int(int i){
printf("%d", i);
}
int main(){
print_int(10);
return 0;
}
因为该函数要做的事情在函数体中就已经做完,没有需要返回什么值,所以这样的函数不需要返回值,定义函数时在返回类型那样用写上void标明。
注意,定义没有返回值函数时,返回值类型那里不能不写void,否则,在C89中编译器会假定返回类型为int,在C99中这是不合法的。
函数还可以没有输入,比如库函数rand(rand函数),比如像getchar函数那样,可以写一个函数来读取并返回用户输入的整数,
int getint(void){
int x;
scanf("%d", &x);
return x;
}
使用它的例子,
int getint(void){
int x;
scanf("%d", &x);
return x;
}
int main(){
int x;
x = getint();
printf("input int is %d\n", x);
getchar();
getcha