该文章Github地址:https://github.com/AntonyCheng/c-notes【有条件的情况下推荐直接访问GitHub以获取最新的代码更新】
在此介绍一下作者开源的SpringBoot项目初始化模板(Github仓库地址:https://github.com/AntonyCheng/spring-boot-init-template【有条件的情况下推荐直接访问GitHub以获取最新的代码更新】& CSDN文章地址:https://blog.csdn.net/AntonyCheng/article/details/136555245),该模板集成了最常见的开发组件,同时基于修改配置文件实现组件的装载,除了这些,模板中还有非常丰富的整合示例,同时单体架构也非常适合SpringBoot框架入门,如果觉得有意义或者有帮助,欢迎Star & Issues & PR!
上一章:由浅到深认识C语言(2):C语言的类型及语句
2.C语言的类型及语句
2.3.运算符
用运算符将运算对象连接起来,复合C语言语法规则的式子,称为C算术表达式;
运算对象包括常量,变量和函数等:
例如:a*b/c-1.5+'a'
算数运算符
符号 | 意义 |
---|---|
+ | 加法 |
- | 减法 |
* | 乘法 |
/ | 取整 |
% | 取余 |
示例如下:
int way() {
printf("%d\n", 5 + 2);
printf("%d\n", 5 - 2);
printf("%d\n", 5 * 2);
// 5/2 = 2···1 取整之后为 2
printf("%d\n", 5 / 2);
// 5/2 = 2···1 取余之后为 1
printf("%d\n", 5 % 2);
}
int main(int argc, char *argv[]) {
way();
return 0;
}
打印效果如下:
如果我们想要做一次生活当中的除法,示例如下:
int way() {
printf("%f\n", 5 / 2.0f);//加一个浮点数就是除法
}
int main(int argc, char* argv[]) {
way();
return 0;
}
打印效果如下:
案例:键盘输入一个数,判断其是否能被 3 整除;
int way() {
printf("请输入一个数:");
int num;
scanf_s("%d", &num);
if (num / 3 == 0) {
printf("这个数能被 3 整除\n");
}
else if (num / 3 != 0) {
printf("这个数不能被 3 整除\n");
}
}
int main(int argc, char *argv[]) {
way();
return 0;
}
打印效果如下:
案例:键盘输入一个四位数,请取出每位上的数值;
int way() {
printf("请输入一个四位数:");
int num,num1,num2,num3,num4;
scanf_s("%d", &num);
num1 = num % 10;
num2 = num % 100 / 10;
num3 = num / 100 % 10;
num4 = num / 1000;
printf("个位:%d 十位:%d 百位:%d 千位:%d", num1, num2, num3, num4);
}
int main(int argc, char *argv[]) {
way();
return 0;
}
打印效果如下:
关系运算符
符号 | 意义 |
---|---|
> | 大于 |
< | 小于 |
== | 等于 |
>= | 大于等于 |
<= | 小于等于 |
!= | 不等于 |
逻辑运算符
符号 | 意义 |
---|---|
! | 逻辑非 |
&& | 逻辑与 |
**` |
-
逻辑非:
C语言中只有
0
为假,其他的数都为真:!0 == Ture !Ture == False
示例如下:
int way() { printf("%d\n", !1); printf("%d\n", !-1); printf("%d\n", !0); } int main(int argc, char* argv[]) { way(); return 0; }
打印效果如下:
-
逻辑与:
-
A && B
:当A
B
同时为真,整个表达式才为真;只要A
B
有一个为假,整个表达式也为假;示例如下:
int way() { if (3 > 2 && 5 > 4) { printf("ok\n"); } else { printf("no\n"); } if (2 > 3 && 5 > 4) { printf("ok\n"); } else { printf("no\n"); } } int main(int argc, char* argv[]) { way(); return 0; }
打印效果如下:
-
逻辑与的短路特性
A && B
:如果A
为假,系统不会执行B
,这就是&&
的短路特性;示例如下:
//验证短路特性 int way() { int num = 10; printf("比较之前num = %d\n", num); (2 > 3) && (num = 100); printf("比较之后num = %d\n", num); } int main(int argc, char* argv[]) { way(); return 0; }
打印效果如下:
-
-
逻辑或:
A || B
只要A
B
任意一个为真,整个表达式为真;A
B
同时为假,整个表达式才为假;示例如下:
int way() { // 假 假 if ((3 < 2) || (5 < 4)) { printf("ok\n"); } else { printf("no\n"); } // 真 假 if (3 > 2 || 5 < 4) { printf("ok\n"); } else { printf("no\n"); } // 真 真 if (3 > 2 || 5 > 4) { printf("ok\n"); } else { printf("no\n"); } } int main(int argc, char* argv[]) { way(); return 0; }
打印效果如下:
逻辑或也有短路特性:
int way() { int num = 10; printf("比较之前的num = %d\n", num); (3 > 2) || (num = 100); // num = 100 等不到执行 printf("比较之后的num = %d\n", num); } int main(int argc, char* argv[]) { way(); return 0; }
打印效果如下:
-
综合案例:表示横轴区间;
注释:蓝色表示
0-100
且不包含 0 和 100-
蓝色:
x < 100 && x > 0;
-
红色:
x >= 100 || x <=0;
-
位运算符
主要是指二进制位的操作;
符号 | 意义 |
---|---|
>> | 右移 |
<< | 左移 |
& | 按位与 |
**` | `** |
~ | 按位取反 |
^ | 按位异或 |
-
左移:
<<
示例如下:我们将
10101100
左移两位;1010 1100 << 2; //(10)10 1100 00 移出的丢弃掉,空缺的用 0 去补; //结果为 1011 0000
注意:移动的位数不要超过或者等于自身长度;
-
右移:
>>
示例如下:我们将
10101100
右移两位;1010 1100 >> 2; // 11/00 1010 11(00) 移出的丢弃掉,空缺的用 0 或 1 去补; //结果为 1110 1011 或者 0010 1011
右移 { 逻辑右移:右边丢弃,左边补 0 算术右移 { 无符号数:右边丢弃,左边补 0 有符号数: { 正数:右边丢弃,左边补 0 负数:右边丢弃,左边补 1 \bf{右移}\begin{cases} \bf{逻辑右移:右边丢弃,左边补0} \\ \bf{算术右移} \begin{cases} \bf{无符号数:右边丢弃,左边补0}\\\bf{有符号数:}\begin{cases} \bf{正数:右边丢弃,左边补0}\\\bf{负数:右边丢弃,左边补1} \end{cases} \end{cases} \end{cases} 右移⎩ ⎨ ⎧逻辑右移:右边丢弃,左边补0算术右移⎩ ⎨ ⎧无符号数:右边丢弃,左边补0有符号数:{正数:右边丢弃,左边补0负数:右边丢弃,左边补1
注意:右移有且只有是负数且算术右移时,左边才会补 1 ;
逻辑右移和算术右移是编译器决定的,我们可以对此做出检测;
示例如下(以VS为例):
void method() { char ch = 0x85;//1000 0101 //逻辑右移:1000 0101>>4 == 0000 1000 == 0x08 //算术右移:1000 0101>>4 == 1111 1000 == 0xf8 ch = ch >> 4; printf("%#x\n", ch); } int main(int argc, char* argv[]) { method(); return 0; }
打印效果如下:
打印结果分析:
因为
ch
是 char 型,占内存为 1B,而输出得是 int 型,占内存为 4B,f
是编译器自己补上去的,所以只看最后两位f8
,该结果满足算术右移,所以判断 VS 是算术右移编译器; -
按位与:
&
0 & 0 = 0
0 & 1 = 0
1 & 1 = 1
即:全一为一,其他为零;
示例如下:
1010 1010 & 1111 0000 --------------- 1010 0000
特点:和一相与保持,和零相与清零;
应用场景:将固定位清零;
-
按位或:
|
0 | 0 = 0
1 | 0 = 1
1 | 1 = 1
即:全零为零,其他为一;
示例如下:
1010 1010 | 1111 0000 --------------- 1111 1010
特点:和零相或保持,和一相或置一;
应用场景:将固定位置一;
案例:将1010 1010的第2、3位置一,其他位保持不变
位次 7654 3210 --------------- 题目: 1010 1010 | --------------- 1010 1110 答: 1010 1010 | 0000 1100 --------------- 1010 1110
-
按位取反:
~
~ 0 = 1
~ 1 = 0
即:零变一,一变零;
示例如下:
~1010 1010 == 0101 0101
应用场景:配合
&
|
操作; -
按位异或:
^
1 ^ 1 = 0
0 ^ 0 = 0
1 ^ 0 = 1
即:相同为零,相反为一;
示例如下:
1010 1010 ^ 0000 1111 --------------- 1010 0101
特点:和零异或保持,和一异或取反;
应用场景:将固定位发生高低电平反转;
案例:将1010 1010第零位发生翻转;
位次 7654 3210 --------------- 题目: 1010 1010 ^ --------------- 1010 1011 答: 1010 1010 ^ 0000 0001 --------------- 1010 1011
其他运算符
符号 | 意义 |
---|---|
= | 赋值运算符 |
? 和: | 条件运算符 |
, | 逗号运算符 |
* 和 & | 指针运算符 |
sizeof() | 求字节数运算符 |
. - > | 分量运算符 |
[ ] | 下标运算符 |
-
条件运算符----
?
和:
用法:
表达式? a : b
,若表达式为真,则输出a
,否则输出b
。示例如下:
int way() { int ret = 0; ret = 3 > 2 ? 5 : 6; printf("ret = %d\n", ret); } int main(int argc, char* argv[]) { way(); return 0; }
打印效果如下:
-
逗号运算符
逗号运算符的优先级最低,且计算顺序从左往右,所以逗号运算符在括号里时,会遍历括号里的元素,直至最后;
示例如下:
void way() { int data1 = 0; int data2 = 0; data1 = 3, 4, 5, 6; data2 = (3, 4, 5, 6); printf("data1 = %d\n", data1); printf("data2 = %d\n", data2); } int main(int argc, char* argv[]) { way(); return 0; }
打印效果如下:
综合案例
注意:我们用十六进制去表示二进制,比如:0xaa
代表 1010 1010
;
-
将
1010 1010
的第1
,5
位 清零,第3
,4
位 置一;方法一:
int way() { //我们用十六进制去换算二进制 signed int num = 0xaa; num = num & 0xcc; num = num | 0x18; printf("%x\n", num); } int main(int argc, char* argv[]) { way(); return 0; }
方法二:
int way() { //我们用十六进制去换算二进制 signed int num = 0xaa; num = num & ~(0x01 << 5 | 0x01 << 1); //可读性 1 5 位清零 num = num | (0x01 << 4 | 0x01 << 3); //可读性 3 4 位置一 printf("%x", num); } int main(int argc, char* argv[]) { way(); return 0; }
打印效果如下:
我们再将
98
转换成二进制得:1001 1000
;
复合运算符
符号 | 意义 |
---|---|
+= | 加等 |
-= | 减等 |
*= | 乘等 |
/= | 除整等 |
%= | 除余等 |
++i | |
--i | |
i++ | |
i-- |
-
以
+=
举例: A + = B < = = > A = A + B A + = B + C < = = > A = A + ( B + C ) A+=B\ <==>\ A =A+B\\A+=B+C\ <==>\ A=A+(B+C) A+=B <==> A=A+BA+=B+C <==> A=A+(B+C)注意:
=
右边需要看成一个整体先算; -
++i
或者--i
:先加减,后使用;示例如下:
void way() { int i = 3; int j = 0; j = ++i; printf("i = %d,j = %d", i, j); } int main(int argc, char* argv[]) { way(); return 0; }
解释:
step1:i+1 ==> i==4(先加减)
step2:y=i ==> j==4(然后赋值)
打印效果如下:
-
i++
或者i--
:先使用,后加减;示例如下:
void way() { int i = 3; int j = 0; j = i++; printf("i = %d,j = %d", i, j); } int main(int argc, char* argv[]) { way(); return 0; }
解释:
step1:j=i ==> j==3(先赋值)
step2:i+1 ==> i==4(然后加减)
打印效果如下:
注意:当
i++/--
或者++/--i
作为单独的指令没有区别;示例如下:
void way() { int a = 1; int b = 1; int c = 1; int d = 1; a++; b--; ++c; --d; printf("a = %d,b = %d, c = %d, d = %d", a, b, c, d); } int main(int argc, char* argv[]) { way(); return 0; }
打印效果如下:
优先级
C语言中,运算符的优先级一共分为15级,优先级高的先执行;
同级别的优先级需要看结合性;
优先级如下图:
注意:自己写代码时,尽量规范优先级,实在不能确定,用小括号将优先参与运算的部分括起来;
2.4.控制语句
C语言运行结构
运行结构 { 顺序结构:程序按顺序执行,不发生跳转; 选择结构:依据是否满足条件,有选择的执行相应功能; 循环结构:依据条件是否满足,循环多次执行某段代码; \bf{运行结构}\begin{cases} \bf{顺序结构:程序按顺序执行,不发生跳转;}\\\bf{选择结构:依据是否满足条件,有选择的执行相应功能;}\\\bf{循环结构:依据条件是否满足,循环多次执行某段代码;} \end{cases} 运行结构⎩ ⎨ ⎧顺序结构:程序按顺序执行,不发生跳转;选择结构:依据是否满足条件,有选择的执行相应功能;循环结构:依据条件是否满足,循环多次执行某段代码;
if判断语句
-
如果只在乎项目的一个结果,则选择
if
:if (表达式){ 语句1; }
只有表达式为真的时候,才执行语句1;
案例:判断一个数能被二整除;
void function() { int a = 0; printf(" 请输入一个整数:"); scanf_s("%d", &a); if (a % 2 == 0) { printf(" %d 能被 2 整除", a); } } int main(int argc, char* argv[]) { function(); return 0; }
打印效果如下:
或者
-
如果项目只有两种结果且不会同时出现,则选择
if……else……
:if (表达式){ 语句1; } else{ 语句2; }
表达式为真,执行语句1,否则执行语句2;
案例:判断 data 对 2 的余数;
void function() { int data = 0; printf(" 请输入一个整数:"); scanf_s("%d", &data); if (data % 2 == 1) { printf(" %d 对 2 的余数为 1", data); } else { printf(" %d 对 2 的余数为 0", data); } } int main(int argc, char* argv[]) { function(); return 0; }
打印效果如下:
或者
-
如果一个项目有多个结果且不同时出现,则选择
if……else if ……else if……else
:if(表达式1){ 语句1; } else if(表达式){ 语句2; } //…… //一共 n 个 //…… else{ 语句n; }
只有表达式1为真,执行语句1,只有表达式2为真,执行语句2,所有表达式都为假,才执行语句n;
案例:判断data对3的余数;
void function() { int data = 0; printf(" 请输入一个整数:"); scanf_s("%d", &data); if (data % 3 == 2) { printf(" %d 对 3 的余数为 2\n", data); } else if (data % 3 == 1) { printf(" %d 对 3 的余数为 1\n", data); } else { printf(" %d 对 3 的余数为 0\n", data); } } int main(int argc, char* argv[]) { function(); return 0; }
打印效果如下:
或者
或者
注意:在
else if
中,只有前面的条件不满足,才会判断后面的条件,如果前面的条件满足了,后面的条件不管真假都不会执行;示例如下:
void function() { if (6 % 2 == 0) { printf(" 6%%2\n"); } else if (6 % 3 == 0) { printf(" 6%%3\n"); } else if (6 % 1 == 0) { printf(" 6%%1\n"); } } int main(int argc, char* argv[]) { function(); return 0; }
打印效果如下:
-
一个项目有多个结果,不确定是否同时出现,则选择
if……if……if……
:if(表达式1){ 语句1; } if(表达式2){ 语句2; } //…… //一共 n 个 //…… if(表达式n){ 语句n; }
注意:每一个
if
语句是独立的,所以这样写就不会按顺序表达,且不会停止判断; -
案例(键盘输入一个数,判断能否被3和7同时整除);
void function() { int num = 0; printf(" 请输入一个整数:"); scanf_s("%d", &num); if ((num % 3 == 0) & (num % 7 == 0)) { printf(" %d 能同时被 3 和 7 整除\n",num); } else { printf(" %d 不能同时被 3 和 7 整除\n", num); } } int main(int argc, char* argv[]) { function(); return 0; }
打印效果如下:
或者
switch选择语句
switch(表达式){
case 值1:
语句1;
break;
case 值2:
语句2;
break;
case 值3:
语句3;
break;
//……
//一共 n 个
//……
default:
语句n;
break;
}
注意:switch
中的值不能是浮点型,只能是整型或者字符型,default可以省略,大部分 case
语句都会跟上 break
;
整型示例如下:
void function() {
int num = 0;
printf(" 请输入一个整数:");
scanf_s("%d", &num);
switch (num % 3) {
case 1:
printf(" %d 对 3 的余数是 1\n",num);
break;
case 2:
printf(" %d 对 3 的余数是 2\n",num);
break;
default:
printf(" %d 对 3 的余数是 0\n", num);
break;
}
}
int main(int argc, char* argv[]) {
function();
return 0;
}
打印效果如下:
字符型示例如下:
void function() {
char ch = 0;
printf(" 请输入一个方向(wsad):");
//ch = getchar();
scanf_s("%c", &ch);
//按键不会区分大小写,所以代码如下
switch (ch) {
case 'w':
case 'W':
printf(" 你正在前进!\n");
break;
case 's':
case 'S':
printf(" 你正在退后!\n");
break;
case 'a':
case 'A':
printf(" 你正在左转!\n");
break;
case 'd':
case 'D':
printf(" 你正在右转!\n");
break;
}
}
int main(int argc, char* argv[]) {
function();
return 0;
}
打印效果如下:
案例:键盘输入 1-7 的数,用switch判断今天是星期几;
void function() {
int num = 0;
printf(" 这是一个判断星期的程序,请输入一个整数:");
scanf_s("%d", &num);
switch (num) {
case 1:
printf(" 星期一\n");
break;
case 2:
printf(" 星期二\n");
break;
case 3:
printf(" 星期三\n");
break;
case 4:
printf(" 星期四\n");
break;
case 5:
printf(" 星期五\n");
break;
case 6:
printf(" 星期六\n");
break;
case 7:
printf(" 星期天\n");
break;
default:
printf(" 输入超范围!\n");
break;
}
}
int main(int argc, char* argv[]) {
function();
return 0;
}
打印效果如下:
for循环语句
for(初始语句 ; 循环条件 ; 步进条件){
循环语句;
}
公式讲解:
f
o
r
循环
{
初始语句:只在循环开始时执行一次
循环条件:每一次循环都要执行,循环条件为真,进入循环体,否则退出循环体
步进语句:每次循环结束后,要执行的语句
for\bf{循环}\begin{cases} \bf{初始语句:只在循环开始时执行一次} \\ \bf{循环条件:每一次循环都要执行,循环条件为真,进入循环体,否则退出循环体}\\\bf{步进语句:每次循环结束后,要执行的语句} \end{cases}
for循环⎩
⎨
⎧初始语句:只在循环开始时执行一次循环条件:每一次循环都要执行,循环条件为真,进入循环体,否则退出循环体步进语句:每次循环结束后,要执行的语句
内部运行图示:
案例:求 1-100
的和;
void method() {
int num = 0;
int i = 0;
for (i = 1; i <= 100; i++) {
num += i;
}
printf(" 1 到 100 的和为 %d", num);
}
int main(int argc, char* argv[]) {
method();
return 0;
}
打印效果如下:
案例:求 1-10
的积;
void method() {
int num = 1;
int i = 1;
for (i = 1; i <= 10; i++) {
num *= i;
}
printf(" 1 到 10 的积为 %d\n", num);
}
int main(int argc, char* argv[]) {
method();
return 0;
}
打印效果如下:
注意:如果变量提前初始化了,那么for循环里面的初始语句可以省略;如果循环语句中实现了步进条件,则步进条件也可以省略;如果循环中设置过退出循环的条件,for循环里面的循环条件也可以省略。
示例如下:
void method() {
int num = 0;
int i = 1;//在 for 循环外初始化
for (;;) {
if (i > 100) {
break;//跳出循环
}
num += i;
i++;
}
printf(" 1 到 100 的和为 %d\n", num);
}
int main(int argc, char* argv[]) {
method();
return 0;
}
打印效果如下:
-
break:
break只能跳出离它最近的循环;
void method() { for (;;) { //for1 for (;;) { //for2 break; //break只能跳出离它最近的循环,即 for2 } } } int main(int argc, char* argv[]) { method(); return 0; }
-
continue
结束当前循环,立刻从当前位置进入下一次循环;
void method() { int i = 0; int sum = 0; for (i = 1 ; i <= 100; i++) { if (i == 50) { continue; //结束本次循环,立即从当前位置直接进入下一次循环 } sum += i; } printf("sum = %d\n", sum); } int main(int argc, char* argv[]) { method(); return 0; }
打印效果如下:
-
案例:求出
1-100
中能被7
整除的数;void method() { int num = 0; int i = 0; /*for (i = 1; i <= 100; i++) { if (i % 7 != 0) { continue; }*/ if (i % 7 == 0) { printf(" %2d 能被 7 整除\n",i); } } } int main(int argc, char* argv[]) { method(); return 0; }
打印效果如下:
-
案例:求出
0-100
中所有偶数的和;void method() { int num = 0; int i = 0; for (; i <= 100; i++) { if (i % 2 == 0) { num += i; } } printf(" 0 - 100 中所有偶数的和为 %d\n", num); } int main(int argc, char* argv[]) { method(); return 0; }
打印效果如下:
-
补充:循环嵌套循环(99乘法表);
void method() { int i = 0; int j = 0; for (i = 1; i < 10; i++) { for (j = 1; j < i+1; j++) { printf("%d * %d = %2d ", j, i, i * j); } printf("\n"); } } int main(int argc, char* argv[]) { method(); return 0; }
打印效果如下:
while循环
-
while循环
while(循环条件){ 循环语句; }
如果循环条件为真,就进入循环体,并且执行循环语句;
注意:
while没有初始化语句,所以我们应该提前设置好;
while没有步进条件,所以我们需要再循环语句中写好步进语句;
案例:
求
1-100
的和;void method() { int num = 0; int i = 1; while (i <= 100) { num += i; i++; } printf("1 - 100 的和为 %d\n", num); } int main(int argc, char* argv[]) { method(); return 0; }
打印效果如下:
求
1-10
的积;void method() { int num = 1; int i = 1; while (i <= 10) { num *= i; i++; } printf("1 - 10 的积为 %d\n", num); } int main(int argc, char* argv[]) { method(); return 0; }
打印效果如下:
求出
1-100
中能被7
整除的数;void method() { int i = 1; while (i <= 100) { if (i % 7 == 0) { printf(" %2d 能被 7 整除\n",i); } i++; } } int main(int argc, char* argv[]) { method(); return 0; }
打印效果如下:
求出
0-100
中所有偶数的和;void method() { int num = 0; int i = 1; while (i <= 100) { if (i % 2 == 0) { num += i; } i++; } printf(" 0 - 100 中所有偶数的和 %d\n", num); } int main(int argc, char* argv[]) { method(); return 0; }
打印效果如下:
-
do……while()循环(相对于 while , do……while() 不常用)
do{ 循环语句; } while(循环条件);
先执行循环语句,再判断循环条件是否为真,进行下次循环,否则直接退出循环;
示例如下 :
void method() { int num = 3; do { printf("ok!"); } while (num < 0); //如果这里用 while ,“ok!”是不会打印出来的 } int main(int argc, char* argv[]) { method(); return 0; }
打印效果如下:
-
goto跳转
void method() { printf("------001------\n"); printf("------002------\n"); printf("------003------\n"); goto position;//这里是分号 printf("------004------\n"); printf("------005------\n"); printf("------006------\n"); printf("------007------\n"); position://这里是冒号 printf("------008------\n"); printf("------009------\n"); } int main(int argc, char* argv[]) { method(); return 0; }
打印效果如下:
能看出:
goto
所包含的一部分没有被打印出来;案例:重复输入 1-7 的数字判断星期,输入 0 时结束程序,其他的数请提示“请重新输入有效数字”
void method() { int num = 0; int i = 0; for (i = 1; i > 0;) { printf("请输入一个整数(0-7)判断日期,输入零结束程序:"); scanf_s("%d", &num); if (num == 1) { printf("星期一!\n"); } else if (num == 2) { printf("星期二!\n"); } else if (num == 3) { printf("星期三!\n"); } else if (num == 4) { printf("星期四!\n"); } else if (num == 5) { printf("星期五!\n"); } else if (num == 6) { printf("星期六!\n"); } else if (num == 7) { printf("星期天!\n"); } else if (num == 0) { i -= 1; printf("程序已退出!\n"); } else { printf("请重新输入有效数字!\n"); } } } int main(int argc, char* argv[]) { method(); return 0; }
打印效果如下:
总结
-
for 和 while 我们如何选择?
如果循环的次数是确定的,建议用
for
;如果循环的次数不确定,只知道退出的条件,建议用
while
;