递归
函数的递归调用
函数自己调用自己(直接/间接)
#include <stdio.h>
// 这是函数自己调用自己
// 但是在这里 函数会一直调用 没有结束的条件
// ==> 需要有一个不再调用自己的条件
void func()
{
func();
}
// 求1---n的和
int function(int n)
{
// 1 结束递归的条件
if (n <= 0)
{
return n;
}
return n + function(n - 1);
}
int main()
{
printf("%d\n", function(10));
return 0;
}
结构体
一类数据类型: 他们的共同点是:程序员自己定义的类型 ==>自定义类型
它允许我们存储不同类型的数据项
定义
struct 标签
{
类型1 变量名1;
类型2 变量名2;
// ...
类型n 变量名n;
}结构体变量名1,结构体变量名2,....,结构体变量名n;
-
关键字: struct
-
标签: Tag
-
{}: 限定结构体的范围 注意 " ; " 结尾
-
{}里面: 定义变量
-
在" ; "之前{}之后,可以定义结构体变量
struct Tag
{
int num;
char ch;
float f;
bool is;
// ... ...
}T;
// 1 可以不定义结构体变量
struct Tag1
{
int num;
char ch;
float f;
bool is;
// ... ...
};
// 2 可以不定义标签
struct
{
int num;
char ch;
float f;
bool is;
// ... ...
}T;
struct A
{
int a;
};
struct AB
{
int b;
struct A a; // 定义结构体变量
};
#include <stdio.h>
typedef int I;
typedef struct A
{
int a;
}TypeName;
int main()
{
int num;
I n;
struct A st_a;
TypeName st_a1;
return 0;
}
初始化结构体变量
其他类型的变量 可以继续初始化 那么结构体变量也可以在定义的同时进行初始化
#include <stdio.h>
struct Hero
{
char name[32]; // 名字
int hp; // 血量
int mp; // 蓝条
float speed; // 移速
}hero1 = { "穿山甲", 100, 80, 12.5f };
typedef struct
{
int hp;
}Monster,Name;
int main()
{
struct Hero hero2 = { "华强", 120, 0, 7.5f };
Monster m1 = { 200 };
Name m2 = { 300 };
return 0;
}
核心: 使用{}
访问结构体变量的成员
使用成员访问运算符: " . "
printf("%s\n", hero2.name);
printf("%d\n", hero2.hp);
printf("%d\n", hero2.mp);
printf("%f\n", hero2.speed);
printf("\n%d\n", m1.hp);
结构体的内存
内存对齐
-
起始地址为该类型变量所占内存的整数倍,如果不足部分用数据填充到所占内存的整数倍
-
结构体所占总内存为该结构体的成员中基本数据类型占字节数最大的整数倍
#include <stdio.h>
/*
struct str1
{
char a; // 1
int b; // 4
float c; // 4
double d; // 8
char ch; // 1
};
// 32
*/
struct str1
{
char a; // 1
char ch; // 1
int b; // 4
float c; // 4
double d; // 8
};
// sizeof(): 24字节
int main()
{
struct str1 s1;
printf("%d\n", sizeof(s1));
return 0;
}
#include <stdio.h>
/*
struct str1
{
int b; // 4
double d; // 8
char arr[9]; // 9
};
*/
struct str1
{
double d; // 8
int b; // 4
char arr[9]; // 9
};
int main()
{
struct str1 s1;
printf("%d\n", sizeof(s1));
return 0;
}
#include <stdio.h>
struct A
{
char ch;
short sh;
int num;
};
struct B
{
int n;
struct A a;
};
int main()
{
struct B b;
printf("%d\n", sizeof(b));
return 0;
}
结构体和数组
结构体里面包含数组
#include <stdio.h>
#include <string.h>
struct Hero
{
char name[32]; // 名字
int hp; // 血量
int mp; // 蓝条
float speed; // 移速
};
void showHeroData(struct Hero hero)
{
printf("NAME: %s HP: %d MP: %d SPEED: %.2f\n",
hero.name, hero.hp, hero.mp, hero.speed);
}
int main()
{
struct Hero hero = { "华强", 120, 10, 7.5f };
hero.hp = 666;
// hero.name = "穿山甲"; // 这种写法不对
// 错误原因:
// hero.name中 name是数组名 是一个常量
// 正确方法:
strcpy(hero.name, "穿山甲");
showHeroData(hero);
return 0;
}
数组元素是结构体类型
#include <stdio.h>
#include <string.h>
struct Hero
{
char name[32]; // 名字
int hp; // 血量
int mp; // 蓝条
float speed; // 移速
};
void showHeroData(struct Hero hero)
{
printf("NAME: %s HP: %d MP: %d SPEED: %.2f\n",
hero.name, hero.hp, hero.mp, hero.speed);
}
int main()
{
int arr[5] = {1,2,3,4,5};
// 定义
struct Hero Red[5];
struct Hero hero = { "华强", 120, 10, 7.5f };
// 初始化
struct Hero Blue[5] = {
{ "Name0", 100, 50, 12.5f },
{ "Name1", 200, 60, 22.5f },
{ "Name2", 300, 70, 32.5f },
{ "Name3", 400, 80, 42.5f },
hero
};
printf("%s\n", Blue[4].name);
return 0;
}
结构体函数
结构体变量作为函数参数
#include <stdio.h>
struct Hero
{
char name[32]; // 名字
int hp; // 血量
int mp; // 蓝条
float speed; // 移速
}hero1 = { "华强", 100, 80, 12.5f };
typedef struct
{
int hp;
}Monster,Name;
/* 声明函数 */
void showHeroData(struct Hero hero);
int main()
{
struct Hero hero2 = { "穿山甲", 120, 0, 7.5f };
Monster m1 = { 200 };
Name m2 = { 300 };
showHeroData(hero2);
return 0;
}
/* 定义函数 */
void showHeroData(struct Hero hero)
{
printf("NAME: %s HP: %d MP: %d SPEED: %.2f\n",
hero.name, hero.hp, hero.mp, hero.speed);
}
函数的返回值是结构体变量
#include <stdio.h>
struct Hero
{
char name[32]; // 名字
int hp; // 血量
int mp; // 蓝条
float speed; // 移速
}hero1 = { "张三", 100, 80, 12.5f };
typedef struct
{
int hp;
}Monster,Name;
/* 声明函数 */
void showHeroData(struct Hero hero);
struct Hero getHero();
int main()
{
struct Hero hero2 = { "华强", 120, 0, 7.5f };
Monster m1 = { 200 };
Name m2 = { 300 };
showHeroData(hero2);
struct Hero hero = getHero();
showHeroData(hero);
return 0;
}
/* 定义函数 */
void showHeroData(struct Hero hero)
{
printf("NAME: %s HP: %d MP: %d SPEED: %.2f\n",
hero.name, hero.hp, hero.mp, hero.speed);
}
struct Hero getHero()
{
struct Hero hero = { "穿山甲", 150, 100, 27.5f };
return hero;
}
共用体(联合)union
联合是一种特殊的数据类型 能够在相同的内存位置存储不同的数据类型
语法
union 标签
{
// 成员
}变量;
举例
#include <stdio.h>
union Data
{
int num;
float f;
}data;
int main()
{
data.num = 10;
printf("data.num: %d\n", data.num); // 10
data.f = 3.14f;
printf("data.f : %f\n", data.f); // 3.140000
printf("data.num: %d\n", data.num); // 1078523331
return 0;
}
注意:
共用同一段内存
内存
-
大小必须足够容纳最宽的成员
-
大小能够被他所包含的所有的基本数据类型的大小整除
#include <stdio.h>
union U
{
char s[9];
int n;
double d;
};
union U1
{
char s[5];
int n;
double d;
};
int main()
{
printf("%d\n", sizeof(U));
printf("%d\n", sizeof(U1));
return 0;
}
枚举
枚举是C语言中的一种基本数据类型
定义
enum 枚举名
{
枚举元素1,
枚举元素2,
... ...
枚举元素n
};
例子
enum Day
{
MON,
TUE,
WEN,
THU,
FRI,
SAT,
SUN
};
注意:
-
第一个枚举成员的默认值是整型的0,后续的成员依次+1
-
当改变了某个枚举成员的值,后续成员在改变后的基础上依次+1
内存
全部都是4字节
#include <stdio.h>
enum MyEnum
{
AAA,
BBB
};
int main()
{
enum MyEnum my;
printf("%d\n", sizeof(my));
printf("%d\n", sizeof(AAA));
printf("%d\n", sizeof(MyEnum));
return 0;
}
福利部分:
猴子摘桃问题
#include <stdio.h>
/*
一只猴子摘了一些桃子,当场吃完了一半加一个.
第二天,将剩下的桃子,吃完了一半加一个.\
天天如此.
第10天,只有一个桃子了.
问:第一天摘了多少个桃子
1 使用递归
2 使用循环
*/
int Tao1(int n)
{
// 跳出条件
if (n == 10)
return 1;
if (n<1 || n >10)
return 0;
// 规律
return 2 * (Tao1(n + 1) + 1);
}
int Tao2(int n)
{
if (n<1 || n >10)
return 0;
int num = 1;
for (size_t i = 1; i <= (10 - n); i++)
{
num = (num + 1) * 2;
}
return num;
}
int main()
{
for (size_t i = 0; i < 12; i++)
{
printf("第%d天: %d\n", i,Tao1(i));
printf("第%d天: %d\n", i,Tao2(i));
printf("\n");
}
return 0;
}