递归的作业讲解
假如有n个台阶,一次只能上1个台阶或2个台阶,请问走到第n个台阶有几种走法?为便于读者理解题意,这里举例说明如下:假如有3个台阶,那么总计就有3种走法:第一种为每次上1个台阶,上3次;第二种为先上2个台阶,再上1个台阶;第三种为先上1个台阶,再上2个台阶。输入为n,输出为走到第n个台阶有几种走法
思路:
1层台阶 1种走法 (1)
2层台阶 2种走法 (11 2)
3层台阶 3种走法 (111 12 21)
4层台阶 5种走法 (1111 22 112 211 121)
因为我们一次只可以走两层或者一层,所以就有一层和两层混合的走法
得出step(n)=step(n - 1)+step(n - 2)
#include<stdio.h>
//函数自己调用自己就是递归
int step(int n) {
if (1 == n) {
return 1;
}
if (2 == n) {
return 2;
}
return step(n - 1)+step(n - 2);//递归
}
int main() {
int n;
scanf("%d", &n);
int ret = step(n);
printf("%d\n",ret);
}
结构体与结构体指针
结构体的定义
C语言结构体(Struct)从本质上讲是一种自定义的数据类型,只不过这种数据类型比较复杂,是由 int、char、float 等基本类型组成的。你可以认为结构体是一种聚合类型。
在实际开发中,我们可以将一组类型不同的、但是用来描述同一件事物的变量放到结构体中。例如,在校学生有姓名、年龄、身高、成绩等属性,学了结构体后,我们就不需要再定义多个变量了,将它们都放到结构体中即可。
下面我们写一段程序,来让大家理解一下结构体。
#include<stdio.h>
struct student {
int num;
char name[20];
char sex;
int age;
float score;
char addr[30];
};//一定要加分号
int main() {
struct student s = { 1001,"XiaoMing",'M',18,99.5,"Guangzhou"};
printf("%d,%s,%c,%d,%5.2f,%s", s.num, s.name,s.sex,s.age,s.score,s.addr);
return 0;
}
需要注意的点:
1.结构体始定义在方法外的,定义结束时一定要加分号。
2.使用结构体的时候需要为给一个变量名,然后变量名.元素(注意:.是一个运算符)。访问结构体特定的元素。
输出结果如下:
那么问题来了?这个结构体所占的字节大小是多少
按照上面的图片算的化是占63个字节,有的人就会说:“都算出来了还看啥。”我只能说格局小了
接下来我们看看监视,显示的是68个字节
再看看内存,我们不难发现刚好是显色区域的数量17行一行4列 17*4=68。
那为什么会多出来的如下图的5个字节呢?
解答:
其实多出来的5个字节就是为了为了加快数据传输的效率
结构体这样是比较特殊的,因为我们的现在使用的是32位就是一次可以接收8个字节的数据。
结构体内的数据都是以8个字节为一组(如果64位的话就是16个字节为一组)传输的。所以像char这种占一个字节的,后面的cc cc cc也会传跟char组成4个字节一并传输。其目的就是为了加快传输效率
结构体数组
既然我们定义了一个结构体,如果这个结构体只能存储一条数组那不是很累赘吗?比如你班里有48人。有一张统计表,但是只有一个填写位置只能填一名同学的信息,那岂不是没意义
所以结构体数组就它就来了,具体的定义如下
输入
1001 XiaoMing M 18 99.5 Guangzhou
1002 XiaoLi F 20 95.5 BeiJing
1003 XiaoHong M 19 90.5 ShangHai
#include<stdio.h>
//
struct student {
int num;
char name[20];
char sex;
int age;
float score;
char addr[30];//一定要加分号
};
int main() {
struct student s = { 1001,"XiaoMing",'M',18,99.5,"Guangzhou"};
printf("%d,%s,%c,%d,%5.2f,%s\n", s.num, s.name, s.sex, s.age, s.score, s.addr);
//定义结构体数组
struct student sarry[3];
int i;
printf("输入:\n");
for (i = 0; i < 3; i++) {
scanf("%d %s %c %d %f %s", &sarry[i].num, &sarry[i].name, &sarry[i].sex, &sarry[i].age, &sarry[i].score, &sarry[i].addr);
}
printf("输出:\n");
for (i = 0; i < 3; i++) {
printf("%d %s %c %d %f %s\n", sarry[i].num, sarry[i].name, sarry[i].sex, sarry[i].age, sarry[i].score, sarry[i].addr);
}
return 0;
}
结构体指针
结构体指针的使用
结构体也有指针变量,下面就让我们写一段程序来了解一下
利用指针输出结构体元素的方式
有两种。
对象就是✳p
指针就是p
#include<stdio.h>
struct student {
int num;
char name[20];
char sex;
};//一定要加分号
int main() {
struct student s = { 1001,"XiaoMing",'M'};
//定义结构体指针
struct student* p;
p = &s;//指针指向s
printf("指针指向s的输出方式一:num=%d,name=%s,sex=%c\n", (*p).num, (*p).name, (*p).sex);
printf("\n指针指向s的输出方式二:num=%d,name=%s,sex=%c\n", p->num,p->name,p->sex);
return 0;
}
它们的输出结果都是一样的。
结构体指针的偏移
接下来我们看下面这个程序猜一下结果
#include<stdio.h>
struct student {
int num;
char name[20];
char sex;
};//一定要加分号
int main() {
//定义结构体数组
struct student sarry[3] = { 1001,"XiaoMing",'M',1005,"XiaoLi",'F',1006,"XiaoHong",'M'};//直接按照个数赋值即可
//定义结构体指针
struct student* p;
p = sarry;//指针指向s
int num;
num = p->num++;//拆分为num=p->num;p->num=(p->num)+1,因为->优先级比++高,所以要把p->num算上
printf("num=%d,p->num=%d\n", num,p->num);
num = p++->num;//拆分为num=p->num;p=p+1,因为++是右到左顺序运算的
printf("num=%d,p->num=%d\n", num, p->num);
return 0;
}
过程分析:
num = p->num++;
拆分为num=p->num;p->num=(p->num)+1,因为->优先级比++高,所以要把p->num算上
因此num=p->num就是1001
p->num=(p->num)+1就是1002
所以第一次输出的是1001 1002。
num = p+±>num;
拆分为num=p->num;p=p+1,因为++是右到左顺序运算的
因为上面的p->num被重新赋值成了1002所以num=p->num为1002
p=p+1指针向右偏移指向sarry[1].num值为1005
所以第二次的输出是1002 1005。
其实主要就是看++左边的运算符谁的运算符优先级高,比++高就带上优先级高的运算符一起。平级或者低就不用带上。