循环语句
文章目录
一、goto循环
goto原本是用于实现代码的跳转的,注意:只能在同一个函数中跳转。
goto对代码的逻辑性和易读性是有一定的影响的,所以要慎用goto。
1.1 goto的基本使用格式
代码块1;
goto NEXT;
代码块2;
NEXT: //标签
代码块3;
1.2 执行逻辑
先执行代码块1,然后遇到goto语句,直接跳转到对应的标签继续向下执行代码块3
代码块2 就被跳过了 不执行。
上面代码中的 NEXT叫做标签,名字可以随便起 符合命名规范即可,一般都是大写。
代码中可以定义多个标签,goto到哪个标签,就到哪个标签后面开始执行。
例:
#include <stdio.h>
int main(int argc, const char *argv[])
{
printf("11111111\n");
goto NEXT; //直接跳转到 NEXT 继续向下执行
printf("22222222\n");//被跳过
printf("33333333\n");//被跳过
printf("44444444\n");//被跳过
NEXT:
printf("55555555\n");
return 0;
}
1.3 使用goto实现循环
我们平时使用的循环一般都是有结束条件的
否则就是死循环了
例:使用goto输出 5行 hello world
#include <stdio.h>
int main(int argc, const char *argv[])
{
printf("----start----\n");
int count = 0; //用来计数的
LOOP:
printf("hello world\n");
count++; //count = count + 1;
if(count<5){ //这个条件不满足时 就不再goto了
goto LOOP;//如果无条件的goto 就是死循环了
}
printf("----end----\n");
return 0;
}
练习:
使用goto实现计算 1+2+3+…+100 求和。
实现思路:
#if 0
int sum = 0;
sum += 1;
sum += 2;
...
sum += 100;
#endif
#if 0
int sum = 0;
int i = 1; //用于控制循环次数的变量 称之为循环变量 i j k
sum += i;
i++;
sum += i;
i++;
....
sum += i;
i++;
#endif
int sum = 0;
int i = 1;
LOOP:
sum+=i;
i++;
if(i<=0){
goto LOOP;
}
答案:
#include <stdio.h>
int main(){
int sum = 0;//用来保存求和的结果 此处初始化成0 是必须的
int i = 0;//用来控制循环的次数 以及每次加的值
LOOP:
sum += i;
i++;
if(i<=100){
goto LOOP;
}
printf("sum = %d\n", sum);
return 0;
}
二、 while循环
2.1 格式
while(表达式){
代码块;
}
2.2 执行逻辑
先执行表达式,如果表达式为真,则执行代码块
然后继续执行表达式,如果还为真,就再执行代码块
直到表达式为假 循环立即结束 继续执行循环后面的代码
while中表达式的用法和 if…else 的表达式用法一样。
注意:代码块中一般都有用于表达式结果的语句 来控制循环的次数
例:使用while循环实现 打印 5行 hello world
#include <stdio.h>
int main(int argc, const char *argv[])
{
printf("----start----\n");
int i = 0; //循环变量命名 一般都是 i j k
while(i < 5){
printf("hello world\n");
i++;
}
printf("----end----\n");
return 0;
}
练习:
1.使用while循环,计算 1~100 求和。
#include <stdio.h>
int main(){
int sum = 0;
int i = 1;
while(i <= 100){
sum += i;
i++;
}
printf("sum = %d\n", sum);
return 0;
}
2.猴子吃桃问题
猴子第一天摘了若干个桃,当即就吃掉了一半数量的桃
没吃过瘾,又多吃了一个;
第二天,在剩下的桃中,又吃了一般数量
没吃过瘾,又多吃了一个;
。。。
依次类推,以后的每天都吃一半数量再多一个
到10天再想吃桃的时候,发现,只剩下一个了。
问:猴子第一天摘了多少个桃。
要求使用while循环实现。
/*
9
第10天 1个
第9天 4个 (1+1)*2
第8天 10个 (4+1)*2
..
*/
#include <stdio.h>
int main(){
int count = 1;
int i = 0;
while(i < 9){
count = (count+1)*2;
i++;
}
//当循环结束的时候 count记录的就是 第一天的桃子的数量
printf("第一天有 %d 个桃\n", count);
return 0;
}
思考:
如何实现:把每天剩余的桃子数量都输出出来?
#include <stdio.h>
int main(){
int count = 1;
int i = 0;
while(i < 9){
printf("第 %d 天有 %d 个桃\n", 10-i, count);
count = (count+1)*2;
i++;
}
printf("第 %d 天有 %d 个桃\n", 10-i, count);
return 0;
}
3.思考 下面的代码会输出什么?
//没有代码块的while循环可以将{}用分号 ; 替换
//while(表达式);
int x = 100;
while(x--){}
//while(x--); //这种写法和上面那行是一样的
printf("%d\n", x); // -1
int x = 100;
while(--x);
printf("%d\n", x); // 0
三、 do…while循环
3.1 格式
do{
代码块;
}while(表达式); //别忘了此处有个分号
3.2 执行逻辑
先执行代码块,然后执行表达式,如果表达式为真,
则继续执行代码块,直到表达式为假,循环立即结束。
do…while 和 while 的区别:
while 先判断 后执行
do…while 先执行 后判断
do…while的代码块,不管表达式是否为真,都至少执行一次。
例:使用 do…while 实现 1~100 求和
#include <stdio.h>
int main(int argc, const char *argv[])
{
int sum = 0;
int i = 1;
do{
sum+=i;
i++;
}while(i<=100);
printf("sum = %d\n", sum);
return 0;
}
编码:输入一个日期,输出这个日期是这一年的第几天(考虑平年闰年问题)。
如:2022年3月1日 则输出 2022年3月1日是2022年的第60天
2020年3月1日 则输出 2022年3月1日是2022年的第61天
#include <stdio.h>
//输入一个日期,输出当前日期是这一年的第几天
#define MONTH_1 31
#define MONTH_2 28
#define MONTH_3 31
#define MONTH_4 30
#define MONTH_5 31
#define MONTH_6 30
#define MONTH_7 31
#define MONTH_8 31
#define MONTH_9 30
#define MONTH_10 31
#define MONTH_11 30
#define MONTH_12 31
int main()
{
int year, month, day;
printf("请输入要查询的日期(年/月/日):");
scanf("%d/%d/%d", &year, &month, &day);
//闰年的增量 也是闰年的标志位 0 平年 1 闰年
int leap = 0;
//printf("%d/%d/%d\n", year, month, day);
//判断输入的日期是否有误
//判断年是闰年还是平年
if(((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)){
leap = 1;
}
//判断月份输入的是否有误
if(month < 1 || month > 12){
printf("您输入的月份有误,请重新输入\n");
//在main函数里面使用return,结束整个程序
return -1;
}
//判断日是否有误
//月份:1 3 5 7 8 10 12 最多31天
if(month==1 || month==3 || month==5 || month==7 || month==8 || month==10 || month==12){
if(day < 1 || day > 31){
printf("您输入的日期有误,请重新输入\n");
return -1;
}
}
//月份:4 6 9 11 最多30天
if(month==4 || month==6 || month==9 || month==11){
if(day < 1 || day > 30){
printf("您输入的日期有误,请重新输入\n");
return -1;
}
}
//月份:2 闰年最多29天 平年最多28天
if(month == 2){
if(leap == 1){ //闰年
if(day < 1 || day > 29){
printf("您输入的日期有误,请重新输入\n");
return -1;
}
}else if(leap == 0){ //平年
if(day < 1 || day > 28){
printf("您输入的日期有误,请重新输入\n");
return -1;
}
}
}
int days = 0;
switch(month){
case 12:
days += MONTH_11;
case 11:
days += MONTH_10;
case 10:
days += MONTH_9;
case 9:
days += MONTH_8;
case 8:
days += MONTH_7;
case 7:
days += MONTH_6;
case 6:
days += MONTH_5;
case 5:
days += MONTH_4;
case 4:
days += MONTH_3;
case 3:
days += MONTH_2 + leap;
case 2:
days += MONTH_1;
case 1:
days += day;
break;
}
printf("%d年%d月%d日%d年的第%d天\n", year, month, day, year, days);
return 0;
}
四、 for循环
4.1 格式
for(表达式1;表达式2;表达式3){
代码块;
}
4.2 执行逻辑
先执行表达式1,然后执行表达式2,如果表达式2为真,则执行代码块,然后执行表达式3
然后再执行表达式2,如果还为真,则继续执行代码块和表达式3,
直到表达式2为假,循环立即结束。
4.3关于for循环的三个表达式
表达式1:只执行一次,一般是用来给循环变量赋初值的
----C99的编译器允许for循环的第一个表达式中定义变量,
但是注意,这种方式定义的变量只能在循环内部使用
表达式2:和if或者while的表达式一样,
一般是有关系运算符和逻辑运算符组成用来判断真假的
表达式3:一般是用来改变循环变量的值从而控制循环结束的
注意:
1.这三个表达式如果不需要其中某几个,可以不写,但是两个分号 ;; 必须写
2.表达式1和表达式3,每个都可以不只是一句,如果是多句,用逗号分隔
例:
#include <stdio.h>
int main(int argc, const char *argv[])
{
printf("----start----\n");
#if 0
for(int i = 0; i < 5; i++){//在表达式1中定义的 i 只能在循环内部使用
printf("hello world\n");
}
//printf("i = %d\n", i);//i不能再使用了
#endif
#if 1
int i = 0;
for(i = 0; i < 5; i++){
printf("hello world\n");
}
printf("i = %d\n", i); // 5 i可以使用
#endif
printf("----end----\n");
return 0;
}
练习:
1.使用for循环实现 1~100 求和。
#include <stdio.h>
int main(){
int sum = 0;
int i = 0;
for(i = 1; i <= 100; i++){
sum += i;
}
printf("sum = %d\n", sum);
return 0;
}
把 goto 、while 、do…while 、for 实现的1~100求和的代码 拿出来 自己对比一下。
int sum = 0;
int i = 0;
LOOP:
sum += i;
i++;
if(i <= 100){
goto LOOP;
}
int sum = 0;
int i = 0;
while(i <= 100){
sum += i;
i++;
}
int sum = 0;
int i = 0;
do{
sum += i;
i++;
}while(i <= 100);
int sum = 0;
int i = 0;
for(i = 0; i <= 100; i++){
sum += i;
}
2.在终端输入一个数 [100,999]范围内的,判断这个是是不是水仙花数
水仙花数:个位个位个位 + 十位十位十位 + 百位百位百位 == 自身
如:153 <==> 333 + 555 + 111 == 27 +125 + 1 == 153
#include <stdio.h>
int main(int argc, const char *argv[])
{
int num = 0;
scanf("%d", &num);
int g = num % 10;
int s = num % 100 / 10;
int b = num / 100;
if(g*g*g + s*s*s + b*b*b == num){
printf("%d 是水仙花数\n", num);
}
return 0;
}
3.输出[100,999]范围内所有的水仙花数
#include <stdio.h>
int main(int argc, const char *argv[])
{
int num = 0;
int g = 0;
int s = 0;
int b = 0;
for(num = 100; num < 1000; num++){
//循环里面尽量不要定义变量
//因为频繁的分配和回收内存空间会产生额外的时间开销
//int g = num % 10;
//int s = num % 100 / 10;
//int b = num / 100;
g = num % 10;
s = num % 100 / 10;
b = num / 100;
if(g*g*g + s*s*s + b*b*b == num){
printf("%d 是水仙花数\n", num);
}
}
return 0;
}
C语言中计算幂的函数和开平方的函数–了解即可
使用时需要加头文件 #include
编译时需要链接数学库 需要加编译选项 -lm
double pow(double x, double y); //pow 计算x的y次方
double sqrt(double x); //sqrt 计算x的非负平方根
#include <stdio.h>
#include <math.h>
int main(int argc, const char *argv[])
{
int a = 2;
int b = 3;
double ret1 = pow(a, b);
printf("ret1 = %lf\n", ret1); //8.000000
printf("%lf\n", pow(3, 4)); //81.000000
int x = 16;
printf("%lf\n", sqrt(x)); //4.000000
return 0;
}
4.使用循环配合着 putchar 函数,打印下面的图案。
#include <stdio.h>
int main(int argc, const char *argv[])
{
int i = 0;
int j = 0;
char value = 'F';
//外面循环控制行数
for(i = 0; i < 6; i++){
//循环体 就是一行要输出的内容
//打印没一行的下划线的
for(j = 0; j < i; j++){
putchar('_');
}
//打印字母的
value = 'F'; //此处重置 value 的值为 'F' 是必要的
for(j = 0; j < 6-i; j++){
putchar(value--);
}
putchar(10);//换行
}
return 0;
}
五、 死循环
所谓的死循环就是程序一直在循环里面执行,无限循环。
while(1){ //常用的写法
//循环体
}
for(;;){ //注意所有表达式都可以不写 但是 两个 ;; 必须要写
//循环体
}
//如果自己写代码 不小心死循环了 按 ctrl + c 退出
例:
#include <stdio.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
printf("----start----\n");
#if 0
while(1){
printf("hello world\n");
sleep(1); //休眠1秒
}
#endif
for(;;){ //表达式可以不写 两个分号必须写
printf("hello world\n");
sleep(1); //休眠1秒
}
printf("----end----\n");//永远执行不到
return 0;
}
六、辅助控制关键字
6.1 break
break可以用在switch…case语句中,表示执行完某一个分支就立即结束整个switch…case语句
break也可以用在循环中,表示立即结束本层的循环。
6.2 cuntinue
continue 只能用于循环中,表示立即结束本层的本次循环。
6.3 return
return 如果用在函数中,使用来返回函数运行的结果的;
return 如果用在main函数中,表示理解结束整个程序。
例:
#include <stdio.h>
int main(int argc, const char *argv[])
{
int i = 0;
int j = 0;
for(i = 1; i <=5; i++){
for(j = 1; j <= 5; j++){
if(3 == j){
//break;
//continue;
return 0;
}
printf("%d--%d\n", i, j);
}
}
return 0;
}
七、控制语句综合练习
1.输出 [1,100] 范围内所有的偶数
#include <stdio.h>
int main(int argc, const char *argv[])
{
int num = 0;
for(num = 1; num <= 100; num++){
if(0 == num%2){
printf("%d 是偶数\n", num);
}
}
return 0;
}
2.输入一个数,输出这个数的所有因子。
例如:输入 12 则输出 1 2 3 4 6 12
#include <stdio.h>
int main(int argc, const char *argv[])
{
int num = 0;
scanf("%d", &num);
int i = 0;
//遍历 1~num
for(i = 1; i <= num; i++){
if(num%i == 0){
printf("%d\n", i);
}
}
return 0;
}
3.输入一个数,判断这个数是不是完数。
完数:除了自身之外的所有因子和还等于自身。
如: 6 == 1 + 2 + 3 说明 6就是完数
#include <stdio.h>
int main(int argc, const char *argv[])
{
int n = 0;
scanf("%d", &n);
int sum = 0;
int i = 1;
//计算因子和
for(i = 1; i < n; i++){
if(n%i == 0){
sum += i;
}
}
//当上面的循环结束的时候
//sum中保存的就是 n的所有因子和(不包括n)
if(sum == n){
printf("%d 是完数\n", n);
}
return 0;
}
4.输出 [1,999] 范围内所有的完数
#include <stdio.h>
int main(int argc, const char *argv[])
{
int n = 0;
int sum = 0;
int i = 0;
for(n = 1; n < 1000; n++){
sum = 0; //注意:此处的 sum重新置0是必要的
//因为sum中还保存着上一个数的因子和呢
//计算n的因子和
for(i = 1; i < n; i++){
if(n%i == 0){
sum += i;
}
}
//当上面的循环结束的时候
//sum中保存的就是 n的所有因子和(不包括n)
if(sum == n){
printf("%d 是完数\n", n);
}
}
return 0;
}
5.输出 [2, 99] 范围内所有的质数
质数:因子只有自身和1的数
解决方式1:通过标志位处理
#include <stdio.h>
int main(int argc, const char *argv[])
{
int num = 0;
int flag = 0; //质数的标识位 0 是质数 1 不是质数
int i = 0;
for(num = 2; num < 100; num++){
flag = 0; //如果使用的是标识位来判断 记得每次 重新置0
for(i = 2; i < num; i++){
if(num%i == 0){
flag = 1;
break;
}
}
if(flag == 0){
printf("%d 是质数\n", num);
}
}
return 0;
}
解决方式2:通过判断循环结束的条件来处理
#include <stdio.h>
int main(int argc, const char *argv[])
{
int num = 0;
int i = 0;
for(num = 2; num < 100; num++){
for(i = 2; i < num; i++){
if(num%i == 0){
break;
}
}
//上面的循化有两种结束情况
//第一种:由于表达式2为加导致的正常结束
//第二中:由于break导致的提前结束
if(i == num){
printf("%d 是质数\n", num);
}
}
return 0;
}
n的所有因子和(不包括n)
if(sum == n){
printf(“%d 是完数\n”, n);
}
}
return 0;
}
5.输出 [2, 99] 范围内所有的质数
质数:因子只有自身和1的数
解决方式1:通过标志位处理
#include <stdio.h>
int main(int argc, const char *argv[])
{
int num = 0;
int flag = 0; //质数的标识位 0 是质数 1 不是质数
int i = 0;
for(num = 2; num < 100; num++){
flag = 0; //如果使用的是标识位来判断 记得每次 重新置0
for(i = 2; i < num; i++){
if(num%i == 0){
flag = 1;
break;
}
}
if(flag == 0){
printf("%d 是质数\n", num);
}
}
return 0;
}
解决方式2:通过判断循环结束的条件来处理
#include <stdio.h>
int main(int argc, const char *argv[])
{
int num = 0;
int i = 0;
for(num = 2; num < 100; num++){
for(i = 2; i < num; i++){
if(num%i == 0){
break;
}
}
//上面的循化有两种结束情况
//第一种:由于表达式2为加导致的正常结束
//第二中:由于break导致的提前结束
if(i == num){
printf(“%d 是质数\n”, num);
}
}
return 0;
}