DAY1
*关闭虚拟机:关闭虚拟机不要点右上角的关闭键,如果要关闭虚拟机:点击挂机。不要关闭!!!

编译环境的介绍:
虚拟机:乌班图(ubuntu),是一台虚拟的pc机。
乌班图:LinuxOS(软件裁剪)
什么是嵌入式?
以计算机技术为基础,软硬件可裁剪(修改)的(用软件来控制硬件)
为什么要裁剪:格局用户的 需求。
目录结构
windows的目录结构:有盘符之分(倒置的森林)

LinuxOS的目录结构:没有盘符之分(像一颗倒置的树)

根目录(/):也叫顶层目录:所有路径都从他开始
绝对路径:从根目录开始的路径【/home/linux64/Desktop】
家目录(~)也叫(HOME)(工作目录)(主目录)
home是不是家目录?
home不是家目录:home之下是我们的用户,用户之下才是我们的加目录
家目录之上:普通用户没有操作权限
如果非要操作——在指令前输入sudo (仅有一次管理员权限)
sudo su:切换为超级用户
$:普通用户
#:超级用户
linux之下一切皆文件

Linux常用命令:
命令格式:命令 【选项】 【参数】
注意:
【】括号内的都可以省略,选项就是功能,参数为操作的对象。
三者之间需要用空格隔开
在哪里去输入命令:终端
什么是终端:人机交互的界面。(打开终端的快捷命令1.用鼠标点击终端图标,2.使用快捷键Ctrl、+Alt+t打开默认家目录路径的终端、3.Ctrl+shift+n:打开一个和当前终端相同的路径的终端)
Tab:自动补全
Clear:清屏
Ctrl+l: 清屏
Pwd:显示当前所在的绝对路径
绝对路径:从根(/)目录开始的路径
相对路径:相当于当前的路径
*初学者分不清自己在哪里时应常使用pwd查看自己所处目录。
ls :显示当前路径下的文件
根据颜色区分:
蓝色:文件夹
白色:文件
绿色:可执行文件
ls 路径:显示指定路径下的文件

ls -l:显示当前路径下文件以及他们的属性

ls -a:显示当前路径下的所有文件(包含隐藏文件)
隐藏文件:以.开头的文件

. :当前目录
.. :上一级目录
ls -la:显示所有文件的属性
ls -la 路径:显示指定路径下的所有文件的属性

touch 文件名/文件路径:创建文件,一次可以创建多个
rm 文件名/文件路径: 删除文件,一次可以删除多个


mkdir 文件夹名/文件夹路径:创建文件夹,一次可以创建多个(注意路径)
rmdir 文件夹名/文件夹路径:删除空文件夹,一次可以删除多个
rm -rf : 删除空、非空文件夹
rm -ri: 删除文件夹并且会询问你是否要删除
cd :回到家目录
cd .. :进入上一级目录
cd -:进入上一次操作的路径之下
拷贝:cp 源(文件/-r文件夹) 目标文件中(如果目标是文件夹需要加-r)
mv有两个作用:
移动:mv 文件/文件夹 目标文件
(后面的文件如果存在,就是移动的作用,如果不存在,就是改名的作用)
重命名: mv 原文件名 新文件名
4、Vim编辑器
Vim 文件名
如果此文件存在,进入文件并进行编辑
如果此文件不存在,创建并且进入

三种模式:
命令行模式(刚进入)
插入模式
底行模式
三种模式如何转换:
命令行模式-》插入模式:i
插入模式-》命令行模式:esc
命令行模式-》底行模式:shift+:
底行模式-》命令行模式:esc
底行模式下:
w:保存
q:退出
wq:保存并退出
q!: 强制退出
wq!:保存并强制退出
Set nu: 显示行号
Set nonu: 取消显示行号
命令行模式下:
yy:复制
dd:剪切(剪切后不粘贴则为删除))
P : 粘贴
nyy:复制n行
ndd: 删除n行
u:撤销
Ctrl+r:反撤销
5、gcc编译器

main()
{
return 0;
}
//如果没有写返回值,默认为int类型
void main()
{
函数体;
}
编译:(编译为计算机能够识别的二进制文件!)
gcc hello.c
默认生成的可执行文件为a.out
运行后输入./a.out即可执行文件。(./当前目录)
gcc hello.c -o hello
将生成的可执行文件命名为指定名字
执行:./hello

Day2
计算机的基本组成
组成:输入输出设备(键盘、鼠标)
CPU处理器(控制器、运算器、寄存器)
存储器
程序
存储器:
内存:读写速度更快、容量较小,掉电数据丢失(4+128)
外存:读写速度慢,容量较大,掉电数据不会丢失
寄存器(cpu内部的存储器):容量很小,但是读写速度非常快
2.什么是程序
程序:计算机能够识别的一组有序的指令
指令:计算机能够识别的操作
hello.c和a.out哪个是程序?
a.out是程序(计算机去看的)
3.程序的设计步骤
Vim(编辑器)——》gcc(编译器)——》./a.out(执行)
计算机中的数据表示
4.数值数据和非数值数据
10——》二进制存储
非数据数据在计算机中怎么存储?
4.1非数值数据
(不能直接进行算术运算的数据)
字符、图片、声音、、、、
‘a’‘b’‘A’...
字符在计算机中:
Ascii码(十进制):规定每一个字符都以某8位二进制数去表示
每一个字符都以8bit的二进制数进行存储(1字节=8bit)

记住:‘A’:65
‘a’:97 ‘0’:48
4.2数值数据
可以直接进行算术运算的数据
十进制、二进制、八进制、十六进制
十进制(逢10进1): 0~9
二进制(逢2进1):0~1
八进制(逢8进1):0~7
十六进制(逢16进1): 0~9,a(A)~f(F)
为了区分不同的进制:
76 076(在八进之前加0) 0x76(十六进之前加0x)(注意:0xa7fc 0XA7FC)
4.3进制转换
其他进制转十进制(其他进制*其位数的位次幂)
二进制转换为十进制: 1011----> 1*2^0+1*2^1+0*2^2+1*2^3
八进制转换为十进制: 076------> 6*8^0+7*8^1
十六进制转换为十进制:0xafc---->12*16^0+15*16^1+10*16^2
十进制转其他进制(除以其他进制倒取余数):
十进制转换为二进制(除2倒取余): 34------->0010 0010
十进制转换为八进制(除8倒取余): 34------->042
十进制转换为十六进制(除16倒取余):34------->0x22
二进制和八进制的互相转换421:(每一个八进制数都可以用三位2进制数表示)
0 ~ 7 (421)
0 ----------000
----------001
----------010
----------011
----------100
----------101
6-----------110
7-----------111
二进制和十六进制互相转换8421:每一个十六进制都可以用4位二进制数表示
0~f ( 8421 )
------- 0000
--------0001
--------0010
--------0011
--------0100
--------0101
--------0110
--------0111
--------1000
--------1001
--------1010
--------1011
--------1100
--------1101
--------1110
--------1111
0xfca转换为二进制:1111 1100 1010
10 1001 0101转换为十六进制:0x295
练习:
实现其他进制转换为十进制:
1100 1110 转换为16进制:0x ce :转成10进制:14*16^0+12*16^1=206
06543 = 3*8^0+4*8^1+5*8^2+6*8^3= 3427
0xfadc = 13*16^0+14*16^1+10*16^2+15*16^3 = 64220
十进制转二进制:987 (可以先转换为16进制或者8进制)(然后在转换为二进制)
八进制和十六进制转换为二进制:
0xa865 0763
1010 1000 0110 0101 111 110 011
二进制转换为八进制和十六进制:
1100 1110 1110
0xcee
110 011 101 110
5、基本数据类型
5.1关键字:系统预先定义好的,有特定含义的,都是小写,不能重新定义(int int//error)
(32个关键词!!)
数据类型:int 、char、 short、 long 、float、double、enum、struct、union、void
控制语句:if、else、while、switch、case、default、break、continue、for、do、goto、
存储类型:auto、extern、static、register
return:返回函数
const:只读
signed:有符号数(正数和负数)
unsigned无符号数(正数)
sizeof:求所占内存空间的大小(sizeof(数据类型)、sizeof(变量名))
typedef:给已有的数据类型起别名
volatile:防止编译器优化
5.2标识符:程序员自己去定义的,一般用来定义变量名,函数名,类姓名
要求:(见名知意)【int year;】
不能和关键字重名
由数字、字母、下划线组成、
第一个字母不能为数字
5.3基本数据类型:
32OS:
字符型:char(1字节)
整型:int(4字节) short(2字节) long(4字节)
浮点型:float(4字节) double(8字节)

64OS:
字符型:char(1字节)
整型:int(4字节) short(2字节) long(8字节)
浮点型:float(4字节) double(8字节)

注意:不同的数据类型所占的内存空间是不一样的,作用是为了让我们合理的分配内存空间
5.4有符号数和无符号数:
有符号数:signed:正数和负数
数值数据在计算机中以2进制进行存储
并且所有的数据在计算机中都是以补码的形式存储的
符号位:最高位为符号位:0表示正数,1表示负数
10 ---------> 0000 1010
-10---------> 1000 1010
10+(-10)= 0
因此原码、反码、补码
正数:原码,反码,补码都是一样的!!
10
原码:0000 1010
反码:0000 1010
补码:0000 1010
负数:
原码:最高位为符号位
反码:符号位不变,其他位取反
补码:反码+1
-10
原码:1000 1010
反码:1111 0101
补码:1111 0110
知道一个数的补码,怎样去求得原码?
负数:补码= 反码+1
补码的补码的就是原码
(补码-1),然后符号位不变,其他位取反
5.4无符号数:unsigned:正数
字符型家族
值域范围:
char(1byte == 8bit)
Unsigned : 0000 0000 ------------1111 1111 (0-255)
Signed: 1000 0000 -----------0111 1111 (-128~127)
Unsigned char c = 260;(超范围:转圈去计算他的值)
Printf(“%d\n”,c); // 4
Signed char a = 130;
Printf(“%d\n”,a);//-126
5.5整型家族
值域范围:
int(4byte == 32bit)
Unsigned :(0至2^32-1)
0000 0000 0000 0000 0000 0000 0000 0000 --- 1111 1111 1111 1111 1111 1111 1111 1111
Signed:(-2^31至2^31-1)
1000 0000 0000 0000 0000 0000 0000 0000 --- 0111 1111 1111 1111 1111 1111 1111 1111
5.6浮点型家族
Float:(4字节)单精度浮点数:准确的表示6-7位有效数字(%f)

Double:(8字节)双精度浮点数:准确的表示15-16位有效数字(%lf)

%f和%lf默认输出小数点后6位
****Printf(“格式控制串”,输出表);
格式控制串:原样输出的内容+格式化符(:%c,%d,%f ,%lf)
输出表:输出的内容
Int a = 10;
Printf(“a = %d”,a);
作业:
1、整理笔记
2、自己计算short值域范围
Short(2byte == 16bit)
Unsigned: 0000 0000 0000 0000-----1111 1111 1111 1111(0 - 2^16-1)
Signed: 1000 0000 0000 0000------0111 1111 1111 1111(-2^15-1---2^15-1)
1111 1111 1111 1111
1000 0000 0000 0000
+1
-1
负数两种表示:因1000值域大于1111所以选择1000....。
Day3
1、转义字符


2、常量
程序运行期间,其数值不能也不会被改变的量
2.1 字符常量
‘a’ ‘A’ ‘b’
2.2 整形常量
二进制:1010
八进制:076
十进制:99 -5
十六进制:0xaf7c
注意:默认情况下,整形常量是有符号的(int类型,short、long)
无符号的int整型数:66U
长整型:66L
无符号的长整型:66UL
2.3 浮点型常量
小数:1.45 0.00001 10000(浮点型常量包含整形常量)
指数形式:1e-4 1e+4
%g:选择小数或者指数较短的一种进行输出(合适的一种)
(error//1*10^4)



2.4 字符串常量
“hello” “hi”

注意:字符串‘\0’作为结束符
2.5 标识常量(宏)
#define 宏名 表达式
注意:
1、宏名一般用大写,小写也可以,但是为了和普通的变量区分开,用大写
2、宏后面没有分号!!!
案例:实现求圆的周长和面积
#define PI_ROUNDE 3.14

Gcc -E 文件名.c -o 文件名.i-------》vi 文件名.i即可进入右边这个界面。【小写】
宏只是一个单纯的替换!!!
宏函数:(既有宏的特点又有宏函数的特点)
#define 函数名(形参) 函数体
案例1:实现两个数的求和

案例2:

案例3:

案例4:

注意:宏只是一个单纯的替换,不回去考虑运算符的优先级的问题,所以需要给每个形参加上括号,以及整个表达式加上括号
3.变量
定义:意味着要开辟内存空间

如何去定义一个变量?
<存储类型> 数据类型 变量名;
存储类型:决定开辟的空间在内存中的哪个分区;
数据类型:决定了开辟的空间在内存中的大小;
变量名:开辟空间的名字;
存储类型:auto、static、extern、register
数据类型:char、short、int、long、float、double

3.1局部变量
局部变量:定义在函数体(任何函数体)内
3.2全局变量
全局变量:定义在函数体外的变量

3.3存储类型
存储类型:auto static extern register
auto:只能用来修饰局部变量,修饰的变量存储在栈区
static:全局变量和局部变量均可,修饰的变量存储在静态区
extern:只能用来修饰全局变量,修饰的变量存储在静态区
register:只能用来修饰局部变量,修饰的变量存储在寄存器中,若寄存器空间不足则存储在栈区。
作用:防止编译器优化。
3.4初始化
初始化:定义变量的时候就给变量赋值
int b = 10; //初始化
int a;//定义了一个变量
a = 10;//赋值


注意:
全局变量不进行初始化,他的值为0;
局部变量不进行初始化,他的值是一个随机值。
auto :修饰局部变量,存储在栈区
register:修饰局部变量,修饰的变量存储在寄存器中,一般将变量存储在寄存器中,可以提高运行速度,但是,寄存器的内存空间很小,所以用register修饰局部变量时,若寄存器空间已满,会将变量存储在栈区。
extern:修饰全局变量,存储在静态区
程序可以由多个.c文件构成,但是main函数只能有一个

作用:告诉编译器,该变量已经在其他文件中定义改过了
Static:既可以修饰全局变量,也可以修饰局部变量,修饰变量的时候存储在静态区
1、用static修饰的局部变量:延长局部变量的生命周期,如果局部变量没有初始化,他的值为0,如果初始化了,那么只能初始化一次。


2.用static修饰的全局变量,只能在本文件内使用(限定作用域)

3.5生命周期和作用域
3.51生命周期
从什么时候开辟空间到什么时候释放空间
3.52作用域
使用的范围
局部变量:
生命周期:从定义开始,到模块(大括号)结束
作用域:大括号内
Static修饰的局部变量:
生命周期:从定义开始,到程序结束
作用域:大括号内
全局变量:
生命周期:从定义开始,到程序结束
作用域:整个程序
Static修饰的全局变量:
生命周期:从定义开始,到程序结束
作用域:本文件内
4、数据类型转换
4.1强制类型转换(我们自己转换)

4.2隐式类型转换(编译器自己进行转换)

横向箭头:不管有没有进行混合运算,都会进行转换

注意:char、short都当做int来用

注意:float当做double来用
纵向箭头:只有进行混合运算了,才会进行转换

案例:

隐式类型转换,a+b为混合运算,a+b>0,转换为unsigned,8>0,输出6666
Day4
1、运算符
单算移关与,异或逻条赋!
单目运算符,算术运算符,左移,右移,关系运算符,按位与,异或,按位或,逻辑运算符,条件运算符,赋值运算符
1.1 关系运算符
> < >= <= == !=
关系运算符:比较的结果是真或假

注意:0<a<5//error
注意!!!等号的书写
常量写在等号的左边
(如果判断相等时少写了一个=,会报错)


1.2算数运算符
+ - * / % ++ --
注意:%不能用于浮点数
++在前:先自加,在赋值
++在后:先赋值,在自加
注意:当a++或者++a,单独成立一条语句时,都相当于给a+1


1.3 逻辑运算符
&& || !
&&:表达式1&&表达式2
截断法则:有一个为假,结果就为假,前一个为假,后面就不再进行运算了!

||:表达式1||表达式2
截断法则:有一个为真,结果就为真,前一个为真,后面就不在进行运算了!


C = a > 0比较运算符,只比较结果真假,真为1,假为0.因此该等式为真,输出c = 1,b=2。
!: !0 为1
1.4 sizeof运算符
Sizeof(变量名)或sizeof(数据类型)

1.5 三目运算符
表达式1?表达式2:表达式3
注意:
判断表达式1,是否成立,如果成立,就将表达式2的值作为整个表达式的值,否则,就将表达式3的值作为整个表达式的值


1.6 逗号运算符
表达式1,表达式2,表达式3,。。。。。。表达式n
从左往右依次计算每个表达式的值,将表达式n的值作为整个表达式的值
(注意:必须依次计算,以防止前面的表达式改变了表达式n中的变量的值)
注意:逗号运算符的优先级是最低的,因此在使用的时候,要加上括号


1.7 位运算符
& | ~ << >> ^
1.7.1 &运算符
都为1,才为1,有一个为0,就为0
1000 0010
& 1100 1111
1000 0010
案例:将1101 0011的0-2位进行清零
1101 0011
& 1111 1000 (~7)
1101 0000
101010100101010100111 0-2位进行清零
111111111111111111000 == ~( 0000000000111) = = ~7
1.7.2 |运算符
都为0 ,才为0,有一个为1,就是1
1000 0010
| 1100 1111
1100 1111
案例:将1101 0101的3~5位 置为101
清零3-5 & 1100 0111 ~(111000) &(~56)
11 000 101
| 00 101 000
11 101 101
101010100101010100111 3-5 置为101
置零(3-5) &111111111111111 000111 ~(000000000111000) = =(~56)
置为101 | 000000000000000 101 000
步骤:将3-5位清零其余全为1,|上101即可。(有1则为1同为0则为0)
1.7.3 取反~
0变1,1变0
~(1001 0101)= = 0110 1010
1.7.4 异或^
相同为0,不同为1
1000 0010
^ 1100 1111
0100 1101
1.7.5 左移
Unsigned: 只有正数
没有符号位
1<< 2
1--->0000 0001
高位丢弃,低位补0
补零:0000 0100 : 4

Signed:-1<<2
原码:1000 0001
反码:1111 1110
补码:1111 1111
符号位不变,高位丢弃,低位补0
补0:1111 1100
反码:1000 0011
原码:1000 0100 :-4

1.7.6 右移
Unsigned:只有正数
没有符号位
>2
低位丢弃,高位补0
0000 0100
补零:0000 0001 :1

Signed: 正数+负数
有符号位
-4 >>2
符号位不变,低位丢弃,高位补1
-4 的原码:1000 0100
反码:1111 1011
补码:1111 1100
补1: 1111 1111 1000 0000+1 = 1000 0001 = -1
补码的补码就是原码
补码=反码+1


2.输入输出
函数:有独立功能的一个模块
标准输出输入函数:printf、scanf(对变量类型没有限制)
输入:从键盘拷贝数据到内存中
输出:将内存种的数据打印到终端
2.1 输出函数
printf(“格式控制串",输出表);
格式控制串:原样输出的内容+格式化符(%c、%d、%f、%lf)
输出表:输出的内容
int a = 10;
printf(“a = %d\n”,a);
整型:
%d:以整型形式进行输出
%o: 以八进制形式进行输出
%x:以十六进制形式进行输出(a-f)
#:自动在八进制和十六进制前加上前缀
%X:以十六进制的形式进行输出(A-F)
%u:以无符号整型进行输出
%hd:以short类型,进行输出
%ld:long类型

字符型:
%c

浮点型:
%f:float类型
%lf:double类型
%g:选择小数/指数较短的一种进行输出
%e:以指数形式进行输出
%.nf:保留小数点后n位进行输出

%m.nf
m:指定我们输出的域宽:当m大于0时,默认右对齐,m小于0,左对齐
当m的值大于数据的实际长度时,补空格,m小于数据的实际长度,原样输出!

2.2 输入函数
scanf(“格式控制串”,地址表);
格式控制串:原样输出的内容+格式华府
地址表:&+变量名


注意:1、scanf格式控制串,不要加修饰语,如果要加,要原样输入【scanf(“%d”,&a)】

2、如果输入“%d%d”时,要给多个变量进行赋值,在格式控制串中,没有多余的修饰语时,那么输入以空格、回车、tab键作为第一个变量结束的标志
3、全部输入结束,必须以回车作为结束符
4、如果以“%c%c”输入多个字符时,不能有空格、回车、tab键,因为空格、回车、tab键也是一个字符。

解决办法:1、在%c和%c之间加上“,”或者加上空格

加上%*c,*表示的是抑制字符(吃掉一个字符)

%*nc表示吃掉n个字符

2.3 字符输入输出函数
2.31字符的输入函数:
getchar()
返回值:输入字符的ASCII码值
int a = 0;
a = getchar();
2.32字符的输出函数:
putchar()
参数:输出字符的ASCII码值


作业:
1、
不使用第三方变量
实现两个数的交换



自定义宏函数,用三目运算符求两个数中比较小的数
敲代码:

4、设x为int变量,x = 10,计算x+=x-=x-x,最后x的值为多少 x= 20
5、定义x和y为double型变量,则表达式x=1,y=x+3/2 y的值是多少? y = 2.0
6、定义t和y为int型变量,表达式y = (t=1,t+5,t++);
y的值为多少,t的值为多少?
T = 2
Y = 1
Day5
三大结构:
顺序结构、选择结构、循环结构、
顺序结构:
程序运行期间,语句按照一定的先后顺序去执行
选择结构
2.1单分支选择结构
if(表达式1)
{
语句;
}
先判断表达式的值,如果表达式为真,就执行语句
2.2双分支if选择结构
if(表达式1)
{
语句1;
}
else
{
语句2;
}
先判断表达式1是否成立,表达式1成立执行语句1,否则执行表达式2
案例:输入任意年份,判断该年是闰年还是平年。
//闰年:每4年润+100年不润+400年世纪润。【用if表达式表达出来,定义int year;】
//if(0 ==year%4 && 0 != year%100 || year ==400)

初学者遇到题目应该先要在本子上思考出来需要满足的条件、定义的变量等然后再去敲代码!!
2.3多分枝if选择结构
if(表达式1)
{
语句1;
}
else if(表达式2)
{
语句2;
}
else if (表达式3)
{
语句3;
}
else if (表达式n)
{
语句n
}
else
{
语句n+1;
}
从上往下,依次判断每个表达式的值,如果表达式成立,则执行对应语句。
案例:
输入一个成绩,判断改成绩的等级
输入一个成绩,判断该成绩的等级
90以上:A
75-90:B
60-75:C
60以下:D


2.4 switch语句
switch(表达式)
{
case标号1:
语句1;
case标号2:
语句2;
case标号3:
语句3;
case标号n:
语句n;
default:
语句n+1;
}
注意:1、表达式不能为float类型
2、标号必须为常量
3、当表达式==标号的时候,执行冒号后面对应的语句,
1、直到switchcase语句结束为止,或遇到break,语句结束;

案例:输入年份月份,判断该年有多少天

3循环结构
重复的做一件事
循环的三要素:循环的其实条件,循环的终止条件,循环变量的变化
3.1 for循环
for(表达式1;表达式2;表达式3)
{
循环体;
}
表达式1:循环的初始条件
表达式2:循环的终止条件
表达式3:循环变量的变化
先执行表达式1,在执行表达式2,如果表达式2为真,执行循环体,然后执行表达式3,
去判断表达式2是否成立,如果成立则继续执行循环体,否则,跳出。

案例:实现1-100之和

思考:表达式1,2,3是否可以省略
省略表达式1:可以省略
需要在循环体外给循环变量一个初始值

省略表达式2:可以省略(死循环)

省略表达式3:可以省略
在循环体内实现循环变量的变化

注意:3个表达式都可以省略,但是;不可以省略
for循环的嵌套:

案例:
打印


3.2 while语句
while(表达式)//循环的终止条件
{
循环体;
}
判断表达式是否成立,如果成立,则执行循环体,否则跳出
案例:1-100之和

3.3 do...while语句
do
{
循环体;
}while(表达式);
先去执行循环体,然后判断表达式是否成立,如果成立,执行循环体,否则跳出循环
while和dohile区别:
while:先判断在执行,循环体最少执行0次;
dowhile:先执行在判断,语句至少执行1次;
Break和continue的区别:
跳出循环:离他最近的循环
break:1跳出switchcase语句。2跳出循环(离他最近的循环)

continue:
调出循环
1、跳出本次循环,进入下一次循环


3.4 死循环
while(1)
{
循环体;
}
for(;1;)
{
循环体;
}
3.5 goto语句
无条件跳转语句
goto标号://当执行到这条语句时,程序自动跳转至标号处!
标号:
标号:命名规则和标识符相同!
案例:用goto实现1-100之和

goto loop;
loop:
作业:
1、打印等腰三角形


2、打印99乘法表

选做:打印菱形


