@TOC
5.1第三种循环
5.1.1for循环:这是最古老的循环,确实样子看上去有点古怪
阶乘 n!=123*4...*n 写出一个程序,让用户输入n,然后计算输出n! 变量: 显然读用户的输入需要一个int的n,然后计算的结果需要用一个变量保存,可以是int的factor,在计算中需要有一个变量不断的从1增加到n,那可以是int的i 代码:
#include<stdio.h>
int main()
{
int number;
int i=1;
int sun=1;
scanf("%d",&number);
while(i <= number)
{
sun=sun*i;
i++;
}
printf("%d",sun);
}
在c语言中有一种语句叫for语句,可以直接使变量自加。 代码:
#include<stdio.h>
int main()
{
int number;
scanf("%d",&number);
int sum=1;
for(int i=1;i<=number;i++)
{
sum=sum*i;
}
printf("%d",sum);
}
for循环 for循环像一个计数循环:设定一个计数器,初始化它,然后在计数器到达某值之前,重复执行循环体,而每执行一轮循环,计数器值以一定步数进行调整,比如加1或减1。 for(i=0;i<5;i++) { printf("%d",i); } for=对于 for(count=10;count>0;count--) 就读成:“对于一开始的count=10,当count>10时,重复做循环体,每一轮循环在做完循环体内语句后,使得count--” 小套路 做求和的程序时,记录结果的变量应该初始化为0,而做求积的变量时,记录结果的变量应该初始换为1 循环控制变量i只在循环里被使用了,在循环外面它没有任何用处。因此,我们可以把变量i的定义写到for语句里面去 int n; scanf("%d",&n); int fact=1; for(int i=1;i<n;i++) { fact*=i; } for == while for(int i=1;i<=n;i++) { fact*=i; } 等价于: int i=1; while(i<=n) { fact*=i; i++ } for循环 for循环每一个表达式都是可以省略的 for(;条件;) == while(条件) 循环次数 for(i=0;i<n;i++) 则循环的次数是n,而循环结束以后,i的值是n。循环的控制变量i,是选择从0开始还是从1开始,是判断i<n还是判断i<=n,对循环的次数,循环结束后变量的值都有影响 Tips for loops 如果有固定次数,用for 如果必须执行一次,用do_while 其他情况用while
5.2循环控制
5.2.1循环控制:如何用break和continue来控制循环
素数 只能被1和自己整除的数,不包括1 2,3,5,7,11,13,17... 代码:
#include<stdio.h>
int main()
{
int x;
scanf("%d",&x);
int isPream=1;
for(int i=2;i<x;i++)
{
if(x%i==0)
{
isPream=0;
break;
}
}
if(isPream==1)
{
printf("是素数");
}
else
{
printf("不是素数");
}
}
break vs continue
break:跳出循环
continue:跳过循环这一轮剩下的语句进入下一轮
5.2.2循环的切套:在循环里面还是循环
100以内的素数 如何写程序输出100以内的素数? 代码:
#include<stdio.h>
int main()
{
for(int x=2;x<=100;x++)
{
int isPream=1;
for(int i=2;i<x;i++)
{
if(x%i==0)
{
isPream=0;
}
}
if(isPream==1)
{
printf("%d ",x);
}
}
}
循环的嵌套 循环里面还是循环 前五十个素数 如何写程序输出前50个素数 代码:
#include<stdio.h>
int main()
{
int count=0;
for(int x=2;count<50;x++)
{
int isPream=1;
for(int i=2;i<x;i++)
{
if(x%i==0)
{
isPream=0;
}
}
if(isPream==1)
{
count++;
printf("%d\t",x);
if(count%5==0)
{
printf("\n");
}
}
}
return 0;
}
5.2.3从嵌套的循环中跳出:break只能跳出其所在的循环
嵌套循环时的break 凑硬币 如何用1角2角和 5角的硬币凑出10元以下的金额呢? 代码
#include <stdio.h>
int main()
{
int x;
scanf("%d", &x);
int one, two, five;
for(one = 0; one <= x*10; one++)
{
for(two = 0; two <= x*10/2; two++)
{
for(five = 0; five <= x*10/5; five++)
{
if(one + two*2 + five*5 == x*10)
{
printf("%d元需要%d个一角%d个二角%d个五角\n",x, one, two, five);
}
}
}
}
return 0;
}
如果我们想找到一个结果就输出我们可以使用break,但是因为break只能跳出一个for循环所以要用多个break跳出循环。
#include <stdio.h>
int main()
{
int x;
int sum = 0;
scanf("%d", &x);
int one, two, five;
for(one = 0; one <= x*10; one++)
{
for(two = 0; two <= x*10/2; two++)
{
for(five = 0; five <= x*10/5; five++)
{
if(one + two*2 + five*5 == x*10)
{
printf("%d元需要%d个一角%d个二角%d个五角\n",x, one, two, five);
sum=1;
break;
}
}
if(sum==1)
{
break;
}
}
if(sum==1)
{
break;
}
}
return 0;
}
goto 还有一种语句叫goto语句: 代码:
#include <stdio.h>
int main()
{
int x;
scanf("%d", &x);
int one, two, five;
for(one = 0; one <= x*10; one++)
{
for(two = 0; two <= x*10/2; two++)
{
for(five = 0; five <= x*10/5; five++)
{
if(one + two*2 + five*5 == x*10)
{
printf("%d元需要%d个一角%d个二角%d个五角\n",x, one, two, five);
goto end;
}
}
}
}
end:
return 0;
}
在要跳出的地方放一个goto 在goto后面放一个标号,在想要跳出的地方再放一个标号,成立后就会跳到标号的位置。但是尽量少用goto语句: 代码可读性降低 破坏程序的线性结构 传统的程序代码通常按照从上到下的顺序依次执行,这种线性结构符合人类的思维习惯,便于理解。而 goto 语句可以让程序跳转到任意指定的标签处继续执行,这就打破了这种线性的执行顺序。例如在一个包含多个 goto 跳转的程序中,阅读代码时很难按照正常的逻辑顺序去理解程序的执行流程,需要不断在代码中来回查找跳转的目标位置。 增加理解代码逻辑的难度 当代码中存在多个 goto 语句,且跳转关系复杂时,代码的逻辑会变得错综复杂。特别是在大型项目中,不同模块之间可能存在相互跳转,这使得理解代码的整体逻辑变得非常困难,甚至可能导致对代码功能的误解。 代码可维护性变差 修改代码时容易出错 如果需要对使用了 goto 语句的代码进行修改,例如添加或删除一些代码逻辑,很容易因为 goto 语句的跳转关系而影响到其他部分的代码。一个小小的修改可能会导致 goto 语句跳转到错误的位置,从而引发难以调试的错误。 不利于代码的扩展 随着项目的发展,可能需要对代码进行扩展,添加新的功能或逻辑。使用 goto 语句的代码由于其跳转关系的复杂性,很难在不破坏原有逻辑的前提下进行扩展。新添加的代码可能会干扰原有的 goto 跳转,导致代码的稳定性下降。 违反结构化编程原则 结构化编程的优势 结构化编程强调使用顺序、选择和循环三种基本结构来构建程序,这三种结构具有清晰的逻辑和明确的入口与出口,使得程序的结构更加清晰、易于理解和维护。而 goto 语句可以随意跳转,破坏了这种结构化的编程方式。 影响代码的模块化和抽象 良好的代码应该具有模块化和抽象的特点,每个模块负责完成特定的功能,模块之间通过清晰的接口进行交互。goto 语句的使用可能会使代码的模块化和抽象性变差,因为它可以跨越模块的边界进行跳转,使得模块之间的独立性降低,增加了代码的耦合度。 调试困难 难以跟踪程序执行流程 在调试使用了 goto 语句的代码时,由于程序的执行路径不固定,很难通过单步调试等方式准确跟踪程序的执行过程。调试器在遇到 goto 语句时会直接跳转到目标位置,这使得调试人员难以把握程序在不同时刻的状态。 增加定位错误的难度 当程序出现错误时,由于 goto 语句的跳转关系复杂,很难确定错误发生的具体位置和原因。错误可能是由于 goto 语句跳转到了错误的代码段,或者在跳转过程中导致了某些变量的状态异常,但很难通过常规的调试方法快速定位这些问题。