【C】C系列四 - 流程控制

流程控制在开发中必然会用到,其实高中数学也会讲流程控制,但仅仅是初级阶段。

一、流程控制

按照执行流程的不同,可以将平时编写的代码分为 3 大结构:

  • 顺序结构:默认的流程结构,按照代码的书写顺序执行每一句代码
  • 选择结构:根据表达式的真假性,决定执行哪一段代码
  • 循环结构:在表达式为真的情况下,重复执行某一段代码

1.1. 顺序结构

无论执行多少次main函数,打印结果都是顺序执行:1234

1
2
3
4
5
6
7
int main() {
printf("1");
printf("2");
printf("3");
printf("4");
return 0;
}

1.2. 选择结构

  • if语句
  • if-else语句
  • else if语句
  • switch语句

1.3. 循环结构

  • while语句
  • do-while语句
  • for语句

二、选择结构

2.1. if 语句

格式:

1
2
3
4
5
6
7
代码1;

if (表达式) {
代码2;
}

代码3;

特点:

  • 如果表达式为假,不会执行大括号中的代码 2;
  • 如果表达式为真,就会执行大括号中的代码 2。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
printf("请输入本次考试成绩:");
int score;
scanf("%d", &score);

if (score >= 80) {
printf("表现优秀\n");
}

printf("加油\n");
/*
输入:请输入本次考试成绩:30
输出:
加油

输入:请输入本次考试成绩:90
输出:
表现优秀
加油
*/

2.2. if-else 语句

格式:

1
2
3
4
5
6
7
8
9
代码1;

if (表达式) {
代码2;
} else {
代码3;
}

代码4;

特点:

  • 如果表达式为真,就会执行代码 2,不会执行代码 3;
  • 如果表达式为假,就会执行代码 3,不会执行代码 1。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
printf("请输入本次考试成绩:");
int score;
scanf("%d", &score);

if (score >= 80) {
printf("表现优秀\n");
} else {
printf("再接再厉\n");
}

printf("加油\n");
/*
输入:请输入本次考试成绩:30
输出:
再接再厉
加油

输入:请输入本次考试成绩:90
输出:
表现优秀
加油
*/

2.3. if 语句 和 if-else 语句

案例一:

1
2
3
4
5
6
7
int score = 80;
if (score >= 80) {
printf("表现优秀");
} else {
printf("再接再厉");
}
// 输出:表现优秀

案例二:

1
2
3
4
5
6
7
8
int score = 80;
if (score >= 80) {
printf("表现优秀");
}
if (score < 80) {
printf("再接再厉");
}
// 输出:再接再厉
  • 案例一的代码更简洁,省掉了不必要的判断(案例二的score < 80);
  • 案例一的代码执行效率更高,只需要进行 1 次表达式判断;
  • 案例二的代码需要进行 2 次表达式判断;
    • score >= 80
    • score < 80
  • 所以推荐使用案例一。

2.4. else if 语句

格式:

1
2
3
4
5
6
7
8
9
10
11
if (表达式1) {
代码1;
} else if (表达式2) {
代码2;
} else if (表达式3) {
代码3;
} else {
代码4;
}

代码5;
  • 表达式对应的大括号代码是一一对应的,如果表达式成立,就执行大括号中的代码(不会再判断后面的表达式),否则进入下一个表达式判断;
  • 应该把小范围写在前面,大范围写在后面,否则就永远不会进入后面的表达式判断。

案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int score = 80;
if (score >= 90) {
printf("优\n");
} else if (score >= 80) {
printf("良\n");
} else if (score >= 60) {
printf("中\n");
} else {
printf("差\n");
}
// 输出:良

// 下面的代码永远不会进入score >= 80和score >= 90
if (score >= 60) {
printf("中\n");
} else if (score >= 80) {
printf("良\n");
} else if (score >= 90) {
printf("优\n");
} else {
printf("差\n");
}
// 输出:中

2.5. if 语句 和 else if 语句

案例一:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int score = 80;
if (score >= 90) { // 范围:[90, +∞)
printf("优\n");
} else if (score >= 80) { // 范围:[80, 90)
printf("良\n");
} else if (score >= 60) { // 范围:[60, 80)
printf("中\n");
} else { // 范围:(-∞, 60)
printf("差\n");
}
/*
输出:良
分析:
1.判断score >= 90,不符合条件(即条件为假),进入下一个判断
2.判断score >= 80,符合条件(即条件为真),输出:良,不再执行该流程结构(即其他条件不再判断)
*/

案例二:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int score = 80;
if (score >= 90) { // 范围:[90, +∞)
printf("优\n");
}
if (score >= 80) { // 范围:[80, +∞)
printf("良\n");
}
if (score >= 60) { // 范围:[60, +∞)
printf("中\n");
}
if (score < 60) { // 范围:(-∞, 60)
printf("差\n");
}
/*
输出:良 中
分析:
1.判断score >= 90,不符合条件(即条件为假),顺序执行代码

2.判断score >= 80,符合条件(即条件为真),输出:良,顺序执行代码

3.判断score >= 60,符合条件(即条件为真),输出:中,顺序执行代码

4.判断score < 60,不符合条件(即条件为假),顺序执行代码
*/

案例三:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
int num = 0;
scanf("%d", &num);
if (num > 0) {
printf("正数\n");
} else if (num == 0) {
printf("自然数\n");
} else {
printf("负数\n");
}
if (num & 1) {
printf("奇数\n");
} else {
printf("偶数\n");
}
/*
输入:8
输出:
正数
偶数

输入:11
输出:
正数
奇数

输入:-12
输出:
负数
偶数

输入:0
输出:
自然数
偶数
*/

三个案例比较后发现,如果判断体是互斥且单一的,用else if,如果需要多个判断体验证多套逻辑,就用if

2.6. 表达式的等价性

案例一:

1
2
3
4
5
6
7
int score = 90;
if (90 <=score && score <= 100) {
printf("优秀");
} else {
printf("其他");
}
// 输出:优秀

案例二:

1
2
3
4
5
6
7
int score = 90;
if (!(90 <=score && score <= 100)) {
printf("其他");
} else {
printf("优秀");
}
// 输出:优秀

案例三:

1
2
3
4
5
6
7
int score = 90;
if (score < 90 || score > 100) {
printf("其他");
} else {
printf("优秀");
}
// 输出:优秀

以上三个案例都是等价的

2.7. if 语句-省略大括号

ifelse后可以省略大括号,只会跟其后的第一条语句进行关联。

案例一:

1
2
3
4
5
int score = 90;
if (score >= 90)
printf("优\n");
printf("加油");
// 输出:优 加油

案例一等价写法:

1
2
3
4
5
6
int score = 90;
if (score >= 90) {
printf("优\n");
}
printf("加油");
// 输出:优 加油

案例二:

1
2
3
4
5
6
7
int score = 80;
if (score >= 90)
printf("优\n");
else
printf("其他\n");
printf("加油");
// 输出:其他 加油

案例二等价写法:

1
2
3
4
5
6
7
8
int score = 80;
if (score >= 90) {
printf("优\n");
} else {
printf("其他\n");
}
printf("加油");
// 输出:其他 加油

多个if-else一起使用的时候,else后会跟其前面最接近的if相关联

案例一:

1
2
3
4
5
6
7
8
int a = 10;
int b = 5;
if (a > 0)
if (b > 2)
printf("1");
else
printf("2");
// 输出:1

案例一等价写法:

1
2
3
4
5
6
7
8
9
10
int a = 10;
int b = 5;
if (a > 0) {
if (b > 2) {
printf("1");
} else {
printf("2");
}
}
// 输出:1

编译错误案例:
案例一:

1
2
3
4
5
6
int score = 90;
if (score >= 90)
printf("优\n");
printf("666\n");
else
printf("再接再厉\n");

案例一等价拆解:

1
2
3
4
5
6
7
8
int score = 90;
if (score >= 90) {
printf("优\n");
}
printf("666\n");
else {
printf("再接再厉\n");
}

2.8. 注意点

案例一:

1
2
3
4
5
int a = 10;
if (a > 0); {
printf("%d", a);
}
// 输出:10

案例一分析:if 条件判断后面是一个空实现体,分号代表了 if 结构的结束,所以后面的大括号和 if 没有任何关系

案例二:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int a = 10;
if (a = 1) {
printf("%d", a);
}
// 输出:1

// 等价拆解
int a = 10;
a = 1;
if (a) {
printf("%d", a);
}
// 输出:1

// 正确做法
int a = 10;
if (1 == a) {
printf("%d", a);
}
// 输出:

案例二分析:不管 a 的原始值是多少,都会打印 a 的值,因为条件表达式里面是赋值操作而不是逻辑判断,相当于先给 a 赋值,再判断 a 是否等于 0。所以在开发中一般建议把数值写在左边,变量写在右边,如果这样,即使错把==写成了=,在代码编写及编译阶段就会报错。


2.9. if-else 语句和条件运算符

一些简单的if-else语句可以使用条件运算符来替代,这样能够使代码更简洁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int score = 60;
if (score >= 90) {
printf("优\n");
} else {
printf("差\n");
}
// 输出:差

// 使用条件运算符
// 写法一:
score >= 90 ? printf("优\n") : printf("差\n");
// 输出:差

// 写法二:
printf(score >= 90 ? "优\n" : "差\n");
// 输出:差

稍微复杂的代码就不能用条件运算符了:

1
2
3
4
5
6
7
8
9
int score = 60;
if (score >= 90) {
printf("优\n");
} else {
int a = 10;
int b = 20 + a;
printf("差 - %d\n", a + b);
}
// 输出:差 - 40

2.10. switch 语句

格式:

1
2
3
4
5
6
7
8
9
10
11
switch (表达式) {
case 表达式1:
代码1;
break;
case 表达式2:
代码2;
break;
default:
代码3;
break;
}

switch 语句用 if 语句表示:

1
2
3
4
5
6
7
if (表达式 == 表达式1) {
代码1;
} else if (表达式 == 表达式2) {
代码2;
} else {
代码3;
}

特点:

  • 可以没有default语句;
  • 表达式、表达式 1、表达式 2 都必须是整形表达式;
  • 表达式 1、表达式 2 都必须是常量表达式;
  • case中的表达式不能重复,并且不能带有变量。

案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
char score = 'C';
switch (score) {
case 'A':
printf("优");
break;

case 'B':
printf("良");
break;

case 'C':
printf("中");
break;

default:
printf("差");
break;
}
// 输出:中

// 等价if语句的写法
if (score == 'A') {
printf("优");
} else if (score == 'B') {
printf("良");
} else if (score == 'C') {
printf("中");
} else {
printf("差");
}
// 输出:中

case表达式后面如果没有声明新的变量,大括号可加可不加。如果想在case表达式后面声明新的变量,那就必须加上大括号,否则编译出错。

案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
char score = 'C';
switch (score) {
case 'A': {
printf("优");
break;
}

case 'B': {
int a = 10;
printf("良");
break;
}

case 'C':
printf("中");
break;

default: {
printf("差");
break;
}
}
// 输出:中

  • switch语句中,break语句的作用就是终止switch语句执行;

  • 如果casedefault后面没有break语句,会出现“贯穿”现象,会继续往下执行其他casedefault中的代码,直到遇到break语句或switch语句的结尾为止;

  • casedefault没有可以自由调换顺序。

案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
printf("请输入1~12的月份:");
int month;
scanf("%d", &month);
switch (month) {
case 3:
printf("3");
case 4:
printf("4");
case 5:
printf("5");
printf("春季");
break;

default:
printf("非法输入");
break;

case 6: case 7: case 8:
printf("夏季");
break;

case 9: case 10: case 11:
printf("秋季");
break;

case 12: case 1: case 2:
printf("冬季");
break;
}
/*
输入:3
输出:345春季

输入:4
输出:45春季

输入:11
输出:秋季

输入:13
输出:非法输入
*/

ifswitch相互替代

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
int num = 0;
scanf("%d", &num);
if (num > 0) {
printf("正数");
} else if (num < 0) {
printf("负数");
} else {
printf("0");
}
/*
输入:11
输出:正数

输入:-9
输出:负数

输入:0
输出:0
*/

// 等价写法
switch (num > 0) {
case 1:
printf("正数");
break;

default:
switch (num < 0) {
case 1:
printf("负数");
break;

default:
printf("0");
break;
}
break;
}
/*
输入:11
输出:正数

输入:-9
输出:负数

输入:0
输出:0
*/

思考:什么时候用if,什么时候用switch? 当表示一个范围时,使用if,当判断一个变量是否等于固定值时,两者都可以,但只要switch能表达的,必然都可以用if

三、循环结构

循环结构包括:

  • while语句
  • do-while语句
  • for语句

3.1. while 语句

格式:

1
2
3
4
while (表达式) {
循环体;
}
代码1;

while语句也叫while循环,while语句大括号中的代码,称为循环体。

特点:

  • 如果表达式为假,不会执行循环体,直接终止while语句;
  • 如果表达式为真,执行循环体;
  • 执行完循环体后,会再次回到第一步,根据表达式的真假来做出选择;
  • while语句执行完成后,才会继续往下执行代码 1,否则将会一直循环,直到循环结束。

案例一:(输入正整数 n,使用while语句依次打印区间[1, n]的整数)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// 方法一:
printf("请输入一个正整数:");
int times = 1, num = 1;
scanf("%d", &num);
while (times <= num) {
printf("%d\n", times);
times++;
}
printf("完成");
/*
输入:5
输出:
1
2
3
4
5
完成
*/

// 方法二:
printf("请输入一个正整数:");
int times = 1, num = 1;
scanf("%d", &num);
while (times++ <= num) {
printf("%d\n", times-1);
}
printf("完成");
/*
输入:5
输出:
1
2
3
4
5
完成
*/

// 方法三:
printf("请输入一个正整数:");
int times = 1, num = 1;
scanf("%d", &num);
while (++times <= num+1) {
printf("%d\n", times-1);
}
printf("完成");
/*
输入:5
输出:
1
2
3
4
5
完成
*/

// 方法四……(方法有很多,不再举例)

案例二:(输入一个 1 ~ 100 之间的正整数 n,求 1~n 之间的整数相加结果)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int n = 0;
while (n < 1 || 100 < n) {
printf("请输入1~100之间的整数:");
scanf("%d", &n);
}

int times = 1, sum = 0;
while (times <= n) {
sum += times;
printf("times:%d\n", times); // 打印每次相加的值看起来更明显
times++;
}
printf("结果:%d\n", sum);
/*
输入:5
输出:
times:1
times:2
times:3
times:4
times:5
结果:15
*/

案例二延伸:(求 1~n 之间奇数相加,偶数相减的结果)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int n = 0;
while (n < 1 || 100 < n) {
printf("请输入1~100之间的整数:");
scanf("%d", &n);
}

int times = 1, sum = 0;
while (times <= n) {
sum += (times & 1) ? times : -times;
printf("times:%d\n", times); // 打印每次相加的值看起来更明显
times++;
}
printf("结果:%d\n", sum);
/*
输入:5
输出:
times:1
times:2
times:3
times:4
times:5
结果:3
*/

案例二延伸:(求 1~n 之间奇数相加的结果)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
int n = 0;
while (n < 1 || 100 < n) {
printf("请输入1~100之间的整数:");
scanf("%d", &n);
}

int times = 1, sum = 0;
while (times <= n) {
sum += (times & 1) ? times : 0;
printf("times:%d\n", times); // 打印每次相加的值看起来更明显
times++;
}
printf("结果:%d\n", sum);
/*
输入:5
输出:
times:1
times:2
times:3
times:4
times:5
结果:9
*/

/*
优化版本:
上面的做法循环体会执行n次,其实没必要,这样比较浪费性能。如果把偶数直接在外面过滤掉就会好很多。
*/
int n = 0;
while (n < 1 || 100 < n) {
printf("请输入1~100之间的整数:");
scanf("%d", &n);
}

int times = 1, sum = 0;
while (times <= n) {
sum += times;
printf("times:%d\n", times); // 打印每次相加的值看起来更明显
times += 2;
}
printf("结果:%d\n", sum);
/*
输入:5
输出:
times:1
times:3
times:5
结果:9
*/

3.2. for 语句

格式:

1
2
3
4
for (代码1; 表达式; 代码2) {
循环体;
}
代码3;

for语句也叫for循环,for语句大括号中的代码,称为循环体。

特点:

  • 无论表达式是真还是假,都会先执行代码 1;
  • 如果表达式为假,不会执行循环体、代码 2,直接终止for语句;
  • 如果表达式为真,依次执行循环体、代码 2;
  • 执行完循环体后,会再次回到第二步,根据表达式的真假来做出选择;
  • for语句执行完成后,才会继续往下执行代码 3,否则将会一直循环,直到循环结束。

注意点:

  • 代码 2 后面不能加分号(;);
  • 无论表达式是真是假,都会在第一次执行代码 1,并且在 for 语句后面的执行过程中,都不会在执行代码 1。

3.3. for 语句和 while 语句比较

1
2
3
4
5
6
7
8
9
10
for (代码1; 表达式; 代码3) {
代码2;
}

// 等价while
代码1;
while (表达式) {
代码2;
代码3;
}

案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
for (int i = 1; i <= 5; i++) {
printf("%d\n", i);
}
/*
输出:
1
2
3
4
5
*/

// while语句
int i = 1;
while (i <= 5) {
printf("%d\n", i);
i++;
}
/*
输出:
1
2
3
4
5
*/

根据代码的执行顺序我们可以得出下面的结论:

  • 表达式后面的代码可以拿出来
1
2
3
4
5
6
7
8
9
10
11
12
for (int i = 1; i <= 5;) {
printf("%d\n", i);
i++;
}
/*
输出:
1
2
3
4
5
*/
  • 表达式后面可以使用逗号运算符
1
2
3
4
5
6
7
8
9
10
11
for (int i = 1; i <= 5; printf("%d\n", i), i++) {

}
/*
输出:
1
2
3
4
5
*/
  • 表达式前面声明变量时可以同时声明多个变量
1
2
3
4
5
6
7
8
9
10
11
for (int i = 1, j = 0; i <= 5; i++, j += 1) {
printf("i:%d - j:%d\n", i, j);
}
/*
输出:
i:1 - j:0
i:2 - j:1
i:3 - j:2
i:4 - j:3
i:5 - j:4
*/
  • 表达式前后的分号不能省略
1
2
3
4
5
6
7
8
9
10
11
12
13
int i = 1;
for (; i <= 5; ) {
printf("%d\n", i);
i++;
}
/*
输出:
1
2
3
4
5
*/

案例:(输入一个 1 ~ 100 之间的正整数 n,求 1~n 之间的整数相加结果)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int n = 0;
for (; n < 1 || 100 < n;) {
printf("请输入1~100之间的整数:");
scanf("%d", &n);
}

int sum = 0;
for (int i = 1; i <= n; i++) {
printf("i:%d\n", i); // 打印每次相加的值看起来更明显
sum += i;
}
printf("结果:%d\n", sum);
/*
输入:5
输出:
i:1
i:2
i:3
i:4
i:5
结果:15
*/

上面的案例可以看出,while循环写出的代码一定可以用for循环实现。只是有时候while写出的代码可能会更加简洁,在实际开发过程中应根据业务场景选择更合适的循环语句。

3.4. do-while 语句

格式:

1
2
3
do {
循环体;
} while (表达式);

特点:

  • 无论表达式是真是假,先执行一次循环体;
  • 如果表达式为假,不会执行循环体,直接终止while语句;
  • 如果表达式为真,就会执行循环体;
  • 执行完循环体后,会再次回到第二步根据表达式的真假来做出选择。

注意点:

  • while表达式后面一定要加分号(;);
  • 无论表达式真假,都会在开头先执行一次循环体。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
int i;
scanf("%d", &i);
do {
printf("%d", i);
i++;
} while (i <= 5);
/*
输入:1
输出:12345

输入:6
输出:6
*/

// while语句
while (i <= 5) {
printf("%d", i);
i++;
}
/*
输入:1
输出:12345

输入:6
输出:
*/

// for语句
for (; i <= 5;) {
printf("%d", i);
i++;
}
/*
输入:1
输出:12345

输入:6
输出:
*/

总结:很多时候,使用whiledo-whilefor可以完成一样的功能,只是书写格式不一样。

案例一:
(场景:提示输入一个 1 ~ 100 之间的正整数 n,如果输入错误,要求重新输入,直到输入正确为止)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int n;
do {
printf("请输入一个1~100之间的正整数:");
scanf("%d", &n);
} while (n < 1 || n > 100);
printf("输入正确:%d", n);
/*
输入:-10
输出:请输入一个1~100之间的正整数:

输入:102
输出:请输入一个1~100之间的正整数:

输入:20
输出:输入正确:20
*/

案例一对比:(使用while语句比较)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int n = 0;
while (n < 1 || n > 100) {
printf("请输入一个1~100之间的正整数:");
scanf("%d", &n);
}
printf("输入正确:%d", n);
/*
输入:-10
输出:请输入一个1~100之间的正整数:

输入:102
输出:请输入一个1~100之间的正整数:

输入:20
输出:输入正确:20
*/

总结:对比while语句发现,do-while语句会少一次最初没有必要的判断,因为不论表达式真假,都会先执行一次循环体。

3.5. 循环嵌套

场景一:严格要求输入一个 1~20 之间的正整数 n,输入 n 行 n 列的图形,图形用#表示。

图示:

1
2
3
4
5
6
请输入一个1~20之间的正整数:5
#####
#####
#####
#####
#####

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int n;
do {
printf("请输入一个1~20之间的正整数:");
scanf("%d", &n);
} while (n < 1 || n > 20);

for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
printf("#");
}
printf("\n");
}
/*
输入:5
输出:
#####
#####
#####
#####
#####
*/

场景二:严格要求输入一个 1~20 之间的正整数 n,输入 n 行 n 列的图形,图形用#表示。

图示:

1
2
3
4
5
6
请输入一个1~20之间的正整数:5
#
##
###
####
#####

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int n;
do {
printf("请输入一个1~20之间的正整数:");
scanf("%d", &n);
} while (n < 1 || n > 20);

for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
printf("#");
}
printf("\n");
}
/*
输入:5
输出:
#
##
###
####
#####
*/

场景三:严格要求输入一个 1~20 之间的正整数 n,输入 n 行 n 列的图形,图形用#表示。

图示:

1
2
3
4
5
6
请输入一个1~20之间的正整数:5
#####
####
###
##
#

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
int n;
do {
printf("请输入一个1~20之间的正整数:");
scanf("%d", &n);
} while (n < 1 || n > 20);

// 方法一:
for (int i = 1; i <= n; i++) {
for (int j = i; j <= n; j++) {
printf("#");
}
printf("\n");
}
/*
输入:5
输出:
#####
####
###
##
#
*/

// 方法二:
for (int i = 1; i <= n; i++) {
for (int j = n; j >= i; j--) {
printf("#");
}
printf("\n");
}
/*
输入:5
输出:
#####
####
###
##
#
*/

场景四:严格要求输入一个 1~20 之间的正整数 n,输入 n 行 n 列的图形,图形用#表示。

图示:

1
2
3
4
5
6
请输入一个1~20之间的正整数:5
#####
$$$$$
#####
$$$$$
#####

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int n;
do {
printf("请输入一个1~20之间的正整数:");
scanf("%d", &n);
} while (n < 1 || n > 20);

for (int i = 1; i <= n; i++) {
char c = (i & 1) ? '#' : '$';
for (int j = 1; j <= n; j++) {
printf("%c", c);
}
printf("\n");
}
/*
输入:5
输出:
#####
$$$$$
#####
$$$$$
#####
*/

场景五:严格要求输入一个 1~20 之间的正整数 n,输入 n 行 n 列的图形,图形用#表示。

图示:

1
2
3
4
5
6
请输入一个1~20之间的正整数:5
#####
#$$$#
#$$$#
#$$$#
#####

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
int n;
do {
printf("请输入一个1~20之间的正整数:");
scanf("%d", &n);
} while (n < 1 || n > 20);

for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
char c;
if (i == 1 || i == n || j == 1 || j == n) {
c = '#';
} else {
c = '$';
}
printf("%c", c);
}
printf("\n");
}
/*
输入:5
输出:
#####
#$$$#
#$$$#
#$$$#
#####
*/

场景六:输出九九乘法表

图示:

1
2
3
4
5
1x1=1
1x2=2 2x2=4
1x3-3 2x3=6 3x3=9
……
1x9=9 2x9=18 …… 9x9=81

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; j++) {
printf("%dx%d=%d\t", i, j, i * j);
}
printf("\n");
}
/*
输出:
1x1=1
2x1=2 2x2=4
3x1=3 3x2=6 3x3=9
4x1=4 4x2=8 4x3=12 4x4=16
5x1=5 5x2=10 5x3=15 5x4=20 5x5=25
6x1=6 6x2=12 6x3=18 6x4=24 6x5=30 6x6=36
7x1=7 7x2=14 7x3=21 7x4=28 7x5=35 7x6=42 7x7=49
8x1=8 8x2=16 8x3=24 8x4=32 8x5=40 8x6=48 8x7=56 8x8=64
9x1=9 9x2=18 9x3=27 9x4=36 9x5=45 9x6=54 9x7=63 9x8=72 9x9=81
*/

3.6. break 语句

break语句只用在whiledo-whileforswitch语句中,它的作用就是终止并跳出所在的循环语句。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
for (int i = 1; i <= 5; i++) {
if (i == 4) break;
for (int j = 1; j <= 5; j++) {
if (j == 3) break;
printf("#");
}
printf("\n");
}
printf("end");
/*
输出:
##
##
##
end
*/

3.7. continue 语句

continue语句只用在whiledo-whilefor语句中,它的作用是跳过所在循环语句的循环体剩余部分

示例:

1
2
3
4
5
for (int i = 1; i <= 5; i++) {
if (i == 3) continue;
printf("%c", (i & 1) ? '#' : '$');
}
// 输出:#$$#

3.8. goto 语句

goto语句的作用:可以为所欲为地灵活跳转

示例:

1
2
3
4
5
6
7
8
9
int n = 1;
code:
printf("#");
n++;
if (n <= 5) {
printf("%d", n);
goto code;
}
// 输出:#2#3#4#5#

goto语句使用起来非常灵活,在一定情况下,可以提高程序的效率,但是他破坏了结构化的设计风格,容易造成代码执行流程的混乱(一般情况下,代码的执行顺序是从上到下),导致代码难以调试和维护。所以非常不建议使用goto语句(这也是在开发中几乎看不到goto语句的原因)。