while 循环
for 循环
do while 循环
while 循环 语法结构:
例题:在屏幕上打印 1~10
1 2 3 4 5 6 7 8 9 10 int main () { int a = 1 ; while (a<=10 ) { printf ("%d\n" , a); a++; } return 0 ; }
break的使用 以下代码会打印输出什么?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 int main () { int a = 1 ; while (a<=10 ) { if (a ==5 ) { break ; } printf ("%d\n" , a); a++; } return 0 ; }
答案:1 2 3 4
在while
循环中,break
用于永久终止循环
continue的使用 以下代码会打印输出什么?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 int main () { int a = 1 ; while (a<=10 ) { if (a ==5 ) { continue ; } printf ("%d\n" , a); a++; } return 0 ; }
答案:1 2 3 4 (之后不打印,死循环)
因为代码在a++
前就被continue
跳过了,a
的值一直保持在5,从而变成了一个死循环
在while
循环中,continue
的作用时跳过本次循环中 continue
后面的代码,直接回到了while
循环的判断部分,判断是否进行下一次循环
例题 题目一 1 2 3 4 5 6 7 8 9 int main () { int ch = 0 ; while ((ch = getchar()) != EOF) putchar (ch); return 0 ; }
EOF - end of file - 文件结束标志 (-1)
getchar - 输入一个字符 ,注意它的返回值是整型
putchar - 打印输出一个字符
while
循环进行getchar()读入,则会依次读到所有的字符,直到循环条件结束。
那么我们来看看以下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 int main () { char password[20 ] = { 0 }; printf ("请输入密码:" ); scanf ("%s" , password); printf ("请确认密码(Y/N):" ); int ch = getchar(); if (ch == 'Y' ) { printf ("确认成功\n" ); } else { printf ("确认失败\n" ); } }
有问题吗?
运行代码后,我们发现
在输入完密码后,回车确认,直接确认密码失败了
为什么呢?
因为getchar
和scanf
这种的输入函数,他并不是直接获取键盘输入的值,而是拿到键盘输入后存到缓冲区里的值
如果没有值,会等待键盘输入值
如果有值,会直接拿走使用
那么以上代码,在scanf
函数运行时,发现缓冲区里没有值,就等待键盘输入值
键盘输入值后,回车进行确认,触发scanf
函数,这时缓冲区内有 密码/n(/n哪里来的?回车输入的)
scanf
函数拿走密码后,运行到getchar
函数,此时缓冲区内还有一个/n
,就被getchar
函数直接拿走赋值给了ch
所以if
语句判断时,ch
的值是/n
不等于Y
,确认失败
那么如何解决这个问题呢?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 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" ); } }
那我们可以在ch
前面加上一个getchar()
,把缓冲区内的数值清除就可以了
然而,就有一个新的问题出现了
当我在运行后输入密码 123456 abc 后
也出现了确认失败
也就是scanf
只拿走了空格之前的 123456
而后面的 abc
以及 /n
留在了缓冲区
因为getchar()
只能获得一个字符;清除缓冲区后还留下了bc\n
,
等到ch
拿走缓冲区的第一个字符b
,判断又错误了
所以我们需要清理缓冲区的多个字符
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 main () { char password[20 ] = { 0 }; printf ("请输入密码:" ); scanf ("%s" , &password); printf ("请确认密码(Y/N):" ); while (getchar() != '\n' ) { } int ch = getchar(); if (ch == 'Y' ) { printf ("确认成功\n" ); } else { printf ("确认失败\n" ); } }
这样就可以成功运行代码了
不过这种方法写的密码不能含有空格,否则空格后的数值不会被存储
可以使用gets()
来存储密码,因为它不会向scanf
一样读到空格就停止,而是会一直读到回车
1 2 3 char password[20 ] = { 0 };printf ("请输入密码:" );gets(password);
题目二 1 2 3 4 5 6 7 8 9 10 11 int main () { while ((ch = getchar()) != EOF) { if (ch < '0' || ch > '9' ) continue ; putchar (ch); } return 0 ; }
以上代码会打印输出什么呢?
答案:不管你打了字母,符号,还是数字,它只会打印输出数字。
for 循环 语法结构:
1 2 for (表达式1 ;表达式2 ;表达式3 ) 循环语句;
表达式1表示初始化部分,用于初始化循环变量
表达式2表示条件判断部分,用于循环时候终止
表达式3表示调整部分,用于循环条件的调整
1 2 3 4 5 6 7 8 9 int main () { int i = 0 ; for (i = 1 ; i <= 10 ; i ++) { printf ("%d " ,i); } return 0 ; }
break的使用 1 2 3 4 5 6 7 8 9 10 11 int main () { int i = 0 ; for (i = 1 ; i <= 10 ; i++) { if (i == 5 ) break ; printf ("%d " , i); } return 0 ; }
在for
循环中,break
用于永久终止循环
continue的使用 1 2 3 4 5 6 7 8 9 10 11 int main () { int i = 0 ; for (i = 1 ; i <= 10 ; i++) { if (i == 5 ) continue ; printf ("%d " , i); } return 0 ; }
在for
循环中,continue
的作用时跳过本次循环中 continue
后面的代码,直接回到了for
循环的判断部分,判断是否进行下一次循环
注意:for
循环在调整部分可以调整变量的值,这点和while
不同
for 语句的循环控制变量
尽量不要再for循环中修改循环变量,防止for循环失去控制
建议在for语句的循环控制变量的取值采用“前闭后开区间”写法
1 2 3 4 5 6 7 8 9 10 11 12 13 int main () { int i = 0 ; for (i = 0 ; i < 10 ; i++) { } for (i = 0 ; i <= 9 ; i++) { } return 0 ; }
for循环的变种 以下代码打印输出什么?
1 2 3 4 5 6 7 8 int main () { for (;;) { printf ("hello\n" ); } return 0 ; }
答案:死循环输出hello
在使用for
语句的时候,初始化,判断,调整是可以省略的(但没必要)
但是,当你省略for
循环语句的判断部分的时候,会让判断恒为真,即一直进行循环
1 2 3 4 5 6 7 8 9 10 11 12 int main () { for (int i = 0 ; i <3 ; i++) { for (int j = 0 ; j < 3 ; j++) { printf ("hello\n" ); } } return 0 ; }
以上代码打印输出几次hello
?
答案:9次
因为每一次的的 i
的循环里都会有 3 次 j
的循环
那么以下代码会打印输出几次hello
呢?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 int main () { int i = 0 ; int j = 0 ; for (; i <3 ; i++) { for (; j < 3 ; j++) { printf ("hello\n" ); } } return 0 ; }
答案:3次
因为循环没有初始化
在第一次i
循环后,j
循环运行了3次,结束循环,开始第二次
但是因为没有初始化 j
的值,j
一直等于3,判断不通过
只输出了3次
1 2 3 4 5 6 7 8 9 int main () { int x, y; for (x = 0 , y = 0 ; x < 2 && y < 5 ; ++x, y++) { printf ("hello\n" ); } return 0 ; }
以上代码打印输出几次hello
?
答案:两次
例题 请问循环要循环多少次?
1 2 3 4 5 6 7 8 int main () { int i = 0 ; int k = 0 ; for (i =0 ,k=0 ; k=0 ; i++,k++) k++; return 0 ; }
答案:0次
解析:请注意判断部分,k = 0是赋值操作,0为假,判断不通过,没有进行循环
do while 循环 语法结构:
注意:do while
循环最少也会循环一次
1 2 3 4 5 6 7 8 9 int main () { int i = 1 ; do { printf ("%d" , i); i++; } while ( i <= 10 ); }
break的使用 1 2 3 4 5 6 7 8 9 10 11 int main () { int i = 1 ; do { if (i == 5 ) break ; printf ("%d " , i); i++; } while ( i <= 10 ); }
在do while
循环中,break
用于永久终止循环
continue的使用 1 2 3 4 5 6 7 8 9 10 11 int main () { int i = 1 ; do { if (i == 5 ) continue ; printf ("%d " , i); i++; } while ( i <= 10 ); }
在do while
循环中,continue
的作用时跳过本次循环中 continue
后面的代码,直接到了do while
循环的判断部分,判断是否进行下一次循环
goto语句 C语言中提供了可以随意滥用的 goto语句和标记跳转的标号。
从理论上 goto语句是没有必要的,实践中没有goto语句也可以很容易的写出代码。
最常见的用法就是终止程序在某些深度嵌套的结构的处理过程。
例如:一次跳出两层或多层循环。
多层循环这种情况使用break是达不到目的的。它只能从最内层循环退出到上一层的循环。
1 2 3 4 5 6 7 8 int main () { flag: printf ("hello\n" ); printf ("hello\n" ); goto flag; return 0 ; }
以上的代码会死循环打印hello
因为goto
语句可以直接跳到你需要的位置
你执行完前面两个打印输出,碰到goto
语句,又回到了最开始flag
的位置,进行执行,形成一个死循环
关机程序编写 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 #include <stdlib.h> #include <string.h> int main () { char input[20 ] = { 0 }; system("shutdown -s -t 60" ); printf ("请注意,你的电脑在一分钟内关机,如果你输入:“我是猪”,我就给你取消关机\n" ); again: scanf ("%s" ,input); if (strcmp (input,"我是猪" ) == 0 ) { system("shutdown -a" ); printf ("好的猪,这次就放过你了\n" ); } else { printf ("不对哦,快点输入:“我是猪”,电脑要关机咯\n" ); goto again; } return 0 ; }
不使用goto
语句的写法:
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 #include <stdlib.h> #include <string.h> int main () { char input[20 ] = { 0 }; system("shutdown -s -t 60" ); printf ("请注意,你的电脑在一分钟内关机,如果你输入:“我是猪”,我就给你取消关机\n" ); while (1 ) { scanf ("%s" , input); if (strcmp (input, "我是猪" ) == 0 ) { system("shutdown -a" ); printf ("好的猪,这次就放过你了\n" ); break ; } else { printf ("不对哦,快点输入:“我是猪”,电脑要关机咯\n" ); } } return 0 ; }
goto语句的适用场景 用于跳出多个循环
1 2 3 4 5 6 7 8 9 10 11 12 13 14 for (...) for (...) { for (...) { if (disaster) goto error; } } ... error: if (disaster) ...
注意:goto
语句只能在一个函数范围内跳转,不能跨函数跳转
练习题
计算 n的阶乘。
计算 1!+2!+3!+……+10!
在一个有序数组中查找具体的某个数字n。
编写代码,演示多个字符从两端开始显示,向中间汇聚。hello world!!!
最开始:##############
h############!
he##########!!
hel########!!!
……
到最后:hello world!!!
编写代码实现,模拟用户登录情景,并且只能登录三次。(只允许输入三次密码,如果密码正确则 提示登录成,如果三次均输入错误,则退出程序。
第一题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 int main () { int n = 0 ; int i = 0 ; int ret = 1 ; printf ("请输入n的值:" ); scanf ("%d" , &n); for (i = 1 ; i <= n; i++) { ret *= i; } printf ("%d" , ret); return 0 ; }
第二题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 int main () { int i = 0 ; int ret = 1 ; int sum = 0 ; for (i = 1 ; i <= 10 ; i++) { ret *= i; sum += ret; } printf ("%d" , sum); 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 31 32 33 34 int main () { int arr[] = { 1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 }; int num = 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] < num) { left = mid + 1 ; } else if (arr[mid] > num) { right = mid - 1 ; } else { printf ("找到了:%d,下标为%d\n" , arr[mid], mid); break ; } } if (left > right) { printf ("找不到这个数字" ); } return 0 ; }
第四题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <windows.h> int main () { char arr1[] = "hello world!!!" ; char arr2[] = "##############" ; int left = 0 ; int right = strlen (arr1) - 1 ; while (left<=right) { arr2[left] = arr1[left]; arr2[right] = arr1[right]; printf ("%s\n" , arr2); Sleep(1000 ); system("cls" ); left++; right--; } printf ("%s\n" , arr2); 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 31 32 int main () { int i = 0 ; char password[20 ] = { 0 }; for (i = 0 ; i < 3 ; i++) { printf ("请输入密码:" ); scanf ("%s" , password); if (strcmp (password, "123456" ) == 0 ) { printf ("登陆成功\n" ); break ; } else { if (i < 2 ) { printf ("密码错误,请重新输入\n" ); } } } if (i == 3 ) { printf ("三次密码均输入错误,请稍后再试" ); } return 0 ; }
扩展:
strcmp(s1,s2)
s1<s2时,返回为负数;s1 = s2时,返回值 = 0;s1 > s2时,返回正数。
它比较的是ASCII
码值,比如abcd
和abca
进行比较,
前面三个字符一样,第四位d的ASCII
码值为68,而a的ASCII
码值为65
所以abcd
> abca
猜数字游戏代码实现 写一个猜数字游戏 1.自动生成一个1~100的数字 2.猜数字 a.才对了,就恭喜你,游戏结束 b.你猜错了,就会告诉猜大了,还是猜小了,直到猜对 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 68 69 70 71 72 73 74 75 76 77 #include <stdlib.h> #include <time.h> #include <windows.h> void menu () { printf ("********************************************\n" ); printf ("************ 1.play **************\n" ); printf ("************ 0.exit *************\n" ); printf ("********************************************\n" ); } void game () { int ret = rand()%100 +1 ; int guess = 0 ; while (1 ) { printf ("请猜数字:" ); scanf ("%d" , &guess); if (guess < ret) { printf ("猜小了\n" ); } else if (guess > ret) { printf ("猜大了\n" ); } else { printf ("恭喜你,猜对了\n" ); Sleep(1000 ); system("cls" ); break ; } } } int main () { int input = 0 ; srand((unsigned int )time(NULL )); do { menu(); printf ("请选择:" ); scanf ("%d" , &input); switch (input) { case 1 : game(); break ; case 0 : printf ("退出游戏:\n" ); break ; default : printf ("选择错误,请重新选择:\n" ); break ; } } while (input); return 0 ; }
最大公约数和最小公倍数的代码实现 求两个数的最大公约数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 int main () { int m = 0 ; int n = 0 ; printf ("请输入两个数字:" ); scanf ("%d %d" ,&m,&n); int t = 0 ; while (t=m%n) { m = n; n = t; } printf ("最大公约数为:%d" ,n); return 0 ; }
求两个数的最小公倍数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 int main () { int m = 0 ; int n = 0 ; printf ("请输入两个数字:" ); scanf ("%d %d" ,&m,&n); int t = m > n ? m : n; while (t%m !=0 || t%n != 0 ) { t++; } printf ("最小公倍数为:%d" ,t); return 0 ; }
素数代码实现 求100~200中的素数及其数量:
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 #include <math.h> int main () { int i = 0 ; int count = 0 ; for ( i = 101 ; i <=200 ; i+=2 ) { int j = 0 ; int flag = 1 ; for (j = 2 ; j <= sqrt (i); j++) { if (i%j == 0 ) { flag = 0 ; break ; } } if (flag == 1 ) { printf ("%d " , i); count++; } } printf ("素数一共%d " , count); }