【C总集篇】第五章 循环


第五章 循环

while

初识while

while 语法结构:

while(表达式)
	 循环语句;

举例:
在这里插入图片描述
while就像这张图,去考试就是while的判断条件,而继续学习则是循环内容

我们来演示一下while的用法大家就明白了

在屏幕上打印1-10的数字:

#include <stdio.h>
int main()
{
	 int i = 1;
	 while(i<=10)
	 {
		 printf("%d ", i);
		 i = i+1;
	 }
	 return 0;
}

在这里插入图片描述
执行步骤:

  1. 当函数执行到第四行,先将1的值赋予给i

  2. 到第五行的时候,先判断 i 里面的值是否小于等于10

  3. 当条件成立时,执行第七和第八行的循环语句

  4. 执行完循环语句之后呢,再返回第五行再进行判断i 里面的值是否小于等于10。

  5. 然后步骤3,4循环,直到当条件不成立时跳出,继续向下执行第10行

​   我们只要写好控制语句,每次执行循环体前就会先判断下循环控制表达式是否为真,为真就继续执行循环,否则就结束循环。
  注意:如果在循环体内忘了对影响循环控制表达式的变量(就是这个 n)进行改变,就会使这个循环变成死循环(一直执行)

while介绍

#include <stdio.h>
int main(void)
{
    long num;
    long sum = 0L;      
    int status;
    
    printf("Please enter an integer to be summed ");
    printf("(q to quit): ");
    status = scanf("%ld", &num);
    while (status == 1) 
    {
        sum = sum + num;
        printf("Please enter next integer (q to quit): ");
        status = scanf("%ld", &num);
    }
    printf("Those integers sum to %ld.\n", sum);

    return 0;
}

​ status ==1

==运算符是C的相等运算符,该表达式判断 status 是否等于 1。

​   不要把 status==1与status =1混淆,后者是把1赋给 status。根据测试条件 status == 1,只要 status 等于 1,循环就会重复。每次循环,num的当前值都被加到 sum 上,这样 sum 的值始终是当前整数之和。当status的值不为1时,循环结束。然后程序打印sum的最终值。
​   要让程序正常运行,每次循环都要获取 num的一个新值,并重置status。程序利用 scanf()的两个不同的特性来完成。首先,使用scanf()读取 num 的一个新值:然后,检査 scanf()的返回值判断是否成功获取值。scanf()返回成功读取项的数量。如果scanf()成功读取一个整数,就把该数存入 num 并返回 1,随后返回值将被赋给 status(注意,用户输入的值储存在 num 中,不是 status中)。这样做同时更新了num和 status 的值,while循环进入下一次迭代。如果用户输入的不是数字(如,q),scanf()会读取失败并返回0。此时,status的值就是0,循环结束。因为输入的字符q不是数字所以它会被放回输入队列中(实际上,不仅仅是q,任何非数值的数据都会导致循环终止,但是提示用户输入q退出程序比提示用户输入一个非数字字符要简单)。
​   如果 scanf()在转换值之前出了问题(例如,检测到文件结尾或遇到硬件问题),会返回一个特殊值EOF(其值通常被定义为-1)。这个值也会引起循环终止。

​   总之,因为 while循环是入口条件循环,程序在进入循环体之前必须获取输入的数据并检查 status的值,所以在 while前面要有一个 scanf()。要让循环继续执行,在循环内需要一个读取数据的语句,这样程序才能获取下一个 status 的值,所以在 while 循环末尾还要有一个 scanf(),它为下一次迭代做好了准备。

简洁版:

​   第二种形式同时使用scanf()的两种不同的特性。首先,如果函数调用成功,scanf()会把一个值存入num。然后,利用scanf()的返回值(0或 1,不是num 的值)控制 while 循环。因为每次迭代都会判断循环的条件,所以每次迭代都要调用 scanf()读取新的num值来做判断。换句话说,C的语法特性让你可以用下面的精简版本替换标准版本:
在这里插入图片描述

#include <stdio.h>
int main(void)
{
    long num;
    long sum = 0L;      
    int status;
    
    printf("Please enter an integer to be summed ");
    printf("(q to quit): ");
    while (scanf("%ld", &num) == 1) 
    {
        sum = sum + num;
        printf("Please enter next integer (q to quit): ");

    }
    printf("Those integers sum to %ld.\n", sum);

    return 0;
}

while中的真与假

​   这是一个古老的问题,但是对C而言还不算难。在C中,表达式一定有一个值,关系表达式也不例外。我们用一个例子来表达什么是真,什么是假

#include <stdio.h>
int main(void)
{
    int true_val, false_val; 
    true_val = (10 > 2);   
    false_val = (10 == 2);  
    printf("true = %d; false = %d \n", true_val, false_val); 
    return 0;
}

在这里插入图片描述
所以由上例可知,我们目前可以得知对于 c 语言而言,

​               真为1假为0

  又因为 while 中的判断是判断它是否为真还是为假,所以如果是while(1),则程序会一直执行下去,也就是我们所说的死循环

while(1)
{
    //任务语句
}

注意:当表达式成立时,为真表达式不成立时为假

例如:

2 > 1	//成立,为真
a = 1 	//成立,为真
1 > 2	//不成立,为假
...

那如果我们在while循环中填写,其他值会怎么样,是否含是为真,还是为假?

#include <stdio.h>
int main(void)
{
    int n = 3;
    
    while (n)
        printf("%2d is true\n", n--);
    printf("%2d is false\n", n);
    
    n = -3;
    while (n)
        printf("%2d is true\n", n++);
    printf("%2d is false\n", n);
    
    return 0;
}

在这里插入图片描述
  那从上面的代码我们可以知道,当循环条件为真时,也就是while成立,则会一直输出该值为真,当循环条件为假时,则会输出为假

  然后我们从上述可以知道,如果值等于零的话,那则条件为假。如果数字为其他数的话,则条件为真

​ 所以我们可以总结出来:

非零值为真,值是零则为假

​   所以我们可以很好的利用这一特性

​   例如:用while(goats)替换 while(goats!=0)

​   因为表达式goats!=0和 goats都只有在 goats的值为0时才为0或假。第1种形式(while(goats!= 0))对初学者而言可能比较清楚,但是第2种形式(while(goats))才是比较常用的。

for

for 介绍

  for循环把上述3个行为(初始化、测试和更新)组合在一处。

for (表达式1; 表达式2; 表达式3)
{
        语句;
}

首先要强调两点:

  1. 表达式1、表达式2和表达式3之间是用分号;隔开的,千万不要写成逗号。

  2. for(表达式1;表达式2;表达式3)的后面千万不要加分号,很多新手都会犯这种错误——会情不自禁地在后面加分号。

​   因为 for 循环只能控制到其后的一条语句,而在C语言中分号也是一个语句——空语句。所以如果在后面加个分号,那么 for 循环就只能控制到这个分号,下面大括号里面的语句就不属于 for 循环了。

下面来看看它的执行过程:

求解表达式1。
求解表达式2。若其值为真,则执行 for 语句中指定的内嵌语句,然后执行第3步;若表达式2值为假,则结束循环,转到第5步。
求解表达式3。
转回上面第2步继续执行。
循环结束,执行 for 语句下面的语句。

  从这个执行过程中可以看出,“表达式1”只执行一次,循环是在“表达式2”“表达式3”和“内嵌语句”之间进行的。

例子

#include <stdio.h>
int main(void)
{
    const int NUMBER = 22;
    int count;
    
    for (count = 1; count <= NUMBER; count++)
        printf("Be my Valentine!\n");
    
    return 0;
}

​   关键字 for 后面的圆括号中有3个表达式,分别用两个分号隔开。

​   第1个表达式是初始化,只会在 for循环开始时执行一次。

​   第2个表达式是测试条件,在执行循环之前对表达式求值。如果表达式为假(本例中,count 大于 NUMBER时),循环结束。

​   第3个表达式执行更新,在每次循环结束时求值。

​   上述程序用这个表达式递增 count 的值,更新计数。完整的 for 语句还包括后面的简单语句或复合语句。for 圆括号中的表达式也叫做控制表达式,它们都是完整表达式,所以每个表达式的副作用(如,递增变量)都发生在对下一个表达式求值之前。

在这里插入图片描述
例子2:

# include <stdio.h>
int main(void)
{
    int i;
    int sum = 0;  //sum的英文意思是“总和”
    for (i=1; i<=100; ++i)  //++是自加的意思, ++i相当于i = i + 1
    {
        sum = sum + i;  /*等价于sum += i;但是不建议这么写, 因为sum = sum + i看起来更清楚、更舒服*/
    }
    printf("sum = %d\n", sum);
    return 0;
}

输出结果是:
  sum = 5050

​   这个程序的功能是实现求 1+2+3+4+…+100 的和,如果不用循环,加一次就要一条语句,加 100 次就要 100 条语句。这里是从 1 加到 100,要是从 1 加到 10000 那就要 10000 条语句。但有了循环就很方便了,你想加到多少就加到多少,只要改一个参数就可以了。所以循环很重要。

步骤解析:

首先求解表达式1,即给变量i赋初值,i=1;表达式1只执行这一次,下面都不会再执行了。
然后求解表达式2,若 1<=100 成立,则执行 for 循环中的内嵌语句,即 sum=0+1。
然后执行第3步,变量 i 自加 1,即变量 i 由 1 变为 2。
然后再求解表达式22<=100 成立,则执行 for 循环中的内嵌语句,sum=0+1+2。
然后再执行第3步,变量 i 自加 1,即变量 i 由 2 变为 3。
然后再求解表达式2,即 3<=100 成立,则执行 for 循环中的内嵌语句,sum=0+1+2+3。
……

在这里插入图片描述

for的灵活性

递减运算符来递减计数器
#include <stdio.h>
int main(void)
{
	int i;

	for(i=5;i>0;i--)
	{
		printf("现在输出的是%d\r\n",i);
	}

    return 0;
}
计数器递增倍数
#include <stdio.h>
int main(void)
{
	int i;

	for(i=0;i<20;i=i+2)
	{
		printf("现在输出的是%d\r\n",i);
	}

    return 0;
}

在这里插入图片描述

可以用字符代替数字计数
#include <stdio.h>
int main(void)
{
	char i;

	for(i='a';i<='z';i++)
	{
		printf("现在输出的是%c\r\n",i);
	}

    return 0;
}

在这里插入图片描述

测试多样条件
#include <stdio.h>
int main(void)
{
	int i;
	//for(i=0;i<=6;i++) 替换
	for(i=0;i*i*i<=216;i++)
	{
		printf("现在输出的是%d\r\n",i);
	}

    return 0;
}

在这里插入图片描述

递增的量几何增长
#include <stdio.h>
int main(void)
{
	double i;

	for(i =100.0;i<150.0;i=i*1.1)
	{
		printf("现在输出的是%.2f\r\n",i);
	}

    return 0;
}

在这里插入图片描述

双条件
#include <stdio.h>
int main(void)
{
	int x;
	int y=55;

	for(x = 1; y <= 75; y = (++x * 5) + 50)
	{
		printf("现在输出的x是%d,	y是%d\r\n",x,y);
	}

    return 0;
}

在这里插入图片描述

省略表达式

  可以省略一个或多个表达式(但是不能省略分号),只要在循环中包含能结束循环的语句即可。

  注意:不要造成死循环

省略第一个条件
#include <stdio.h>
int main(void)
{
	int x = 1;

	for(; x <= 5; ++x)
	{
		printf("现在输出的x是%d\r\n",x);
	}

    return 0;
}

在这里插入图片描述

省略第二个条件
#include <stdio.h>
int main(void)
{
	int x;

	for(x = 1;; ++x)
	{
		printf("现在输出的x是%d\r\n",x);
		if(x == 5)
			return ;
	}

    return 0;
}

在这里插入图片描述

省略第三个条件
#include <stdio.h>
int main(void)
{
	int x;

	for(x = 1; x <= 5; )
	{
		printf("现在输出的x是%d\r\n",x);
		++x;
	}

    return 0;
}

在这里插入图片描述

死循环
#include <stdio.h>
int main(void)
{
	for(;;);   
    return 0;
}
初值选择
#include <stdio.h>
int main(void)
{
	int x = 1;

	for(printf("这是一个表达式\r\n");x<5;++x)
	{
		printf("x的值是%d\r\n",x);
	}

    return 0;
}

在这里插入图片描述

简易控制循环值
#include <stdio.h>
int main(void)
{
	int x = 1;
	int num,val;
	printf("本次循环最大值为:\r\n");
	scanf("%d",&val);
	printf("每次循环递增值为:\r\n");
	scanf("%d",&num);

	for(printf("这是一个表达式\r\n");x<val;x=x+num)
	{
		printf("x的值是%d\r\n",x);
	}

    return 0;
}

在这里插入图片描述

逗号运算符

​ 逗号运算符扩展了for循环的灵活性,以便在循环头中包含更多的表达式。

​ 例如演示了一个打印一类邮件资费。

#include <stdio.h>
int main(void)
{
    const int FIRST_OZ = 46; // 2013 rate
    const int NEXT_OZ = 20;  // 2013 rate
    int ounces, cost;
    
    printf(" ounces  cost\n");
    for (ounces=1, cost=FIRST_OZ; ounces <= 16; ounces++,
         cost += NEXT_OZ)
        printf("%5d   $%4.2f\n", ounces, cost/100.0);
    
    return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

do while

​   while循环和 for循环都是入口条件循环,即在循环的每次迭代之前检查测试条件,所以有可能根本不执行循环体中的内容。C语言还有出口条件循环,即在循环的每次迭代之后检查测试条件,这保证了至少执行循环体中的内容一次。这种循环被称为do while循环。

​   do while 语句创建一个循环,在expression为假或0之前重复执行循环体中的内容。do while语句是一种出口条件循环,即在执行完循环体后才根据测试条件决定是否再次执行循环。因此,该循环至少必须执行一次。

格式:

do
{         
   statement;
}While(expression );

在expression为假或0之前,重复执行statement部分。
在这里插入图片描述
例子:

#include <stdio.h>
int main()
{
	int i=1,sum=0;
	do
	{
		sum+=i;
		i++;	
	}while(i<=24);
	printf("%d",sum);
	return 0; 
 } 

在这里插入图片描述
如果是while写的

#include <stdio.h>
int main(void)
{
    const int secret_code = 13;
    int code_entered;
    
    printf("To enter the triskaidekaphobia therapy club,\n");
    printf("please enter the secret code number: ");
    scanf("%d", &code_entered);
    while (code_entered != secret_code)
    {
        printf("To enter the triskaidekaphobia therapy club,\n");
        printf("please enter the secret code number: ");
        scanf("%d", &code_entered);
    }
    printf("Congratulations! You are cured!\n");
    
    return 0;
}

如果是do while写的:

#include <stdio.h>
int main(void)
{
    const int secret_code = 13;
    int code_entered;
    
    do
    {
        printf("To enter the triskaidekaphobia therapy club,\n");
        printf("please enter the secret code number: ");
        scanf("%d", &code_entered);
    } while (code_entered != secret_code);
    printf("Congratulations! You are cured!\n");
    
    return 0;
}

在这里插入图片描述
  do while循环在执行完循环体后才执行测试条件,所以至少执行循环体一次;而 for 循环或 while循环都是在执行循环体之前先执行测试条件。do while循环适用于那些至少要迭代一次的循环。例如,下面是一个包含do while循环的密码程序伪代码:

在这里插入图片描述

在这里插入图片描述

如何选择循环

  如何选择使用哪一种循环?首先,确定是需要入口条件循环还是出口条件循环。通常,入口条件循环用得比较多,有几个原因。其一,一般原则是在执行循环之前测试条件比较好。其二,测试放在循环的开头,程序的可读性更高。另外,在许多应用中,要求在一开始不满足测试条件时就直接跳过整个循环。
         那么,假设需要一个入口条件循环,for循环还是while循环?这取决于个人喜好,因为二者皆可要让for循环看起来像while循环,可以省略第1个和第3个表达式。例如:
for ( ;  test  ; )
与下面的while效果相同: while (  test  )
要让while循环看起来像for循环,可以在while循环的前面初始化变量,并在while 循环体中包含更新语句。例如:
初始化;
while (测试)
{

其他语句

更新语句

}
与下面的for循环效果相同:

for(初始化 ;测试;更新)
     其他语句
       一般而言,当循环涉及初始化和更新变量时,用f循环比较合适,而在其他情况下用while循环好。对于下面这种条件,用while循环就很合适:
while (scanf("%d"&num) == 1)
对于涉及索引计数的循环,用for循环更适合。

例如: for (count = 1; count <= 100; count++)

嵌套循环

​   嵌套循环指在一个循环内包含另一个循环。嵌套循环常用于按行和列显示数据,也就是说一个循环处理一行中的所有列,另一个循环处理所有的行。

#include <stdio.h>
#define ROWS  6
#define CHARS 10
int main(void)
{
    int row;
    char ch;
    
    for (row = 0; row < ROWS; row++)             
    {
        for (ch = 'A'; ch < ('A' + CHARS); ch++) 
            printf("%c", ch);
        printf("\n");
    }
    
    return 0;
}

![image-202402111643
  第 9行开始的 for 循环被称为外层循环

​   第11行开始的for 循环被称为内层循环(innerloop)。

​   外层循环从row为0开始循环,到row为6时结束。

​   因此,外层循环要执行6次,row的值从 0变为 5。每次迭代要执行的第1条语句是内层的 for 循环,该循环要执行 10 次,在同一行打印字符 A~J:第2条语句是外层循环的 printf(“\n”);

​   该语句的效果是另起一行,这样在下一次运行内层循环时,将在下一行打印的字符。

​   注意,嵌套循环中的内层循环在每次外层循环迭代时都执行完所有的循环.内层循环一行打印10个字符,外层循环创建6行。

#include <stdio.h>
int main(void)
{
    const int ROWS = 6;
    const int CHARS = 6;
    int row;
    char ch;
    
    for (row = 0; row < ROWS; row++)
    {
        for (ch = ('A' + row);  ch < ('A' + CHARS); ch++)
            printf("%c", ch);
        printf("\n");
    }
    
    return 0;
}

在这里插入图片描述

​   因为每次迭代都要把 row的值与’'相加,所以 ch在每一行都被初始化为不同的字符。然而,测试条件并没有改变,所以每行依然是以F结尾,这使得每一行打印的字符都比上一行少一个。

  • 23
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值