循环
题目:给你一个4位及以下的正整数,让你数一下这个整数是几位数,程序该如何设计
判断数的范围来决定它的位数
#include <stdio.h>
int main()
{
int a,n;
printf("请输入整数");
scanf("%d",&a);
if(a>999){
n=4;
}else{
if(a>99){ 注:因为从高处往下判断,所以不需要判断上上限呢。若反过来判断,>改为<即可。
n=3;
}else{
if(a>9){
n=2;
}else{
n=1;
}
}
}
printf("%d",n);
return 0;
}
题目:如何判断任意一个正整数的位数呢
三位数逆序的题
如352%100得到52,划掉了百分位(从左往右划) 如何知道100?
反过来(从右往左划)。如352/10得到35,划掉了个位。再35/10得到3........... 不断的划,直到没数可以划,在这个过程中计数,就得到了位数
程序实现:
#include <stdio.h>
int main()
{
int x;
int n=0;
printf("请输入正整数");
scanf("%d",&x);
n++;
x/=10;
while(x>0) { 注:当x>0的时候,不断地进行while大括号中的计算,直到x<=0为止。
n++;
x/=10; 注:循环体内要有改变条件的机会(这里是x/=10;)
}
printf("%d",n);
return 0;
}
while循环
流程图(while)
流程图(if)
while循环:
- 如果我们把while翻译作"当“。那么一个while循环的意思就是:当条件满足时。不断的重复循环体内的语句。
- 循环执行之前判断循环是否继续循环,所有有可能循环一次也没有被执行。
- 条件成立是循环继续的条件。
验证:
测试程序常使用边界数据,如有效范围两端的数据、特殊的倍数等
#include <stdio.h>
int main()
{
int x;
int n=0;
printf("请输入正整数");
scanf("%d",&x);
n++;
x/=10;
while(x>0) {
n++;
x/=10;
}
printf("%d",n);
return 0;
}
上面这个程序验证:
1.个位数;
2.10; 特殊的倍数
3.0; 范围两端的数,严格来说0不是正整数。
4.负数。 这里先不验证负数
验证的方法:
方法1.草稿上进行:
x n
10 0
1 1
0 2 循环结束
方法2.在程序适当的地方插入printf来输出变量的内容
#include <stdio.h>
int main()
{
int x;
int n=0;
printf("请输入正整数");
scanf("%d",&x);
n++;
x/=10;
while(x>0) {
n++;
x/=10;
printf("x=%d,n=%d\n",x,n);
}
printf("%d",n);
return 0;
}
如下:printf("hr1\n") 放这样一个输出,目的是看程序是否进来过,程序到哪呢 一些复杂的程序不方便调试的时候,采用此方法
数位数的算法:
1.用户输入x;
2.初始化n为0;
3.x=x/10,去掉个位;
4.n++;
5.如果x>0,回到3;
6.否则n就是结果。
do-while循环
- 再进入循环的时候不做检查,而是在执行完一轮循环体的代码之后,再来检查循环的条件是否满足,如果满足则继续下一轮循环,不满足则结束循环。
do
{
<循环体语句>
}while(<循环条件>); while后面一定有个分号,表示语句结束。 结束一个语句,要么是大括号要么是分号。
流程图:
do-while循环 (先进循环体) while循环(先判断条件)
两种循环
- do-while循环和while循环很像,区别是在循环体执行结束的时候才来判断条件。也就是说,无论如何,循环都会执行至少一遍,然后再来判断条件。与while循环相同的是,条件满足时执行循环,条件不满足时结束循环。
例:do-while几位数
#include <stdio.h>
int main()
{
int n=0;
int x;
printf("请输入正整数");
scanf("%d",&x);
do{
n++;
x/=10;
}
while(x>0);
printf("位数:%d",n);
return 0;
}
循环计算
log2X 即2多少次方等于X
#include <stdio.h>
int main()
{
int x;
int ret=0;
printf("请输入x的值");
scanf("%d",&x);
int t=x; 注:因为X的值一直在变,所以在此处定义了t变量,为了后面 printf("2的%d次方等于%d",ret,t) ; 这是一个小套路:计算之前先保存原始的值,后面可能会用到
while(x>1){
x/=2;
ret++;
}
printf("2的%d次方等于%d",ret,t) ;
return 0;
}
计数循环1
#include <stdio.h>
int main()
{
int count=100;
while(count>=0){
printf("%d\n",count);
count--;
}
printf("发射!\n");
return 0;
}
思考如上程序:
- 这个循环需要执行多少次?
- 循环停下来的时候,有没有输出最后的0?
- 循环结束后,count的值是多少?
小套路:如果要模拟运行一个很大次数的循环,可以模拟较少的循环次数,然后做出推断。
草稿循环如下:取count=3
count printf
3 3
2 2
1 1
0 0
-1
回答:当count=3时
1.有4个输出,循环走了四轮
2.0有输出
3.当循环结束的时候,count=-1
推到:当count=100时
1.执行101次
2.0有输出
3.循环结束后,count的值是-1
计数循环2
#include <stdio.h>
int main()
{
int count=100;
while(count>=0){
count--; count--; 和 printf("%d\n",count); 交换下位置,再思考下上面三个问题。
printf("%d\n",count);
}
printf("发射!\n");
return 0;
}
以count=3做推算
count printf
3
2 2
1 1
0 0
-1 -1
第一个输出的值和最后一个输出的值变了
猜数游戏
- 让计算机来想一个数,然后让用户来猜,用户每输入一个数,就告诉他是大了还是小了,直到用户猜中为止,最后还要告诉用户猜了多少次。
- 因为需要不断重复让用户猜,所以需要用到循环。
- 在实际写出程序之前,我们可以先用文字描述程序的思路。
- 核心重点是循环的条件
- 人们往往会考虑循环终止的条件
- 计算机先想一个数,记在变量number里
- 一个负责记次数的变量count初始化为0
- 让用户输入一个数字a
- count递增(加1)
- 判断a和number的关系,如果大了,就输出大,如果a小,就输出小了
- 如果a和number是不相等的,程序返回到第三步 循环的条件是a和number不想等
- 否则程序输出猜中和次数,然后结束
随机数
- 每次召唤rand()就得到一个随机的整数
%100
- x%n的结果是[0,n-1]的一个整数;
- 如:123%100结果是23;
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
srand(time(0));
int number=rand()%100+1;
int count=0;
int a;
printf("我已经想好了一个1到100之间的数呢\n");
do{
printf("再猜猜这个数\n");
scanf("%d",&a);
count++;
if(a>number){
printf("大了!\n");
}else{
printf("小了!\n");
}
}while(a!=number) ;
printf("您用了%d次猜中猜到了这个数\n",count);
return 0;
}
算平均数
- 让用户输入一系列的正整数,最后输入-1表示输入结束,然后程序计算出这些数字的平均数,输出输入数字的个数和平均值
- 变量-算法-流程图-程序
变量:
- 一个记录读到的整数的变量
- 平均要怎么算?
- 只需要每读到一个数,就把它加到一个累加的变量里,到全部数据读完,在拿它去除读到数的个数就可以
- 一个变量记录累加的结果,一个变量记录读到数的个数
算法:
- 初始化变量sum和count为0;
- 读入number;
- 如果number不是-1,则将number加入sum,并将count+1回到2;
- 如果number是-1,则计算和打印sum和count(注意换成浮点来计算)
流程图;
程序:
do-while循环
#include <stdio.h>
int main()
{
int sum,count=0;
int number;
do{
printf("请输入一个正整数\n");
scanf("%d",&number);
if(number!=-1){
count++;
sum+=number;
}
}while(number!=-1);
printf("平均值为%lf",1.0*sum/count);
return 0;
}
while循环
#include <stdio.h>
int main()
{
int sum,count=0;
int number;
printf("请输入一个正整数\n");
scanf("%d",&number);
while(number!=-1){
count++;
sum+=number;
printf("请输入一个正整数\n");
scanf("%d",&number); 没有这句scanf("%d",&number); 程序会死循环
}
printf("平均值为%lf",1.0*sum/count);
return 0;
}
整数的逆序
整数的分解
- 一个整数是由1至多位数字组成的,如何分解出整数的各个位上的数字,然后加一计算
- 对一个整数做%10的操作,就得到了它的个位数
- 对一个整数做/10的操作,就去掉了它的个位数
- 然后再做%10,就得到原来数的十位数呢
- 以此类推;
- 输入一个正整数,输出逆序的数
- 结尾0的处理
700逆序为007程序:
#include <stdio.h>
int main()
{
int x;
printf("请输入x的值\n");
scanf("%d",&x);
int digit;
int ret;
while(x>0){
digit=x%10;
printf("%d",digit); 注:这里%d后面一定要没有\n,才能输出007
ret=ret*10+digit; 注:原来的结果往左移一位,加上新的digit
x/=10;
}
// printf("%d",ret); 使用快捷键ctrl+/快速将该行变为注释
return 0;
}
700逆序为7的程序:
#include <stdio.h>
int main()
{
int x;
printf("请输入x的值\n");
scanf("%d",&x);
int digit;
int ret;
while(x>0){
digit=x%10;
// printf("%d",digit);
ret=ret*10+digit;
x/=10;
}
printf("%d",ret);
return 0;
}
第三种循环:
阶乘
- n!=1x2x3x4x...xn
- 写一个程序,让用户输入n,然后计算输出n!
- 变量:
- 显然读用户的输入需要一个int 的n,然后计算的结果需要用一个变量保存,可以是int的factor,在计算中需要有一个变量不断的从1递增到n,那可以是int的i
#include <stdio.h>
int main()
{
int n;
printf("请输入n\n");
scanf("%d",&n);
int fact=1;
int i=1;
while(i<=n){
fact=fact*i;
i++;
}
printf("%d!的值为%d",n,fact);
return 0;
}
for循环实现:
#include <stdio.h>
int main()
{
int n;
printf("请输入n\n");
scanf("%d",&n);
int fact=1; 小套路:做求和的程序时,记录结果的变量应该初始化为0,做乘积的程序时,记录结果的变量应该初始化为1
int i=1;
for(i=1;i<=n;i++){ i=1是初始条件;i<=n是循环继续的条件;i++是循环每一轮要做的事情
fact*=i;
}
printf("%d!的值为%d",n,fact);
return 0;
}
for循环
- for循环像一个计数循环:设定一个计数器,初始化它,然后在计数器到达某个数之前,重复执行循环体,而每执行一轮循环,计数器值以一定步进进行调整,比如加1或者减1
- for(i=0;i<5;i=i+1){ 注:for循环里三个条件之间用的;
printf("%d",i);
}
for读成对于
- for(count=10;count>0;count--)
- 就读成:对于一开始的count=10,当count大于0时,重复做循环体,,第一轮循环在做完循环体内语句后,使得count--
循环次数
- for(i=0,i<n,i++)
- 则循环的次数是n,而循环结束以后,i的值是n。循环的控制变量i,是选择从0开始还是从1开始,是判断i<n还是i<=n,对循环的次数,循环结束后变量的值都有影响。
for==while
for(i=1,i<=1,i++){
fact*=1;
}
==
int i=1;
while(i<=n){
fact*=1;
i++;
}
流程图:
for循环
for(初始动作;条件;每轮动作){
}
- for中的每一个表达式都是可以省略的
如:for(;条件;)==while(条件)
Tips:
- 如果有固定次数,用for
- 如果必须执行一次,用do-while
- 其他情况用while
循环控制
素数:只能被1和自己整除的数,不包括1
如:2,3,5,7,11,13,17...
判断是否为素数
#include <stdio.h>
int main()
{
int x;
printf("请输入X");
scanf("%d",&x);
int i;
int isPrime=1;
for(i=2;i<x;i++){
if(x%i==0){
isPrime=0;
break; 跳出循环
}
}
if(isPrime==0){
printf("不是素数");
}else{
printf("是素数");
}
return 0;
}
break&continue
- break:跳出循环
- continue:跳出循环这一轮剩下的语句,进入下一轮
嵌套的循环
循环里面还是循环
注:每个循环应该使用不一样的变量
例:如何写程序输出100以内的素数?
#include <stdio.h>
int main()
{
int x;
int i;
for(x=1;x<100;x++) {
int isPrime=1;
for(i=2;i<x;i++){
if(x%i==0){
isPrime=0;
break;
}
}
if(isPrime==1){
printf("%d\n",x);
}
}
return 0;
}
输出前50个素数
#include <stdio.h>
int main()
{
int x;
int i;
int cnt=0;
for(x=1;cnt<50;x++) {
int isPrime=1;
for(i=2;i<x;i++){
if(x%i==0){
isPrime=0;
break;
}
}
if(isPrime==1){
cnt++;
printf("%d\t",x);
if(cnt%5==0){ 注:每5个数字一行
printf("\n");
}
}
}
return 0;
}
离开多重循环
例:凑硬币
如何用1角、2角和5角的硬币凑出10元以下的金额呢?
计算1块钱
#include <stdio.h>
int main()
{
int x=1;
int a;
int b;
int c;
for(a=1;a<x*10;a++){
for(b=1;b<x*10/2;b++){
for(c=1;c<c*10/5;c++){
if(a+2*b+5*c==x*10) {
printf("%d个一角加%d个2角加%d个5角等于%d块钱\n",a,b,c,x);
}
}
}
}
return 0;
}
当出现第一个结果时,输出结果,离开循环
int main()
{
int x=5;
int a;
int b;
int c;
int exit=0;
for(a=1;a<x*10;a++){
for(b=1;b<x*10/2;b++){
for(c=1;c<c*10/5;c++){
if(a+2*b+5*c==x*10) {
printf("%d个一角加%d个2角加%d个5角等于%d块钱\n",a,b,c,x);
exit=1;
break; 离开第一个for循环
}
}
if(exit==1){
break; 离开第二个for循环
}
}
if(exit==1){
break; 离开第三个for循环
}
}
return 0;
}
上面例子使用了“接力break”,蓝色部分,才跳出三个for循环
break和continue 只能对它所在的那层循环做
第二种方法跳出嵌套循环
goto
嵌套循环的内侧跳到最外侧可以使用goto
目前只把goto用在这种类似案例里,其他案例不要使用goto,会破坏程序的一体型。
#include <stdio.h>
int main()
{
int x=5;
int a;
int b;
int c;
for(a=1;a<x*10;a++){
for(b=1;b<x*10/2;b++){
for(c=1;c<c*10/5;c++){
if(a+2*b+5*c==x*10) {
printf("%d个一角加%d个2角加%d个5角等于%d块钱\n",a,b,c,x);
goto out; 跳到out这个位置
}
}
}
}
out: out位置在这里
return 0;
}
循环应用
1.求和
分析:分子都是1,分母递增加1。起点是1和终点是n很明确,用for循环
#include <stdio.h>
int main()
{
int n=100;
int i;
double sum=0;
for(i=1;i<=n;i++){
sum+=1.0/i; 在这里,如果是1/i,则值一定是0。所以写成1.0/i,两个数相除,如果其中一个是浮点数,那个另一个也会变成浮点数,结果也是浮点数。
}
printf("f(%d)=%f",n,sum);
return 0;
}
一正一负求和
#include <stdio.h>
int main()
{
int n=10;
int i;
double sum=0;
double sign=1;
for(i=1;i<=n;i++){
sum+=sign/i;
sign=-sign;
}
printf("f(%d)=%f",n,sum);
return 0;
}
正序输出某个正整数(每个数字后面带空格)
取出每一位数字
#include <stdio.h>
int main()
{
int x=3234;
int i;
do{
i=x%10;
printf("%d ",i); %d后面有个空格
x/=10;
}while(x>0);
return 0;
}
去掉输出最后一位后面的空格
#include <stdio.h>
int main()
{
int x=3234;
int i;
do{
i=x%10;
printf("%d",i);
if(x>9){
printf(" ");
}
x/=10;
}while(x>0);
printf("\n");
return 0;
}
取出每一位数字的程序中最终结果中数字是逆序的。那正序输出某个正整数,可以先给这个数求逆,在用上面程序输出。逆逆得正
#include <stdio.h>
int main()
{
int x=3234;
int i;
int t=0;
int y;
do{
y=x%10;
t=t*10+y;
x/=10;
}while(x>0);
printf("t=%d\n",t); 逆序
x=t;
do{
i=x%10;
printf("%d",i);
if(x>9){
printf(" ");
}
x/=10;
}while(x>0);
printf("\n");
return 0;
}
上面程序,当x=700时,输出是7,而不是007
700输出为7 0 0
#include <stdio.h>
int main()
{
int x=700;
int t;
int a=x;
int mask;
int cnt=0;
do{
a/=10;
cnt++;
}while(a>0);
mask=pow(10,cnt-1); 10的cnt-1次方
do{
t=x/mask;
printf("%d",t);
if(mask>9){
printf(" ");
}
x%=mask;
mask/=10;
}while(mask>0);
return 0;
}
第二种计算上面程序中mask值的方法
#include <stdio.h>
int main()
{
int x=700;
int t;
int a=x;
int mask=1;
int cnt=0;
do{
a/=10;
mask*=10;
}while(a>9);
do{
t=x/mask;
printf("%d",t);
if(mask>9){
printf(" ");
}
x%=mask;
mask/=10;
}while(mask>0);
return 0;
}
如果x=1,上面程序计算的mask值是10。说明mask计算错误
do-while循环改为while循环
#include <stdio.h>
int main()
{
int x=1;
int t;
int a=x;
int mask=1;
int cnt=0;
while(a>9){
a/=10;
mask*=10;
}
do{
t=x/mask;
printf("%d",t);
if(mask>9){
printf(" ");
}
x%=mask;
mask/=10;
}while(mask>0);
return 0;
}
求最大公约数
输入两个数a,b,输出他它们的最大公约数
方法1:枚举法
#include <stdio.h>
int main()
{
int a;
int b;
int min;
int i=1;
int ret=0;
scanf("%d %d",&a,&b);
if(a<b){
min=a;
}else{
min=b;
}
for(i=1;i<min;i++)
{
if(a%i==0){
if(b%i==0){
ret=i;
}
}
}
printf("最大公约数为%d",ret);
return 0;
}
方法2:辗转相除法
1.如果b等于0,计算结束,a就是最大公约数;
2.否则计算a/b的余数,让a等于b,而b等于那个余数;
3.回到第一步。
#include <stdio.h>
int main()
{
int a,b;
int t;
scanf("%d %d",&a,&b);
while(b!=0){
t=a%b;
a=b;
b=t;
}
printf("gcd=%d",a);
return 0;
}