• 微信号
  • 微信号
您当前的位置:首页 > 学海无涯 > 茑语花香>C++ While及Do-while讲解与一本通平台讲解

C++ While及Do-while讲解与一本通平台讲解

孤峰 孤峰家 2023-09-21 58人阅读

今天,我来讲解一下 C++ 中 While 以及 Do-while 语句的作用,因为他俩的作用差不多,所以我就混在一起写了(我绝对不会告诉你我是懒得写两篇)。

拖更还不是因为考试...

While

while 的意思是直到,我们就可以非常轻松的看出它的意思,就是满足某种条件时执行其内部的代码,它的结构如下:

while(条件表达式) 语句;

或者是

while(条件表达式)

{

语句1;

语句2;

...

}

还有就是

while(条件表达式);

当 while 语句中的条件表达式成立时,我们就可以执行其中的语句,而当它不成立了,我们就会从 while 语句中退出来,继续执行后面的语句。while 在不确定循环次数时使用,例如输入一列数据,假设读取到了 E 就退出,那么我们可以使用 while 进行循环,判断读入的是否是 E,如果是就退出,否则继续读入,代码如下:

#include<iostream>

#include<cstdio>

using namespace std;

int **in()

{

char a;

while(cin>>a&&a!='E');//字符 a 满足不为 E 时继续循环,否则退出循环

printf("By - December\n");//退出循环后执行 while 后面的语句

return 0;

}

我们可以看到,while 的作用是很方便的,但是随之而来的肯定是其他问题。

Do - While

当你想让 while 循环至少先判断一次时,如果对 while 加上特判的话会显得有些麻烦,所以,C++ 中有一个看似跟 while 长得十分像的东西 do - while 一看它就不简单,还是分开来的,其实并不难,只不过它把要执行的程序放在了 while 的前面,do 的后面,例如:

#include<iostream>

#include<cstdio>

using namespace std;

int **in()

{

char a;

do

{

printf("By - December\n");

}while(cin>>a&&a!='E');//再 do - while 后面要加上冒号

return 0;

}

这段代码与上面的没有太大的区别,只不过一开始会输出一次,多输入几个字符会多弹出几个罢了......

一般来说,只要你学会了 while 语句,do - while 语句自然就十分容易了。

信息学奥赛一本通的题目

2020 - 2023,1085 - 1090,2024 - 2025

do - while 语句的一部分题与 while 语句重复了,可以使用 while 和 do - while 各写一遍,加强对这两个语句的理解与运用。不要像我一样 Ctrl + C + Ctrl + V 。

2020:【例4.5】第几项

这是一道十分典型的求项数的题目,三种循环都可以用,这里用 while 和 do - while 各写一个,代码如下:

while

#include<iostream>

using namespace std;

int **in()

{

int i=0,m,sum=0;//累加的数一定要初始化为0!!!

cin>>m;

while(sum<=m)//判断什么时候不满足这个条件

{

i++;//累加的数每次增加1

sum+=i;//每次sum累加i的数

}

cout<<i<<endl;//输出这个项

return 0;

}

do - while

#include<iostream>

using namespace std;

int **in()

{

int i=0,m,sum=0;

cin>>m;

do//先会执行一次

{

i++;

sum+=i;

}while(sum<=m);//判断是否满足这个条件

cout<<i<<endl;

return 0;

}

较好都写一遍

2021:【例4.6】较大公约数

这道题虽然使用暴力解决(也就是枚举除数,再用两个数分别除,看看是否余数都为零),但是它还有一个更加高级的方法,那就是辗转相除法,效率要比枚举快,推荐使用。

代码如下:

while

#include<iostream>

#include<cstdio>

using namespace std;

int **in()

{

int x,y,z;

scanf("%d%d",&x,&y);

if(x==y)//特判

{

printf("%d\n",x);

return 0;

}

if(x<y) swap(x,y);//将大数作为被除数

z=x;

while(x%y!=0)

{

x=y;

y=z%y;

z=x;

}//辗转相除法的核心代码

printf("%d\n",y);

return 0;

}

do - while(其实差不多)

#include<iostream>

#include<cstdio>

using namespace std;

int **in()

{

int x,y,z;

scanf("%d%d",&x,&y);

if(x==y)//特判

{

printf("%d\n",x);

return 0;

}

if(x<y) swap(x,y);//将大数作为被除数

z=x;

do

{

x=y;

y=z%y;

z=x;

}while(x%y!=0);//辗转相除法的核心代码

printf("%d\n",y);

return 0;

}

同样较好都写一遍(虽然十分相像...)

2022:【例4.7】**小n值

这一题因为不确定循环次数,所以使用 while 或 do - while 。

#include<iostream>

using namespace std;

int **in()

{

int i=0,m;

double sum=0;//要使用单/双精浮点数

cin>>m;

while(sum<m)//使用题目给出的条件进行判断

{

i++;

sum+=1.0/i;//求和

}

cout<<i<<endl;

return 0;

}

do - while 就不贴出来了,都是差不多的。

2023:【例4.8】数据统计

分别使用求出**小,较大值,再计算出平均值即可。

代码如下:

#include<iostream>

#include<cstdio>

using namespace std;

int **in()

{

int x,minn=1100,**xn=-1100,sum=0,tot=0;//初始化一定不能忘

while(scanf("%d",&x)!=EOF)//"!=EOF"是指判断输入是否成功

{

if(x<minn) minn=x;

if(x>**xn) **xn=x;

sum+=x;tot++;

}

printf("%d %d %.3f\n",minn,**xn,double(sum)/double(tot));

return 0;

}

1085:球弹跳高度的计算

当时是用 do - while 写的,所以(代码如下):

#include<iostream>

#include<cstdio>

using namespace std;

int **in()

{

double a,b,h;

int i=2;

scanf("%lf",&h);

a=h;

b=h/2.0;

do

{

a=a+2*b;

b=(1.0/2)*b;

i++;

}

while(i<=10);//按照步骤依次计算即可

printf("%g\n%g",a,b);

return 0;

}

这题本身不难,不会做的人多了,它也就变难了。只要你清楚了步骤就可以写出来。

1086:角谷猜想

此题难点:无,跟上一题是一样的,按照题目一步步做就绝对不会错。

代码如下:

#include<iostream>

using namespace std;

int **in()

{

int x,y,z;

cin>>x;

while(x!=1)//特判输入为1的情况

{

if(x%2==0)//如果是2的倍数

{

cout<<x<<"/2="<<x/2<<endl;

x=x/2;

}

else//如果不是2的倍数

{

cout<<x<<"*3+1="<<x*3+1<<endl;

x=x*3+1;

}

}

cout<<"End"<<endl;

return 0;

}

这题本身不难...

1087:级数求和

这就像是 2022 题的升级版,但实话是并没有太大的区别,仔细思考就可以想的到。

代码如下:

#include<iostream>

using namespace std;

int **in()

{

int k,n=1;

double sum=1;

cin>>k;

while(sum<=k)

{

n++;

sum+=1.0/n;

}

cout<<n<<endl;

return 0;

}

是不是很像 2022 的代码 ?

1088:分离整数的各个数

这里就需要仔细的思考才可以推导出这段代码。

这段代码的主要意义是截取出末尾的位数,并进行下一次的计算,整个设计都十分的巧妙。

代码如下:

#include<iostream>

#include<cstdio>

using namespace std;

int **in()

{

int a,n,b=10,c=0,s=0;

cin>>n;

do

{

a=(n%b-c)/(b/10);//截取

c=a;

s=a*(b/10)+s;//s用于判断这段数字是否截取完了

b=b*10;//扩大截取位

cout<<a<<" ";//输出

}

while(n>s);

return 0;

}

但是,如果你学习了字符串后,你一定会抛弃这种复杂,难以理解的算法的。因为字符串好理解还简单,代码如下:

#include<iostream>

#include<string>

#include<cstdio>

using namespace std;

int **in()

{

string x;

getline(cin,x);

int i,l=x.size();

for(i=l-1;i>=0;i--) cout<<x<<' ';

return 0;

}

又简洁,又易懂,是做题的不二选择。

1089:数字反转

这道题如果纯用数学方法的话,估计要想较久,这题使用字符串仍然要好用许多。

代码如下(数学方法):

#include<iostream>

using namespace std;

int **in()

{

int n,sum=0;

cin>>n;

if(n<0)

{

cout<<"-";

n=-n;

}

while(n)

{

sum=sum*10+n%10;//对正数进行反转

n/=10;

}

cout<<sum<<endl;

return 0;

}

但是这篇文章不是学字符串...

1090:含k个3的数

按照题目意义写,分离各个数位进行判断即可

代码如下:

#include<iostream>

using namespace std;

int **in()

{

int m,k,g,s,b,q,w,num=0;//累加的 sum 一定要清零!!!

cin>>m>>k;

w=m/10000;//分离万位

q=m%10000/1000;//分离千位

b=m%1000/100;//分离百位

s=m%100/10;//分离十位

g=m%10;//分离个位

if(g==3) num++;//判断个位是否为3

if(s==3) num++;//判断十位是否为3

if(b==3) num++;//判断百位是否为3

if(q==3) num++;//判断千位是否为3

if(w==3) num++;//判断万位是否为3

if(num==k&&m%19==0) cout<<"YES"<<endl;//如果有 k 个 3 且可以被 19 整除

else cout<<"NO"<<endl;//不满足时

return 0;

}

不难...

2024:【例4.10】末两位数

这道题乍一看,诶!还挺简单的啊?只要把这个计算出来然后取后两位不就成了吗?

但是,事实却并非如此,你要是这样做,肯定会超出空间限制(简称MLE),因为一个程序要在系统规定的空间大小内完成程序的执行。要知道空间复杂度的概念,它表示一个程序运行所需占用的空间大小,表示为 O(Memory) 的形式,其中 Memory 为占用空间,通常空间复杂度用于表示输入数据大小,如输入 2^31 ( 2,147,483,648 ) 这么大的数,int 类型就存不下了,因为 int 的存储范围为 ± 2 ^ 31 - 1 ( ± 2,147,483,647 ),要用 long long 类型存储,long long 的存储范围要比 int 大许多,为 ± 2 ^ 63 -1 ( ± 9,223,372,036,854,775,807 ) ,一旦存入的数据超过了这个此数据类型的范围,就会出现 溢出 现象,即值从极限大变为极限小,从极限小变为极限大,这样的反转,对程序危害极大,在计算空间复杂度时通常取计算过程中的较大值

这题如果计算出结果的空间复杂度为 : O (),超级恐怖,而说明 n 最坏情况下为 1999,这样算出来的数据,怎么可能存的下?

其结果为19027373411336818260390395849490...(此处省略6562个0)...00

那我们应该怎么解呢?想一下,我们在计算次方时真的需要保留所有位数吗?其实不用,百位以上对后两位根本没有影响,且它只要较后的两位数。所以,我们可以每次保留两位进行计算,这样就不会超出限制了。

代码也是十分简短 ( 但是为啥要放在 do - while 呢??? ) :

#include<iostream>

using namespace std;

int **in()

{

int i,n,sum=1;//初始化为1,否则无法乘

cin>>n;

for(i=1;i<=n;i++) sum=sum*1992%100;//每次取后两位并乘起来

cout<<sum<<endl;//直接输出

return 0;

}

只要思考好了就不是问题

2025:【例4.11】体操队

这题就一个答案。这不是明摆着直接算吗?根据题意可以知道结果为 301 个人,当然也可以用 while 求出来,枚举人数即可,代码如下:

#include<iostream>

using namespace std;

int **in()

{

int n=7;//人数不可能少于7人(这个优化没啥效果...)

while(true)//不停枚举

{

n+=2;//因为排成两行多一人说明人数为奇数,直接跳过偶数,增加速度(当然也没啥效果)

if(n%3==1&&n%4==1&&n%5==1&&n%6==1&&n%7==0)//是否满足给出条件

{

cout<<n<<endl;//如果满足就输出

return 0;//直接结束,不用继续干了

}

}

}

这样的题目也可以直接算...

并且有着更加简单的代码:

#include<iostream>

using namespace std;

int **in()

{

cout<<301<<endl;

return 0;

}

所以,301 就是答案了

题目都讲完了,你是否都会了呢?

转载:感谢您阅览,转载请注明文章出处“来源从小爱孤峰知识网:一个分享知识和生活随笔记录的知识小站”。

链接:C++ While及Do-while讲解与一本通平台讲解http://www.gufeng7.com/niaolang/1847.html

联系:如果侵犯了你的权益请来信告知我们删除。邮箱:119882116@qq.com

上一篇: C++ 入门讲解

下一篇: C++ 循环嵌套讲解