C语言初阶——循环语句

目录

循环语句

 一.while 循环

1.语法结构

2.break 和 continue 的用法

3.while 中的清理缓冲区

(1)getchar 和 putchar 的使用

(2)缓冲区的概念

(3)为什么清理缓冲区

(4)如何清理缓冲区

(5)我们来再看一个例子

二.do   while 循环

1.基本形式

2.do   while 和 while 的区别

3.break 和 continue 的用法

三.for 循环

1.基本形式

2.break 和 continue 的用法

3.两个好习惯

4.一些变种

(1)for 条件的省略

(2)for 的嵌套

(3)for 初始化的省略

(4)两个变量的

(5)容易犯错

四.goto 语句

1.两个小函数

(1)system函数

(2)strcmp函数

2.goto的用法

3.实例——关机程序

结束语


循环语句

1.while

2.for

3.do while

 一.while 循环

1.语法结构

while(表达式)

循环语句;

我们进行实现

()中的表达式,表达为真,继续循环,表达为假出循环,0表示假,!0表示真

 #include <stdio.h>
int main()
{
 int i = 1;
 while(i<=10)    //()中的表达式,表达为真,继续循环,表达为假出循环,0表示假,!0表示真
 {
 printf("%d ", i);
 i = i+1;
 }
 return 0;
}

2.break 和 continue 的用法

#include <stdio.h>
int main()
{
	int i = 1;
	while(i<=10)
	{
		if(i == 5) 
		{                      //当i等于5的时候,if判断这个成立,所以break执行,if是判断break是否执行的,是在整个while中
			break;
		}	                   //而当break执行的时候,会直接终止循环,下面的循环都不在执行,全部停止
		printf("%d ", i);
		i = i+1;               //这个break虽然在if里,但是if只是判断它发生不,一旦执行,整个while都停下来
	}
	return 0;
}

打印的结果为 1 2 3 4

break在while循环中的作用:

其实在循环中只要遇到break,就停止后期的所有的循环,直接终止循环。

所以:while中的break是用于永久终止循环的。

我们再来看continue

#include <stdio.h>
int main()
{
	int i = 1;
	 while(i<=10)
	{
		if(i == 5)         //当i等于5的时候,if里的开始执行,continue执行,就会跳过后面的代码,直接回到while再开始循环
		{
			continue;      //这个时候跳过后面的i++,导致后面陷入到死循环中,也不打印,也不++,就死在这了。
		}
		printf("%d ", i);  //所以我们知道continue的用法就是跳过它后面的代码,回到上面的while中在进行循环
		i++;
	}
	return 0;
}

这个打印的结果是 1 2 3 4 _    后面就是一个死循环,因为continue的作用就是跳过后面的代码,重新回到上面的循环中,继续执行,而这个跳过了 i++,所以i的值一直是5,所以会一直continue,就陷入到死循环中了,我们怎么解决呢?

#include <stdio.h>
int main()
{
	int i = 1;
	 while(i<=10)
	{
		i = i + 1;
		if(i == 5)         //当i等于5的时候,if里的开始执行,continue执行,就会跳过后面的代码,直接回到while再开始循环
		{
			continue;      //所以等于5的时候,跳过了打印,回到上面的循环中,再进行,所以打印出来没有5,结果是1 2 3 4 6 7 8 9 10
		}
		printf("%d ", i);  //所以我们知道continue的用法就是跳过它后面的代码,回到上面的while中在进行循环
	}
	return 0;
}

我们把 i++放到continue的前面,这样就不会跳过这个调整部分了,所以就能继续循环,跳过后面的代码,回到上面的循环,打印结果就是1 2 3 4 6 7 8  9 10

continue在while循环中的作用就是:

continue是用于终止本次循环的,也就是本次循环中continue后边的代码不会再执行,

而是直接跳转到while语句的判断部分。进行下一次循环的入口判断。

所以我们就常用在:某一次条件条件发生了,这一次循环后的代码不想让她执行了,就直接跳过去

3.while 中的清理缓冲区

(1)getchar 和 putchar 的使用

当我们想要在输入一个字符,并且打印它的时候,我们头脑中最先想到的一定是scanf和printf,这两个函数搭配使用来输出并且打印。

#include<stdio.h>
int main()
{
	char n;
	scanf("%c", &n);
	printf("%c", n);
	return 0;
}

当我们用getchar和putchar的时候

#include<stdio.h>
int main()
{
	char n;
	//scanf("%c", &n);
	//printf("%c", n);
	n = getchar();//从键盘中获取一个字符
	putchar(n);//输出一个字符到屏幕上
	return 0;
}

注意:scanf和printf可以针对各种各样的数据进行输入输出。但是getchar和putchar仅仅针对字符

当我们对他们加上while循环后,我们来看

int main()
{
	int ch = 0;
	while ((ch=getchar()) != EOF)    //这个!=EOF于scanf是一样的效果,看他是是否读到这个字符,读到了就是返回1,读取失败
	{                                //返回EOF,而1!=EOF,判断真,就继续循环读,EOF!=EOF判断为假,就出循环结束不读了	
		putchar(ch);                 //想停止于scanf一样就是ctrl+Z停止下来
	}

	return 0;
}

这里又出现了我们常见的 EOF

所以下面来看getchar与scanf返回值的相同

在我们多组输入的时候,我们就介绍过 EOF,那这么getchar也可以看到 EOF,我们来对比一下

#include<stdio.h>
int main()
{
	int a, b;
	while (scanf("%d %d",&a,&b) != EOF)
	{
		//代码段;
	}
	return 0;
}

这里他们俩的效果是一样的道理,我们在输入的时候,scanf 和 getchar 都是会去读取你所输入的数据,当他俩读取不到的时候,就会返回 EOF,所以我们这个用循环去判断,保证他们可以读取完你的数据,从而来实现多组输入,getchar 也一样,也是为了读取完你的数据,我们想停下来,也是一样 ctri + Z 就可以停止下来。

(2)缓冲区的概念

我们 getchar  读取数据的时候是从缓冲区拿的,我们来看图

 所以我们来看一段代码

#include<stdio.h>
int main()
{
	char ch = 0;
	while ((ch = getchar()) != EOF) {
		putchar(ch);
	}
	return 0;
}

我们输入几个数据打印出来的效果是这样的

 为什么我们打印的值都是换行后排列的呢

当我们在输入的时候,和最后执行的时候,我们先输入 a 然后输入回车,才在下面进行打印,回车就是 \n

这个时候我们在缓冲区里的就是 a \n ,这两个字符,但是我们 getchar 在拿的时候是一个一个字符拿的

第一次我先拿A,第二次我再拿这个 \n,所以我们打印的时候,会出现换行的效果

getchar 就是这样一个一个字符拿的,直到里面没有字符可以拿了,就返回 EOF

(3)为什么清理缓冲区

我们来看一段代码

int main()
{
	//数组名本来就是地址,所以下面scanf可以不用再取地址了,不用 & 了
	char password[20] = { 0 };
	int ch = 0;

	printf("请输入密码:>");
	scanf("%s", password);//123456

	//当我们输入密码后,我们回车后,直接就是:请确定密码(Y/N):>确认失败
	//原因就是,我们scanf在拿的时候,只拿他自己需要的,我们这里时%s,所以他就只拿字符串,后面的他不要,他不拿
	//他只拿属于自己类型的,后面或者有空格,或者就像这里的\n,他都不拿
	//所以scanf就只拿123456,现在里面剩个\n,到了getchar拿了,就只剩个\n了,\n !== Y,所以直接就失败了
	
	printf("请确认密码(Y/N):>");
	ch = getchar();
	if (ch == 'Y')
		printf("确认成功\n");
	else
		printf("确认失败\n");

	return 0;
}

来看我们的结果

 直接输出,确认失败,这是为什么呢?我们来看图片中的缓冲区

    我们scanf在拿的时候,只拿他自己需要的,我们这里时%s,所以他就只拿字符串,后面的他不要,他不拿
    他只拿属于自己类型的,后面或者有空格,或者就像这里的\n,他都不拿
    所以scanf就只拿123456,现在里面剩个\n,到了getchar拿了,就只剩个\n了,\n !== Y,所以直接就失败了

(4)如何清理缓冲区

像刚才上面出现的那种情况,我们就需要一个代码来帮 scanf 把 \n 给拿走,现实情况中,不仅仅只有 \n ,可能还有会空格,其他的scanf拿不了的,都需要一段代码帮他拿走

	while (getchar()!='\n')
	{
		;
	}

就是这样的简单代码,我们加入到里面,我们也不管他拿走存到哪里,也不管他里面是什么代码,我让你过来,就是让你过来,拿代码,拿到 \n 后,判断为假,你出循环了,你任务就结束了。

int main()
{
	//数组名本来就是地址,所以下面scanf可以不用再取地址了,不用 & 了
	char password[20] = { 0 };
	int ch = 0;

	printf("请输入密码:>");
	scanf("%s", password);//123456

	//消除\n - 清理缓冲区      
	//当我们不加这段代码的时候,我们刚输入密码123456,我们回车进行下一步确定密码时,直接结束,说确定失败了

	//所以现在加上这个代码,把后面的没有用的给拿走,不管输出啥,也不管存到哪,就给拿走就完了
	//这里可以用!=EOF,也可以用!=\n,因为我们最后一个是\n,所以我们让!=,所以读到最后的\n的时候,为假的,就出循环了
	//就把scanf拿不了的,都给拿走了,下面就能正常进行了
	while (getchar()!='\n')
	{
		;                     
	}
	
	//我们来看我们的缓冲区,这里有scanf还要getchar都来接受
	//scanf            缓冲区           键盘
	//getcahr          123456\n     
	//当我们输入密码后,我们回车后,直接就是:请确定密码(Y/N):>确认失败
	//原因就是,我们scanf在拿的时候,只拿他自己需要的,我们这里时%s,所以他就只拿字符串,后面的他不要,他不拿
	//他只拿属于自己类型的,后面或者有空格,或者就像这里的\n,他都不拿
	//所以scanf就只拿123456,现在里面剩个\n,到了getchar拿了,就只剩个\n了,\n !== Y,所以直接就失败了
	//所以我们在scanf后面加个getchar,帮scanf拿不走的给拿走,我们后面就能正常了,给拿走,可以存也可以不存
	//我们就是让他把scanf拿不了的拿走就行了,里面输出不输出,或者存不存,都不管他
	
	printf("请确认密码(Y/N):>");
	ch = getchar();
	if (ch == 'Y')
		printf("确认成功\n");
	else
		printf("确认失败\n");

	return 0;
}

    所以现在加上这个代码,把后面的没有用的给拿走,不管输出啥,也不管存到哪,就给拿走就完了
    这里可以用!=EOF,也可以用!=\n,因为我们最后一个是\n,所以我们让!=,所以读到最后的\n的时候,为假的,就出循环了
    就把scanf拿不了的,都给拿走了,下面就能正常进行了

(5)我们来再看一个例子

这个代码的作用是:只打印数字字符,跳过其他字符的

#include <stdio.h>
int main()
{
	char ch = '\0';       //初始化,被害怕
	while ((ch = getchar()) != EOF)
	{
		if (ch < '0' || ch > '9')  //这里的0-9是数字字符,需要看ASCII表,对应的就是数字,所以这个范围就是只打印数字字符
			continue;              //跳过其他的字符,当不在0-9的范围,if执行,就会continue,下面的不执行了,回到上面的while
		putchar(ch);               //就只打印0-9里面的,不符合if,所以就不会continue,就会去打印
	}
	return 0;
}

运行结果为,只能打印,0--9之间的字符,其余全部不打印,因为即便是\n出现了输入缓冲区的作用也会因为满足判断条件,而被终止不会被打印出来

二.do   while 循环

1.基本形式

int main()
{
	int i = 1;
	do
	{
		printf("%d ", i);
		i++;
	} while (i<=10);

	return 0;
}

2.do   while 和 while 的区别

这个就是上来先给你干一次,再去循环,判断在后面,while是先循环判断,在去执行一次,do while 是先执行一次,后再判断

3.break 和 continue 的用法

#include <stdio.h>
int main()
{
	int i = 1;
	do
	{
		if (5 == i)
			break;       //用法都是一样的,就是看清楚break放在哪里,注意看打印到几
		printf("%d ", i);
		i = i + 1;
	} while (i <= 10);

	return 0;
}
#include <stdio.h>
int main()
{
	int i = 1;

	do
	{
		if (5 == i)
			continue;        //看清楚这个,就是死循坏了,因为continue跳过后面的代码,然后回到上面,所以i值不变了,也不打印了,死循环了
		printf("%d ", i);    //要看清楚放的地方是哪里,具体问题具体分析不要太过于死板
		i = i + 1;
	} while (i <= 10);

	return 0;
}

其实 break 和 continue 的用法都是一样的,都是直接打破循环,直接跳过后面的代码回到上面,就是具体问题具体分析,看 continue 跳过了哪些代码,会不会产生死循环,有些调整该放到  continue 的放到上面,看清楚从哪打破,从哪些跳过去就好

三.for 循环

1.基本形式

先对比while中的,初始化,判断,调整的位置

int main()
{
	int i = 1;//1 - 初始化

	while (i < 10)//2 - 判断
	{
		printf("%d ", i);
		i++;//3 - 调整
	}

	return 0;
}

现在我们再来看用for

使用for在屏幕上打印1~10

for(初始化;判断;调整)

int main()
{
	int i = 0;
	for (i = 1; i <= 10; i++)
	{
		printf("%d ", i);
	}
	return 0;
}

2.break 和 continue 的用法

//代码1 1 2 3 4 
#include <stdio.h>
int main()
{
	int i = 0;
	for (i = 1; i <= 10; i++)
	{
		if (i == 5)
			break;       //break用法都是一样的,直接终止循环
		printf("%d ", i);
	}
	return 0;
}
//代码2   1 2 3 4 6 7 8 9 10 
#include <stdio.h>
int main()
{
	int i = 0;
	for (i = 1; i <= 10; i++)
	{
		if (i == 5)     //这个就跟while中的有点区别,但是continue都是一样的效果,都是直接跳过后面的代码,再回到上面的循环中
			continue;   //在while中,可能调整在continue后面所以会发生死循环,但是for不会,他的调整在上面,不怕continue的跳过
		printf("%d ", i);
	}
	return 0;
}

其实 break 和 continue 的用法都是一样的,都是直接打破循环,直接跳过后面的代码回到上面,就是具体问题具体分析,看 continue 跳过了哪些代码,会不会产生死循环,有些调整该放到  continue 的放到上面,看清楚从哪打破,从哪些跳过去就好

在 for 中就不会容易出现像 while 中 continue 跳过的时候出现死循环,因为 for 的调整部分是在 for 里面,所以不会被 continue 给跳过

3.两个好习惯

1. 不可在for 循环体内修改循环变量,防止 for 循环失去控制。

2. 建议for语句的循环控制变量的取值采用“前闭后开区间”写法。

int main()
{
	int arr[10] = {1,2,3,4,5,6,7,8,9,10};
	//0~9
	//打印数组的内容
	int i = 0;               //别在for{}改变变量的值,这样可能发生死循环,调整是在for()中进行的
	for (i = 0; i < 10; i++) //就是这样写,前闭后开,写i<10     不写 i<=9,但是还是看题目的条件,都是全部都是这样的
	{
		printf("%d ", arr[i]);
	}

	return 0;
}

4.一些变种

(1)for 条件的省略

for循环的初始化,判断和调整三个部分都可以省略

但是省略调判断部分,判断就恒为真,循环就死循环

	for (;;)
	{
		printf("hehe\n");    //这个就是一个死循环
	}

(2)for 的嵌套

	int i = 0;
	int j = 0;
	for (i=0; i < 3; i++)
	{
		for (j = 0; j < 3; j++)   //俩个循环套娃,打印9次
		{
			printf("hehe\n");
		}
	}

打印9个 hehe

(3)for 初始化的省略

    int i = 0;
	int j = 0;
	//如果省略掉初始化部分,这里打印多少个hehe?
	for(; i<3; i++)
   {
		for(; j<3; j++)        //当省略到初始化的部分,只打印3个,再第一个i=0时,下面的循环3次后,j=3,就一直等于3了
	   {
			 printf("hehe\n"); //所以再回到上面的那个循环里,j还是一直等于3,所以就不打印了,直到i出循环
	   }
   }

只会打印3个 hehe,因为一个循环后面,不会初始化,所以第二个 for 循环结束后,j 一直就是3,所以第一个 for 循环在第二个中就不会再 打印了,所以就只能打印3个 hehe

(4)两个变量的

 //使用多于一个变量控制循环
 int x, y;
	for (x = 0, y = 0; x<2 && y<5; ++x, y++)
   {
		printf("hehe\n");  //打印两次,去看好他们的判断条件,是或还是且,看清楚循坏几次,两个变量都要看
   }
	return 0;
}

就是要看清楚两个变量,都要注意他们的条件和判断,看什么时候出循环

(5)容易犯错

//请问循环要循环多少次?
#include <stdio.h>
int main()
{
	 int i = 0;
	 int k = 0;
	 for(i =0,k=0; k=0; i++,k++) //看清楚啊,这是赋值,不是相等的判断,是赋值!!!,k为0了,所以就不循环了,
			k++;                 //k=0,是赋值,直接0为假,直接出循环了,
	 return 0;
}

要看清楚这里的判断不再是判断了,直接变成赋值了,k=0,是赋值,直接0为假,直接出循环了

四.goto 语句

1.两个小函数

先简单介绍一下,下一期会主要讲解的

(1)system函数

这个函数头文件是 stdlib.h ,是用来执行电脑命令的一个库函数

(2)strcmp函数

这个函数头文件是 string.h ,是用来判断两个字符串是否相等的一个库函数

2.goto的用法

从理论上 goto语句是没有必要的,实践中没有goto语句也可以很容易的写出代码。 但是某些场合下goto语句还是用得着的,最常见的用法就是终止程序在某些深度嵌套的结构的处理过程。

例如:一次跳出两层或多层循环。 多层循环这种情况使用break是达不到目的的。它只能从最内层循环退出到上一层的循环

for(...)
    for(...)
   {
        for(...)
       {
            if(disaster)
                goto error;
       }
   }
    …
error:
 if(disaster)
         // 处理错误情况

3.实例——关机程序

#include <stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
    char input[100];
    system("shutdown -s -t 60"); //这引用这个库函数,来传递系统命令,-s 就是关机。-a 取消关机
                                 //这是Windows系统下的一个关机命令,-t 60,就是六十秒后执行,注意空格 
    flag:                        //这里就是goto回到这的标志,goto后面加这个,就是回到这里
	printf("你的电脑将在一分钟后关机,如果输入“我是猪”,就会取消关机!\n请输入: ");
    scanf("%s",input);
    if(0==strcmp(input,"我是猪")) //判断字符串相等不能直接判断,需要函数strcmp
	{
        system("shutdown -a");//取消关机命令
	}
    else
	{
        goto flag;
	}
    return 0;
}

system就是执行系统的命令,可以自己百度多做了解

而strcmp函数,就是判断两个字符串是否相等

第一个字符串 > 第二个字符串       返回的数值 < 0

第一个字符串 < 第二个字符串       返回的数值 > 0

第一个字符串 = 第二个字符串       返回的数值 为 0

 但是这个goto也没必要,用循环也是一样,所以goto能不用就不用,多个嵌套的时候,看情况用

#include <stdio.h>
#include <stdlib.h>
int main()
{
    char input[10] = {0};
    system("shutdown -s -t 60");
    while(1)
   {
        printf("电脑将在1分钟内关机,如果输入:我是猪,就取消关机!\n请输入:>");
        scanf("%s", input);
        if(0 == strcmp(input, "我是猪"))
       {
            system("shutdown -a");
            break;
       }
   }
    return 0;
}

结束语

下一节会讲几个,分支语句和循环语句的典型重要例题并加以说明。

我的gitee仓库:https://gitee.com/he-yangtongxue/bit.c.test

  • 10
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值