C语言 | 2.循环语句

https://prong-1316442664.cos.ap-nanjing.myqcloud.com/picgo/202301142359877.webp

循环语句

[toc]

while循环

1
2
3
4
5
6
7
8
9
10
11
int main()
{
int i = 0;//初始化

while (i <= 10)//判断部分
{
printf("%d ", i);
i++;//调整部分
}
return 0;
}

break

用于永久的终止循环

continue

满足条件就跳出本次循环,直接去while判断,进行下一次循环
往往弄成死循环


案例

  • EOF
    文件结束标志End of file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//getchar读取键盘输入的字符

int main()
{
int ch = 0;
//ctrl+z getchar就读取结束

while ((ch = getchar()) != EOF)
{
putchar(ch);
}

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int main()
{
char password[20] = { 0 };
printf("请输入密码->");
scanf("%s", password);//数组本身就是地址所以不用加&引用
printf("请确认密码(Y/N)->");
int ch = getchar();

if (ch == 'Y')
{
printf("确认成功\n");
}
else
{
printf("确认失败\n");
}
return 0;
}

会失败,因为getchar、scanf从缓冲区取东西,输入密码后sacnf把123456拿走,剩下\n被getchar拿走,而\n不符合条件

修改版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int main()
{
char password[20] = { 0 };
printf("请输入密码->");
scanf("%s", password);//数组本身就是地址所以不用加&引用
printf("请确认密码(Y/N)->");

getchar();//清理缓冲区

int ch = getchar();

if (ch == 'Y')
{
printf("确认成功\n");
}
else
{
printf("确认失败\n");
}
return 0;
}

还有一点小问题,例如输入 123456abc123456 abc 这样的密码,scanf取走了123456,但是后面的字符还在缓冲区中,需要设计取走缓存区中的多个字符

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
int main()
{
char password[20] = { 0 };
printf("请输入密码->");
scanf("%s", password);//数组本身就是地址所以不用加&引用
printf("请确认密码(Y/N)->");

int tmp = 0;
while ((tmp = getchar()) != '\n')
{
;
}
//清理缓冲区的多个字符

int ch = getchar();

if (ch == 'Y')
{
printf("确认成功\n");
}
else
{
printf("确认失败\n");
}
return 0;
}

for循环

解决while写太长不方便调整的问题
语法

1
2
for(表达式1; 表达式2; 表达式3)
循环语句;
1
2
3
4
5
6
7
8
9
10
11
int main()
{
int i = 1;
for (i = 1; i<=10; i++)
//第一个表达式是初始化,第二个表达式是判断部分,第三个是调整部分
//不论循环多少次,初始化只有一次
{
printf("%d ", i)
}
return 0;
}

案例

  • break
  • continue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//输出1~4,6~10的整数
int main()
{
int i = 1;
for (i = 1; i<=10; i++)
//第一个表达式是初始化,第二个表达式是判断部分,第三个是调整部分
//不论循环多少次,初始化只有一次
{
if (i == 5)
{
continue;
}
printf("%d ", i);
}
return 0;
}

建议:

  1. 不可在for循环体内修改循环变量,防止for循环失去控制
  2. 建议for语句的循环控制变量的取值采用“左闭右开区间”

变种

1
2
3
4
5
6
7
8
int main()
{
for (;;)
{
printf("傻逼\n");
}
return 0;
}

判断部分不能省,不然会变成死循环

1
2
3
4
5
6
7
8
9
10
11
12
13
int main()
{
int i = 0;
int j = 0;
for (; i<3; i++)
{
for (; j < 3; j++)
{
printf("SB\n")
}
}
return 0;
}

会输出3个SB

1
2
3
4
5
6
7
8
9
10
11
12

//经典面试题
int main()
{
int i = 0;
int k = 0;
for (i = 0, k = 0; k = 0; i++, k++)
{
k++;
}
return 0;
}

循环0次,因为表达式2不是判断式而是赋值k=0, 也就是k为假,直接就不满足条件跳出去了

do while循环

语法

1
2
3
do
循环语句
while(表达式);
1
2
3
4
5
6
7
8
9
10
11
12
13
//打印1~10
int main()
{
int i = 1;
do
{
pringtf("%d\n", i);
i++;
}
while (i<=10);

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int main()
{
int i = 0;

do
{
if (i == 5)
{
break;
//跳出循环,也就是跳到打印呵呵那里继续执行
}
printf("%d\n", i);
i++;
} while (i <= 10);
printf("呵呵");
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int main()
{
int i = 0;

do
{
if (i == 5)
{
continue;
//跳过后续循环语句,由于i++没执行而且还留在while里会一直死循环
}
printf("%d\n", i);
i++;
} while (i <= 10);

return 0;
}

案例

1. 计算n的阶乘

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//用for循环
int main()
{
int i = 0;
int n = 0;
int fac = 1;

scanf("%d", &n);

for (i = 1; i <= n; i++)
{
fac = fac * i;
}
printf("%d\n", fac);

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//while循环
int main()
{
int i = 1;
int n = 0;
int fac = 1;
printf("输入n的数值:");
scanf("%d", &n);

while (i <= n)
{
//fac = fac * i;
fac *= i;//更优雅
i++;
}

printf("%d\n", fac);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//do while循环
int main()
{
int i = 1;
int n = 0;
int fac = 1;

printf("输入n");
scanf("%d", &n);

do
{
fac = fac * i;
i++;
} while (i <= n);

printf("%d\n", fac);
return 0;
}

2. 计算1!+2!+3!+...+10!1!+2!+3!+...+10!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//常规做法
int main()
{
int i = 0;
int n = 0;
int j = 0;
int fac = 1;
int sum = 0;
scanf("%d", &j);
for (n = 1; n <= j; n++)
{
fac = 1;//非常关键,不然不能从1开始往后乘
for (i = 1; i <= n; i++)
{
fac *= i;
}
sum += fac;
}
printf("%d", sum);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//一个好思路,优化了算法
//相当于重复利用了前面计算的值
int main()
{
int i = 0;
int n = 0;
scanf("%d", &n);
int fac = 1;
int sum = 0;

for (i = 1; i <= n; i++)
{
fac *= i;
sum += fac;
}
printf("%d", sum);
return 0;
}

上面这个妙招的分析如下

i n fac sum
0 0
3 1 0
1 1 1
2 2 3
3 6 9

3. 从一个有序数组中查找某个具体的数字n

折半查找(二分法)的运用案例,复杂度是log2n\log_{2}{n}

以1~10这10个数字为例

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
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int k = 7;//要查找的数字
int sz = sizeof(arr) / sizeof(arr[0]);
//数组的大小除以数组中第一个元素的大小算出个数

int left = 0;//左下标
int right = sz - 1;//右下标

while (left <= right)
{
int mid = (left + right) / 2;
if (arr[mid] < k)//不在左边,在右边
{
left = mid + 1;
}
else if (arr[mid] > k)
{
right = mid - 1;
}
else
{
printf("找到啦:%d\n", mid);
break;
}
}
if (left > right)
{
printf("找不到\n");
}
return 0;
}
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
//for循环试一波
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int k = 7;
int sz = sizeof(arr) / sizeof(arr[0]);

int left = 0;
int right = sz - 1;
int mid = 1;

for (int left = 0, right = sz - 1; left <= right; mid = (left + right) / 2)
{
if (arr[mid] < k)
{
left = mid + 1;
}
else if (arr[mid] > k)
{
right = mid - 1;
}
else
{
printf("找到啦%d\n", mid);
break;
}
}
return 0;
}
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
//do while写法
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int k = 7;
int sz = sizeof(arr)/sizeof(arr[0]);

int left = 0;
int right = sz - 1;

do
{
int mid = (left + right)/2;
if (arr[mid] < k)
{
left = mid + 1;
}
else if (arr[mid] > k)
{
right = mid - 1;
}
else
{
printf("找到啦:%d\n", mid);
break;
}
}
while (left <= right);
return 0;
}

4. 编写代码,演示多个字符从两端移动,向中间汇聚

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
//打印welcome to the world!,但是字符从两端逐渐替换
#define _CRT_SECURE_NO_WARNINGS 1
//放在代码第一行,取消报错显示
#include <stdio.h>
#include <string.h>
#include <Windows.h>//Sleep的头文件
int main()
{
char arr1[] = "welcome to the world!";
char arr2[] = "#####################";
int left = 0;
int right = strlen(arr1) - 1;

do {
arr2[left] = arr1[left];
arr2[right] = arr1[right];
printf("%s\n", arr2);
Sleep(1000);//睡眠也就是延时
system("cls");//清空屏幕,让它咔咔自己动
left++;
right--;
} while (left <= right);
printf("%s\n", arr2);
return 0;
}

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
#include <string.h>
int main()
{
int i = 0;
char password[20] = { 0 };

for (i = 0; i <= 3; i++)
{
printf("请输入密码!");
scanf("%s", password);//字符串本身就是地址不用引用&
//不能用==直接比较字符串内容
if (strcmp(password, "123456") == 0)//strcmp比较字符串
{
printf("登陆成功\n");
break;
}
else
{
printf("密码错误,请重新输入!\n");
}
}
if (i == 3)
{
printf("三次密码输入错误,退出程序!\n");
}
return 0;
}
Value Relationship of string1 and string2
<0 string1 less than string2
=0 string1 indentical to string2
>0 string1 more than string2

6. 猜数字游戏

  1. 自动产生一个1~100之间的随机数
  2. 猜数字
    1. 猜对了,恭喜你,游戏结束
    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
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
60
61
62
63
64
65
66
67
#include <stdlib.h>//随机数rand的头文件
#include <time.h>

void menu()
{
printf("#########################\n");
printf("####### 1. play #######\n");
printf("####### 0. exit #######\n");
printf("#########################\n");
}

void game()//涉及随机数的使用
{
int ret = rand() % 10 + 1;//模10+1,得到的就是1-10范围的数字

int guess = 0;
while (1)
{
printf("guess!!!!");
scanf("%d", &guess);
system("cls");
if (guess < ret)
{
printf("smaller 了\n");
}
else if (guess > ret)
{
printf("bigger 了\n");
}
else
{
printf("对辣!!!\n");
break;
}
}
}


int main()
{
int input = 0;
//rand函数返回一个0-32767之间的数字
//srand函数设置随机起点,起点就是括号内的数
//要实现随机起点,可以利用时间戳(时间戳本质是把时间转换成一串数字)
srand((unsigned int)time(NULL));

do
{
menu();
printf("please select");
scanf("%d", &input);
system("cls");
switch (input)
{
case 1:
game();
break;
case 0:
printf("exit\n");
break;
default:
printf("wrong selection! try again\n");
break;
}
} while (input);
return 0;
}