C 语言 - 循环嵌套、函数
1. 循环嵌套
1.1 作用
循环 套 循环。
1.2 使用
需求1:
打印以下图形:
* * * * * * * * * * * * * * * *
代码:
1、使用循环打印
#include <stdio.h> int main(int argc, char const *argv[]) { for (int i = 0; i < 4; i++) { printf("* * * *\n"); } return 0; }
2、循环嵌套打印
#include <stdio.h> int main(int argc, char const *argv[]) { for (int i = 0; i < 4; i++) //外层控制行数 { for (int j = 0; j < 4; j++) //内层控制每一行的样式 { printf("* "); } printf("\n"); } return 0; }
#include <stdio.h> int main(int argc, char const *argv[]) { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (j <= i) { printf("* "); } } printf("\n"); } return 0; }
小结:
i 0 * 1 * * 2 * * * 3 * * * * 0 1 2 3 j
外层
控制行数
内层
控制每一行的样式
需求2:
打印以下图形
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
代码:
#include <stdio.h> int main(int argc, char const *argv[]) { for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if (j <= i) { printf("* "); } } printf("\n"); } return 0; }
优化:
#include <stdio.h> int main(int argc, char const *argv[]) { for (int i = 0; i < 9; i++) { for (int j = 0; j <= i; j++) { printf("* "); } printf("\n"); } return 0; }
需求3:
打印9*9乘法表
#include <stdio.h> int main(int argc, char const *argv[]) { for (int i = 1; i < 10; i++) { for (int j = 1; j <= i; j++) { // 1 * 1 = 1 printf("%d * %d = %d\t", i, j, i*j); } printf("\n"); } return 0; }
结果如下:
1.3 案例
例1:
百文百鸡
- 中国古代,有一个人去市场买鸡
- 公鸡3文钱一只
- 母鸡2文钱一只
- 小鸡1文钱三只
- 这个人有100文钱,要求买100只鸡
- 请问他可以有多少中买法,每种每种买法可以可以公鸡多少只,母鸡多少只,小鸡多少只
数学思路 假设: 公鸡x只 母鸡y只 小鸡100-x-y只 3 * x + 2 * y + (100 -x -y) / 3 = 100; x + y + (100 - x - y) = 100; 代码思路: 公鸡取值范围:0~33 母鸡取值范围:0~50 小鸡取值范围:0~100 遍历
代码:
#include <stdio.h> int main(int argc, char const *argv[]) { int num = 0; for (int g = 0; g < 34; g++) { for (int m = 0; m < 51; m++) { int x = 100 - g - m; if (3 * g + 2 * m + x / 3 == 100 && x % 3 == 0) { printf("公鸡:%d只,母鸡:%d只,小鸡:%d只\n", g, m, x); num++; } } } printf("共有%d种买法\n", num); return 0; }
输出结果:
公鸡:0只,母鸡:40只,小鸡:60只 公鸡:5只,母鸡:32只,小鸡:63只 公鸡:10只,母鸡:24只,小鸡:66只 公鸡:15只,母鸡:16只,小鸡:69只 公鸡:20只,母鸡:8只,小鸡:72只 公鸡:25只,母鸡:0只,小鸡:75只 共有6种买法
例2:
鸡兔同笼
养殖户将鸡与兔子放在同一个笼中
该养殖户无法数清鸡的数量与兔的数量
但是该养殖户数出了腿的数量与头的数量
腿60
头20请您帮助养殖户计算鸡兔个几何
数学思想: 设:兔子有t只,鸡有j只 4 * t + 2 * j = 60; t + j = 20; t = 20 - j; 4 * (20 -j ) + 2j = 60; 80 -4j + 2j = 60; 80 - 2j = 60; 80 - 60 = 2j; 20 = 2j; j = 10; t = 10; 代码思想: 鸡的取值范围:0~20 兔的取值范围:0~15
代码:
#include <stdio.h> int main(int argc, char const *argv[]) { int tag = 0; for(int j = 0; j <= 20; j++) { for(int t = 0; t <= 15; t++) { if(j + t == 20 && 4 * t + 2 * j == 60) { tag = 1; printf("鸡有:%d只,兔有:%d只\n",j,t); } } } if(tag) { printf("输入的头与腿数量正确\n"); } else { printf("此题无解,头腿数量有误\n"); } return 0; } // 输出:鸡有:10只,兔有:10只
2. 函数
2.1 作用
封装一段代码,使其便于使用。
注意:
- 一个功能可以封装一个函数
- 定义函数的时候一切
以功能为目的
,根据功能
去定义函数的参数
和返回值
。
2.2 分类
1、库函数 (c 库实现的)
- 不能直接操作内核
2、系统调用 (操作系统实现的函数)
- 可以直接操作内核
3、自定义函数 (程序员自己实现的函数)
- 定义
- 调用
2.3 使用步骤
① 声明(可有可无)
语法:
extern 返回值类型 函数名(形参列表);
注意:
- 在函数外声明
- 声明函数时可以忽略形参的变量名不写
② 定义
语法:
返回值类型 函数名(形参列表)
{
函数体
}
解释:
返回值类型
:返回值的数据类型,当函数没有返回值
,返回值类型为void(空类型)
函数名
:标识符,自定义的
形参列表
:根据实际情况,可有可无,多个参数之间使用逗号隔开,每个参数有数据类型变量名编写
函数体
:封装的代码return:结束当前函数
return xxx:结束当前函数并返回xxx,xxx就是返回值
注意:
一个函数
最多只能有一个返回值
同一个源文件
中函数名不能重复
(c语言不支持重载)- 函数不能定义在函数中
例1:定义函数计算10+1的结果
voild add01()
{
int x = 10 + 1;
printf("x=%d\n",x);
}
例2:定义一个函数计算两数之和
void add02(int x,int y)
{
int sum = x + y;
printf("sum=%d\n",sum);
}
例3:定义一个函数计算 1 + 2的结果,并将结果返回给调用处
int add03()
{
int x = 1 + 2;
return x;
}
例4:定义一个函数判断是否成年,成年返回1,未成年返回0
int iscN(int age)
{
if(age >= 18)
{
return 1;
}
else
{
return 0;
}
}
③ 调用
语法:
- 调用
无返回值
的函数
- 函数名(实参列表);
- 调用
有返回值
的函数
- 函数名(实参列表);
- 变量名 = 函数名(实参列表);
注意:
实参列表
要与形参列表
一致 (长度一致,顺序一致,数据类型一致)- 一个函数可以被调用无数次
- 只能在函数中调用
例:
add01();
add02(1,2);
add02(5,10);
int a = 1;
int b = 9;
add02(a,b);
add03();
int x = add03();
iscN(19);
int y = iscN(20);
int age = 17;
int z = iscN(age);
2.4 特殊情况
① 多重调用
在函数A中调用函数B,在B中调用c,c中调用....
例:
#include <stdio.h>
extern void funA();
extern void funB();
extern void func();
void funA()
{
printf("A开始\n");
funB();
printf("A结束\n");
}
void funB()
{
printf("B开始\n");
func();
printf("B结束\n");
}
void func()
{
printf("c开始\n");
printf("c结束\n");
}
int main(int argc, char const *argv[])
{
funA();
return 0;
}
② 递归
在函数中调用该函数,会形成循环
例:
#include <stdio.h>
void test(int num)
{
printf("num=%d\n",num);
if (num >= 0)
{
num--;
test(num);
}
}
int main(int argc, char const *argv[])
{
test(2);
return 0;
}
③ 多文件编译,跨文件调用函数
-
文件1:05_codeA.c
#include <stdio.h> extern void test05(); extern int num; int main(int argc, char const *argv[]) { test05(); printf("05_codeB\tnum=%d\n",num); return 0; }
-
文件2:05_codeB.c
#include <stdio.h> int num = 20; void test05() { printf("测试\n"); }
-
编译:
gcc 05_codeA.c 05_codeB.c
-
结果:
3. 变量的存储类别
-
程序是一个文件,
-
一个正在进行的程序称为一个进程
-
一个进程系统会为其分配一片运行内存
-
在32位系统下,每个进程的寻址范围是4G
3.1 数据存储分类
1)、堆
在动态申请内存的时候,在堆里开辟内存。
2)、栈
主要存放局部变量。
3)、静态全局区
未初始化的静态全局区
- 静态变量(定义变量的时候,前面加 static 修饰),或全局变量 ,没有初始化的,存在此区
初始化的静态全局区
- 全局变量、静态变量,赋过初值的,存放在此区
4)、代码区
存放咱们的程序代码
5)、文字常量区
存放常量的
3.2 函数相关
① 普通成员函数(全局函数)
语法:
返回值类型 函数名(形参列表)
{
函数体
}
特点:
可以在当前
.c 文件
(源文件)中使用,也可以在其他.c文件
中使用
② 静态成员函数(静态全局函数)
语法:
static 返回值类型 函数名(形参列表)
{
函数体
}
特点:
只能在当前
.c文件
(源文件)中使用
3.3 变量相关
① 局部变量
定义位置:当前函数中
作用域:所
声明的代码块中
生命周期:调用所在函数时生成,随着所在
代码块的执行完毕
而销毁默认值:随机数
② 成员变量(全局变量)
定义位置:在函数外
作用域:当前程序中
生命周期:随着所在进程的执行而生成,随着
所在进程的结束
而结束默认值:0
③ 静态局部变量
定义位置:当前函数中
作用域:所声明的代码块中
生命周期:第一次调用所在函数时生成,随着
所在进程的执行完毕
而销毁,只会定义一次默认值:0
例:
#include <stdio.h>
void test()
{
static int x = 10;
x++;
printf("x=%d\n",x);
}
int main(int argc, char const *argv[])
{
test();
test();
test();
return 0;
}
输出结果:
x=11
x=12
x=13
④ 静态成员变量(静态全局变量)
定义位置:在函数外
作用域:当前源文件中
生命周期:随着所在进程的执行而生成,随着
所在进程的结束
而结束默认值:0
4. const
const 修饰的变量值不能被修改