下面对于while循环、do-while循环、for循环相关的知识进行学习记录
4.1判断是几位数
#include<stdio.h>
int main(){
int x;
scanf("%d",&x);
if(x>999) {
printf("4");
}else if(x>99){
printf("3");
}else{
printf("2");
}
}
这个程序只能判断2位,3位,4位的数,如果很多位数,比如123344557676879955…怎么办?
#include<stdio.h>
int main(){
int x,count=0;
scanf("%d",&x);
count++;//处理0的问题 输入0应该输出1
x=x/10;
while(x>0) {
count++;
x=x/10;
}
printf("%d",count);
}
while循环
·如果我们把while翻译作“当”,那么一个while循环的意思就是:当条件满足时,不断地重复循环体内的语句。
·循环执行之前判断是否继续循环,所以有可能循环一次也没有被执行。
·条件成立是循环继续的条件。
如果没有外面的运算?
#include<stdio.h>
int main(){
int x,count=0;
scanf("%d",&x);
while(x>0) {
count++;
x=x/10;
}
printf("%d",count);
}
当输入352 输出3 结果正确
当输入0 输出0 结果错误
删掉外面的运算之后的程序处理不了0的问题
验证
·测试程序常使用边界数据,如有效范围两端的数据、特殊的倍数等
如: ·个位数、10、0、负数
do-while循环
·在进入循环的时候不做检查,而是在执行完一轮循环体的代码之后,再来检查循环的条件是否满足,如果满足则继续下一轮循环,不满足则结束循环
do{
<循环体语句>
}while(<循环条件>);
用do-while循环实现
#include<stdio.h>
int main(){
int x,count=0;
scanf("%d",&x);
do{
count++;
x=x/10;
}while(x>0);//后面需要有分号
printf("%d",count);
}
两种循环
·do-while循环和while循环很像,区别是在循环体执行结束的时候才来判断条件。也就是说,无论如何,循环都会执行至少一遍,然后再来判断条件。与while循环相同的是,条件满足时执行循环,条件不满足时结束循环。
4.2循环计算 计算log2(X)
#include<stdio.h>
int main(){
int x,ret=0;
scanf("%d",&x);
int t = x; //保存原始值
while(x>1){
x = x/2;
ret++;
}
printf("log2 of %d is %d",t,ret);//此时x的值已经改变了,所以需要在前面保存他的值
}
4.3猜数游戏
·让计算机随机产生一个数,然后让用户来猜,用户每输入一个数,就告诉她是大了还是小了,直到用户猜中为止,最后还要告诉用户他猜了多少次。
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main(){
srand(time(0));
int number=rand()%100;//0-99
int a,count=0;
scanf("%d",&a);
count++;
while(number!=a){
count++;
if(a>number){
printf("too big\n");
}else if(a<number){
printf("too small\n");
}else{
break;
}
scanf("%d",&a);
}
printf("right!你用了%d次就猜对了\n",count);
}
随机数
·每次使用rand()就得到一个随机的整数
%100
·x%n的结果是[0,n-1]的一个整数
4.4算平均数
·用户输入一系列的正整数,最后输入-1表示输入结束,然后程序计算出这些数字的平均数,输出输入的数字的个数和平均数
#include<stdio.h>
int main(){
int number,count=0,sum=0;
scanf("%d",&number);
while(number!=-1){
sum+=number;
count++;
scanf("%d",&number);
}
double avg = sum*1.0/count;
printf("%f",avg);
}
4.5整数逆序
#include<stdio.h>
int main(){
int x,digit,ret=0;
scanf("%d",&x);
while(x>0){
digit=x%10;//分离出来的每一位的数字
ret=ret*10+digit;
printf("x=%d digit=%d ret=%d\n",x,digit,ret);
x=x/10;
}
}
使用整数的分解的思想,取出x的每一位数字来进行逆序的操作
for循环
4.6阶乘
n!=1×2×3×…×n
用while循环实现
#include<stdio.h>
int main(){
int n,p=1;
scanf("%d",&n);
while(n>0){
p=p*n;
n--;
}
printf("%d",p);
}
用for循环实现
#include<stdio.h>
int main(){
int n,p=1;
scanf("%d",&n);
if(n==0){
p=1;
}
for(int i=1;i<=n;i++){
p=p*i;
}
printf("%d",p);
}
·for循环像一个计数循环:设定一个计数器,初始化它,然后在计数器到达某值之前,重复执行循环体,而每执行一轮循环,计数器值以一定步进进行调整,比如加1或者减1。如:
for(i=0;i<5;i=i+1){
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(初始动作;条件;每轮的动作){
}
·for中的每一个表达式都是可以省略的
for(;条件;)==while(条件)
tips
·如果有固定次数,用for
·如果必须执行一次,用do-while
·其他情况用while
4.7素数
只能被1和自己整除的数,不包括1.
2,3,5,7,11,13,17,19…
#include<stdio.h>
int main(){
int x;//x是否为素数
scanf("%d",&x);
int isPrime=1;
for(int i=2;i<x;i++){
if(x%i==0){//x不是一个素数
isPrime=0;
break;
}
}
if(isPrime){
printf("x=%d是素数",x);
}else{
printf("x=%d不是素数",x);
}
}
break VS continue
·break:跳出循环
·continue:跳过循环这一轮剩下的语句进入下一轮
嵌套的循环
·循环里面还是循环
4.8 100以内的素数
#include<stdio.h>
int main(){
for(int i=2;i<=100;i++){
int isPrime=1;//注意要卸载循环里面 对于每一个数字都需要初始化isPrime=1
for(int j=2;j<i;j++){
if(i%j==0){
isPrime=0;
break;
}
}
if(isPrime){
printf("i=%d是素数\n",i);
}
}
}
4.9 输出前50个素数
#include<stdio.h>
int main(){
int x=2,count=0;
while(count<50){
int isPrime=1;
for(int i=2;i<x;i++){
if(x%i==0){
isPrime=0;
break;
}
}
if(isPrime){
count++;//是素数才+1
printf("%d是素数\n",x);
}
x++;
}
}
4.10 凑硬币
·如何用1角、2角和5角的硬币凑出10元以下的金额呢
#include<stdio.h>
int main(){
int x;
//i:one j:two k: five
scanf("%d",&x);
for(int i=1;i<=x*10;i++){
for(int j=1;j<=x*10/2;j++){
for(int k=0;k<=x*10/5;k++){
int sum=i+j*2+k*5;
if(sum==x*10){
printf("可以用%d个一角加%d个两角加%d个五角得到%d元\n",i,j,k,x);
}
}
}
}
}
如果只需要得到一个结果,组合出一个结果就结束,可以使用break或continue
#include<stdio.h>
int main(){
int x;
//i:one j:two k: five
scanf("%d",&x);
int exit = 0;
for(int i=1;i<=x*10;i++){
for(int j=1;j<=x*10/2;j++){
for(int k=0;k<=x*10/5;k++){
int sum=i+j*2+k*5;
if(sum==x*10){
printf("可以用%d个一角加%d个两角加%d个五角得到%d元\n",i,j,k,x);
exit=1;
break;
}
}
if(exit) break;
}
if(exit) break;
}
}
break和continue
·只能对它所在的那层循环做
也可以使用goto
#include<stdio.h>
int main(){
int x;
//i:one j:two k: five
scanf("%d",&x);
for(int i=1;i<=x*10;i++){
for(int j=1;j<=x*10/2;j++){
for(int k=0;k<=x*10/5;k++){
int sum=i+j*2+k*5;
if(sum==x*10){
printf("可以用%d个一角加%d个两角加%d个五角得到%d元\n",i,j,k,x);
goto out;
}
}
}
}
out:
return 0;
}
goto适合在多重循环中需要从最内层跳出到最外层时使用
4.11求和
f(n)= 1+1/2+1/3+1/4+…+1/n
#include<stdio.h>
int main(){
int n;
scanf("%d",&n);
double sum=0;
for(int i=1;i<=n;i++){
sum+=1.0/i;
}
printf("f(%d)=%f",n,sum);
}
若f(n)= 1-1/2+1/3-1/4+…+1/n,前n项和是多少
方法一:奇数项前面是加号,偶数项前面是减号
#include<stdio.h>
int main(){
int n;
scanf("%d",&n);
double sum=0;
for(int i=1;i<=n;i++){
if(i%2!=0){
sum+=1.0/i;
}else{
sum-=1.0/i;
}
}
printf("f(%d)=%f",n,sum);
}
方法二:使用sign,首先设定为sign=1,每加一个数sign变号
#include<stdio.h>
int main(){
int n;
scanf("%d",&n);
double sum=0;
int sign=1;
for(int i=1;i<=n;i++){
sum+=sign*1.0/i;
sign=-sign;
}
printf("f(%d)=%f",n,sum);
}
可以直接让sign为double类型的,这样在sum计算那里就不需要乘以1.0了
4.12 正序分解整数
·输入一个非负整数,正序输出它的每一位数字
·输入:13425
·输出: 1 3 4 2 5
思路一:先把数字逆序 ,再对这个数字进行逆序分解
#include<stdio.h>
int main(){
//先逆序再分解
int x;
scanf("%d",&x);
int t=0;
do{
int d=x%10;
t=t*10+d;
x/=10;
} while(x>0);
printf("x=%d,t=%d\n",x,t);
x=t;
do{
int d=x%10;
printf("%d",d);
if(x>9){
printf(" ");
}
x/=10;
}while(x>0);
printf("\n");
}
输入 12345
输出:1 2 3 4 5
结果正确
输入:700
输出:7
结果错误
所以先逆序再逆序分解的方案只适合用于末尾没有0的数字
思路二:
#include<stdio.h>
int main(){
int x;
scanf("%d",&x);
int t=x;
int mask=1;
while(t>9){
t=t/10;
mask=mask*10;
}
printf("x=%d,mask=%d\n",x,mask);
do{
int digit = x/mask;
printf("%d",digit);
if(mask>9){
printf(" ");
}
x=x%mask;
mask=mask/10;
}while(mask>0);
printf("\n");
}
4.13求最大公约数
·输入两个数a和b,输出它们的最大公约数
方法一:枚举
(1)设t为2
(2)如果u和v都能被t整除,则记下这个t
(3)t加后重复第2步,直到t等于u或v
(4)那么,曾经记下的最大的可以同时整除u和v的t就是gcd
#include<stdio.h>
int main(){
int a,b;
int min;
scanf("%d %d",&a,&b);
if(a<b){
min=a;
}else{
min=b;
}
int ret=0;
int i;
for(i=1;i<min;i++){
if(a%i==0){
if(b%i==0){
ret=i;
}
}
}
printf("%d和%d的最大公约数是%d",a,b,ret);
}
方法二:辗转相除法
(1)如果b等于0,计算结束,a就是最大公约数
(2)否则,计算a除以b的余数,让a等于b,而b等于那个余数
(3)回到第一步
#include<stdio.h>
int main(){
int a,b,t;
scanf("%d %d",&a,&b);
while(b!=0){
t=a%b;
a = b;
b=t;
}
printf("gcd=%d",a);
}
例:
a b t
12 18 12
18 12 6
12 6 0
6 0