嵌入式学习day4
一、循环结构
重复执行同一段代码,则选用循环结构
循环结构分类:
-
while
-
do…while
-
for
-
while 和 for: 当型循环,最少执行0次
-
do…while: 直到型循环,最少执行1次
1.1while 循环
当型循环,先判断,后执行,最少执行0次
格式1:
表达式1;
while(表达式2) //表达式2为真,则循环,表达式2为假,则不循环
{
循环体;
表达式3;
}
格式2:
while(表达式2)
{
循环体;
}
- 表达式1:表示初始值
- 表达式2:循环条件[可以是任意表达式,一般选用关系,算数,逻辑]
- 表达式3:步长
- while :循环函数,只能放在内部
- while()后面不允许加分号
- 当只有一条语句是,大括号可以省略
- 死循环 while(1) ,没有步长
例1> 计算1-100之间的和
int i = 1, sum = 0;
while (i <= 100)
{
sum += i;
i++;
}
printf("得到的和为%d\n", sum);
例2> 随机输入一个数,计算各个位数字之和
如: 1234567=1+2+3+4+5+6+7
int num, sum = 0, count = 0, t;
printf("请随机输入一个值:\t");
scanf("%d", &num);
t = num; // 使用t保存一下num的值
while (num != 0)
{
sum += num % 10; // 累加余数的和
count++;
num /= 10; // 步长
}
printf("%d各个位数字之和是:%d,%d位\n", t, sum, count);
return 0;
例3>计算起始值到终止值之间的偶数和
注:
- 输入起始值和终止值
- 注意保证起始值一定小与终止值
起始值大于终止值交换 - 循环求和
- 在判断数据是否是偶数
int start, end, sum = 0;
printf("请输入起始值和终止值:");
scanf("%d %d", &start, &end);
if (start > end)
{
start = start + end;
end = start - end;
start = start - end;
}
int i = start;
while (i <= end) // while(start<=end)
{
if (i % 2 == 0)
sum += i;
i++; // start++;
}
printf("%d-%d之间的和是:%d\n", start, end, sum);
1.2 do…while循环
直到型循环,先做,后判断,最少执行1次
格式1:
表达式1;
do
{
循环体;
表达式3;
}while(表达式2);
//分号必须加 ,当表达式2成立【非0】则循环,不成立【0】,循环结束
格式2:
do
{
循环体;
}while(表达式2); //分号必须加
解析:
- 表达式1: 表示初始值
- 表达式2:循环条件【可以是任意表达式,一般选用关系,算数,逻辑】
- 表达式3:步长
- do…while后面必须加分号
- 死循环 do…while(1);
例:循环1-10
int i=1;//表达式1
do
{
i++;//表达式3
}while(i<=10);//表达式2
1.3 for循环
当型循环,先判断,后执行,最少执行0次
格式:
for(表达式1;表达式2;表达式3)
{
循环体;
}
解析:
- 表达式1:初始值【可以是多个,多个之间使用逗号隔开】
- 表达式2:循环条件【可以是任意表达式,一般选用关系,算数,逻辑】可以是多个,使用运算符进行连接[一般选用逻辑与和逻辑或]
- 表达式3:步长,可以是多个
- 当{}里面只有一条语句是可以省略
- 表达式1,2,3均可省略,但是分号不可以省略
- 死循环 for(;; )
例1: 循环1-100求和
int sum=0;
for(int i=1;i<=100;i++)
{
sum+=i;
}
例2:任意输入一个数,判断这个数是否是素数
素数:质数,只能被1和本身整除
约数:约数一定小于等于本身
7:1----7
判断能被7整除的个数是否是2个,如果是则证明素数,不是2个,不是素数
最小素数是2
int main(int argc, const char *argv[])
{
int num, count = 0;
printf("请输入任意一个数:");
scanf("%d", &num); // 判断num是否是一个素数
for (int i = 1; i <= num; i++) // 循环num所有的约数的可能
{
if (num % i == 0) // 判断i是否是num的约数
{
count++; // 计算能被整除的个数,约数的个数
}
}
if (count == 2)
printf("素数\n");
else
printf("不是素数\n");
return 0;
}
例3 :有10位评委打分,计算去掉最高分和最低分的平均值
1.4 goto
无条件跳转语句
格式:
标识符:
goto 表示符;
- 标识符:满足命名规范
如:
A:
代码段;
goto A ;到代码A
1.5循环嵌套
1.6循环跳转
1.6.1break
break:中断,停止,用来跳出一层循环或switch
使用于所有循环【while\do…while\for】,以及switch,break不可以单独使用在if语句中
1.跳出循环
int i=1;
while(1)
{
printf("%d\n",i);
if(i>2)
{
break;
}
i++;
}
printf("你好\n");
//2.break单独在if中
if(i==1)
{
// break;
}
3.break使用在多层循环嵌套中
for(int i=0;i<3;i++)
{
for(int j=1;j<2;j++)
{
break;//break只可以跳出本层循环
}
}
1.6.2continue
作用:结束本次循环,进入下次循环
场景:只可以只用在循环【while\do…while\for】
for(int i=1;i<20;i++)//7 8 14 15
{
if(i%10==7||i%7==0)
continue;
printf("%d\n",i);
}
1.6.3 return
作用:返回,结束函数
1.6.4 goto
无条件跳转语句
1.6.5 exit
结束程序
格式:exit(常量)
- exit(0): 正常结束程序
- exit(非0)异常结束程序
二、数组
数组:使用连续的存储空间存储类型相同的构造类型
【数组、结构体、共用体】是构造类型,可以分割
2.1 一维数组
只有一个下标表示的数组,称为一维数组
2.2 一维数组的定义格式
格式:[存储类型] 数据类型 数组名[常量表达式];
存储类型:
- auto: 自动类型,一般默认不写的就是自动类型
- static: 静态类型,存储在静态区,延长生命周期
- const:修饰词,表示变量的值不可修改
- register: 寄存器, 访问速度快
- extern: 外部变量
- volatile:防止内存优化
数据类型:
- int 整型
- float 浮点型
- double 双浮点型
- char 字节型
- short 短整型
- 结构体
- 共用体
数组名:符合命名规范
常量表达式:表示数组的个数【不为0,定义不为空,不为小数,初始化时不为变量】
int arr[0]
int arr[];
int arr[2.5];//错误,数组只能是整数
错误示范:
int n=5; //n是变量,不能定义数组
int arr[n]={1,2,3,4,5};错误
2.3 一维数组的初始化
初始化相当于给数组赋初值
- 全局变量:在函数外定义的称为全局变量
全局变量未初始化的数组,默认结果是0 - 静态变量:static int arr[5];
静态变量数组未初始化,默认结果是0 - 局部变量数组未初始化,默认结果是随机值
- 全部初始化
int arr[5]={11,22,33,44,55}; - 部分初始化:剩余元素默认以0填充
int arr[5]={11,22}; - 特殊初始化:在初始化时,可以省略数组长度,默认数组长度是实际元素的个数
int arr[]={11,22,33}; ===> int arr[3]={11,22,33}; - 错误的初始化
int arr[5];
arr={11,22,33,44,55};
2.4 数组的引用
- 数组下标从0开始,如:arr[9]==》下标为0-9
- 越界访问,例如int arr[100],输出arr[100]
-
当越界访问的空间没有被占用,可以访问,输出垃圾值
-
当越界访问的空间被占用,不是重要的数据,可以访问,输出的数据没有意义
-
当越界访问的空间被占用,存储重要的数据,一旦访问,出现段错误
段错误:访问了不该访问的内存空间
2.5 数组的地址空间
- 数组名表示数组的首地址,也就是第一个元素的地址 arr=&arr[0]
数组名表示常量,不可以进行自增或自减【arr++ \ ++arr \ arr-- \ --arr】 - 地址的加减运算,表示地址的偏移
例如:int arr[4];
&arr[0]+1: 表示向高字节方向偏移数据类型大小
&arr[0]-1: 表示向底字节方向偏移数据类型大小 - 地址输出的格式控制符是%p
取地址 | 解释 |
---|---|
&arr[0] | 表示数组第一个元素的地址,偏移一个数据类型大小 |
arr | 数组名表示数组的首地址,偏移一个数据与类型大小 |
&arr | 表示整个数组的首地址,偏移整个数组大小 |
2.6 一维数组组练习
//循环输入n个数,计算最大值,最小值
int main(int argc, const char *argv[])
{
int n, max, min;
printf("输入数组的个数n:");
scanf("%d", &n);
int arr[n];
// 循环数组输入
for (int i = 0; i < n; i++)
{
printf("请输入%d个元素:", i + 1);
scanf("%d", &arr[i]);
if (i == 0) // 第一次循环
{
max = arr[i]; // 给max赋值第一个元素
min = arr[i]; // 给min复制第一个元素
}
if (max < arr[i]) // 计算最大值
max = arr[i];
if (min > arr[i]) // 计算最小值
min = arr[i];
}
printf("max=%d min=%d\n", max, min);
return 0;
}
作业
作业1:
输出如下字符
F
_FE
__FED
___FEDC
____FEDCB
_____FEDCBA
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
int main(int argc, const char *argv[])
{
/* 输出如下字符
F F
_FE - FE
__FED = __ + FED
___FEDC ___ FEDC
____FEDCB ____ FEDCB
_____FEDCBA _____ FEDCBA
*/
for (int i = 1; i <= 6; i++)
{
for (int j1 = 1; j1 < i; j1++)
{
printf("_"); // 输出_
}
for (int j2 = 0; j2 < i; j2++)
{
printf("%c", 70 - j2); // 输出FEDCBA 'F'的ascii值为70
}
printf("\n");
}
return 0;
}
输出的结果如下
作业2
请输入一个整数,判断是不是完美数
注:它所有的真因子(即除了自身以外的约数)的和(即因子函数),恰好等于它本身
如: 6=1+2+3
28= 1+2+4+7+14
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
程序要求:输入一个数判断是不是完美数
一个数恰好等于它的真因子之和
*/
int main()
{
printf("请输入任意一个整数\n");
int a, sum = 0;
scanf("%d", &a);
for (int i = 1; i <= a; i++) //遍历整数从1 到 整数
{
if (a % i == 0 && i < a / i) //可以被整除 且 不让重复求值
{
printf("公因子分别为%d 和 %d\n", i, a / i);
sum += i + a / i;
}
}
if (sum - a == a)
printf("输入的数%d是完美数\n", a);
else
printf("输入的数%d不是完美数\n", a);
return 0;
}