你该逆袭了
文章目录
- 一、复习函数
- 1、定义带形式参数的函数
- 2、声明带形式参数函数的原型
- 3、使用 return 从函数中返回值
- (1)、返回值不仅可以赋给变量,也可以被用作表达式的一部分。
- (2)、返回值不一定是变量的值,也可以是任意表达式的值。
- (3)、如果函数返回值的类型与函数声明的类型不匹配怎样?
- (4)、return 用来终止函数并把控制返回给主调函数的下一条语句。
- return; 的作用
- 4、函数类型
- (1)函数声明既可以在主调函数外面,也可以放在主调函数里面。
- 二、ANSI C 函数原型
- 1、无参数和未指定参数
- 2、函数原型的优点
- 三、递归
- 1、演示递归
- 2、递归的基本原理
- 3、尾递归
- 4、递归和倒序计算
- 5、递归的优缺点
- 四、编译多源代码文件的程序
- 1、使用头文件
- (1)示例程序的注意点
- (2)示例程序
- (3)示例程序的运行结果截图
- 五、查找地址:&运算符
一、复习函数
1、定义带形式参数的函数
void dibs(x, y, z)
char x, y, z;
void dibss(x, y) //这里,圆括号中只有参数列表,而参数的类型在后面声明。
int x;
char y;
//这是 ANSI C 之前的形式,现在已经将其废弃不用
2、声明带形式参数函数的原型
3、使用 return 从函数中返回值
#include <stdio.h>
int imin(int, int);
int main()
{
int num1 = 0;
int num2 = 0;
printf("enter a pair of integers (q to quit):\n");
while (scanf("%d %d", &num1, &num2) == 2)
{
printf("the lesser of %d and %d is %d.\n",
num1, num2, imin(num1, num2));
printf("enter a pair of integers (q to quit):\n");
}
printf("bye\n");
return 0;
}
int imin(int n, int m)
{
int min = 0;
if (n < m)
min = n;
else
min = m;
return min;
}
(1)、返回值不仅可以赋给变量,也可以被用作表达式的一部分。
answer = 2 * imin(z, zstar) + 25;
printf("%d\n", imin(-32 + answer, LIMIT));
(2)、返回值不一定是变量的值,也可以是任意表达式的值。
imin(int n, int m)
{
return (n < m) ? n : m;
}
(3)、如果函数返回值的类型与函数声明的类型不匹配怎样?
(4)、return 用来终止函数并把控制返回给主调函数的下一条语句。
return; 的作用
4、函数类型
声明函数时必须声明函数的类型。带返回值的函数类型应该与其返回值类型相同,而没有返回值的函数应声明为 void。
(1)函数声明既可以在主调函数外面,也可以放在主调函数里面。
二、ANSI C 函数原型
1、无参数和未指定参数
2、函数原型的优点
三、递归
结束递归 是使用递归的难点,因为如果递归代码中没有终止递归的条件测试部分,一个调用自己的函数会无限递归。
1、演示递归
如果函数使用%p转换说明打印地址,如果你的系统不支持这种格式,请使用 %u 或者 %lu 代替 %p。
#include <stdio.h>
void digui(int n);
int main()
{
digui(1);
return 0;
}
void digui(int m)
{
printf("%d 的地址是 %p\n", m, &m); // #1
if (m < 4) //使递归停止的条件
{
digui(m + 1);
}
printf("%d 的地址是 %p\n", m, &m); // #2
return 0;
}
2、递归的基本原理
(1)每级函数调用都有自己的变量。
(2)每次函数调用都会返回一次。当函数执行完毕后,控制权将被传回上一级递归。且程序必须按顺序逐级返回递归。
(3)递归函数中位于 递归调用之前 的语句,均按被调函数的顺序执行。
(4)递归函数中位于 递归调用之后 的语句,均按被调函数相反的顺序执行。
(5)虽然每级递归都有自己的变量,但是并没有拷贝函数的代码。
(6)递归函数必须包含能让递归调用停止的语句。
3、尾递归
最简单的递归形式是把递归调用置于函数的末尾,即正好在 return 语句之前。这种形式的递归被称为 尾递归,因为递归调用在函数的末尾。
分别用 循环 和 递归 计算阶乘:
#include <stdio.h>
long recur(int x); //阶乘
long xunhuan(int x); //循环
int main()
{
int input = 0;
printf("请输入 12 以内的正整数(q to exit)\n");
while ((scanf("%d", &input) == 1))
{
if (input > 12)
{
printf("请输入12以内的整数,你输入的数据太大。\n");
}
else if (input < 0)
{
printf("你输入的数据是负数,请重新输入数据。\n");
}
else
{
printf("递归:%d 的阶乘是 %d\n", input, recur(input));
printf("循环:%d 的阶乘是 %d\n", input, xunhuan(input));
}
}
printf("bye\n");
return 0;
}
long recur(int x)
{
long sum = 0;
if (x > 0)
{
sum = x * recur(x - 1);
}
else
sum = 1; // 0 的阶乘 是 1
// 0!= 1
return sum;
}
long xunhuan(int x)
{
long sum = 1;
for (sum = 1; x >= 1; x--)
{
sum *= x;
}
return sum;
}
代码的关键点:
虽然递归调用不是函数的最后一行,但是当 x > 0 时,它是该函数执行的最后一条语句,因此它也是 尾递归。
long recur(int x)
{
long sum = 0;
if (x > 0)
{
sum = x * recur(x - 1);
}
else
sum = 1; // 0 的阶乘 是 1
// 0!= 1
return sum;
}
4、递归和倒序计算
用二进制形式打印整数
#include <stdio.h>
void binary(int n);
int main()
{
int input = 0;
printf("请输入一个整数:\n");
while (scanf("%d", &input) == 1)
{
printf("以二进制的形式输出:");
binary(input);
putchar('\n');
printf("请继续输入整数,q to exit\n");
}
printf("bye\n");
return 0;
}
void binary(int n)
{
int r = 0;
r = n % 2;
if (n >= 2)
{
binary(n / 2);
}
putchar(r == 0 ? '0' : '1'); //此处注意,输出 字符‘1’ 和 字符‘0’
return; //什么也不返回
}
注意点:
putchar(r == 0 ? '0' : '1');
//此处注意,输出 字符‘1’ 和 字符‘0’
return; //什么也不返回
5、递归的优缺点
优点:
递归为编程问题提供了最简单的解决方案。
缺点:
一些递归算法会快速消耗计算机的内存资源。
(举例:Fibonacci函数)
#include <stdio.h>
int fibonacci(int);
int main()
{
int input = 0;
printf("请输入整数:");
scanf("%d", &input);
fibonacci(input);
printf("%d\n", fibonacci(input));
return 0;
}
int fibonacci(int n)
{
if (n > 2)
return fibonacci(n - 1) + fibonacci(n - 2);
else
return 1;
}
四、编译多源代码文件的程序
1、使用头文件
(1)示例程序的注意点
以下程序注意点:
scanf("%*s");
处理非数值输入,跳至下一个空白字符。
(2)示例程序
usehotel.c ————房间费率程序
#include <stdio.h>
#include "hotel.h" //定义符号常量,声明函数
int main()
{
int nights;
double hotel_rate;
int code;
while ((code = menu()) != QUIT)
{
switch (code)
{
case 1: hotel_rate = HOTEL1;
break;
case 2: hotel_rate = HOTEL2;
break;
case 3: hotel_rate = HOTEL3;
break;
case 4: hotel_rate = HOTEL4;
break;
default:hotel_rate = 0.0;
printf("oops!\n");
break;
}
nights = getnights();
showprice(hotel_rate, nights);
}
printf("thank you and goodbye.\n");
return 0;
}
hotel.c ————酒店管理函数
#include <stdio.h>
#include "hotel.h"
int menu(void)
{
int code, status;
printf("\n%s%s\n", STARS, STARS);
printf("enter the number of the desired hotel:\n");
printf("1) Fairfield Arms 2) Hotel olympic\n");
printf("2) chertworthy plaza 4) the stockton\n");
printf("5) quit\n");
printf("%s%s\n", STARS, STARS);
while ((status = scanf("%d", &code)) != 1 ||
(code < 1 || code>5))
{
if (status != 1)
{
scanf("%*s"); //处理非整数输入
}
printf("enter an integer from 1 to 5,please.\n");
}
return code;
}
int getnights(void)
{
int nights;
printf("how many nights are needed? ");
while (scanf("%d", &nights) != 1)
{
scanf("%*s"); //处理非整数输入
printf("please enter an integer ,such as 2.\n");
}
return nights;
}
void showprice(double rate, int nights)
{
int n;
double total = 0.0;
double factor = 1.0;
for (n = 1; n < nights; n++, factor *= DISCOUNT)
total += rate * factor;
printf("the total cost will be $%0.0f.\n", total);
}
hotel.h ————符号常量 和 hotel.c 中所有函数的原型
//符号常量 和 hotel.c 中所有函数的原型
#define QUIT 5
#define HOTEL1 180.00
#define HOTEL2 225.00
#define HOTEL3 255.00
#define HOTEL4 355.00
#define DISCOUNT 0.95
#define STARS "***********************************"
//显示选择列表
int menu(void);
//返回预定天数
int getnights(void);
//根据费率,入住天数计算费用
//并显示结果
void showprice(double rate, int nights);
(3)示例程序的运行结果截图
五、查找地址:&运算符
主调函数不使用 return 返回的值,则必须通过地址才能修改主调函数中的值。
#include <stdio.h>
int main()
{
int a = 0;
int b = 9;
printf("a=%d &a=%p\n", a, &a);
printf("a=%d &a=%p\n", b, &b);
acc(a);
return 0;
}
int acc(int a)
{
int b = 10;
printf("a=%d &a=%p\n", a, &a);
printf("a=%d &a=%p\n", b, &b);
}
总结:
从所得地址可以看出,这是 4 个不同的独立变量。
仅仅只是实现了值传递。
其余是指针的概念,在我的“C语言小知识点”专栏中,有详细总结。