C语言基础第七课循环结构程序设计——第四节逗号运算符(表达式值得问题)、for语句变形(省略表达式123的情况)、求π的近似值、编程序判断m是否为素数、编程序求1!+3!+.+19!、百鸡百钱优化算法

一、逗号运算符

将多个表达式连接起来,构成一个逗号表达式。
一般形式:
表达式1,表达式…表达式n
功能:
自左至右计算各表达式的值,并以最右一个表达式的值作为逗号表达式的值。

例如:
a=(3*5,4*5);
则a的值为20。
例如:
a=3*5,4*5;
则a的值为15。
但是逗号表达式的值还是20
printf("%d",(i=3,i++,++i,i+5));
结果为10

并不是所有的逗号,都是逗号运算符,有的逗号只
是分隔符。
例如:
int a,b,c;
其中的逗号都是分隔符。

二、for语句变形

for语句中的表达式1、表达式3均可以是逗号表达式。
for语句中的表达式1、表达式2和表达式3均可以缺省。

  1. 如果for语句中的赋初值部分或递变部分,需要使用多个表达式完成,那么可以构成一个逗号表达式。for语句中的表达式1、表达式3均可以是逗号表达式。
for(i=1,j=10,i<j,i++,j--)
printf("i=%d,j=%d\n",i,j);
因为都是,
所以不好分辨
也会报错
for语句的三个表达式之间,必须以分号分隔。
for(i=1,j=10;i<j;i++,j--)
printf("i=%d, j=%d\n",i,j);
  1. 既可以将循环之前的语句,移入到表达式1之中;
    也可以将循环体中的语句,移入到表达式3之中

求1+2+… +100之和。

#include <stdio.h>
int main(void)
{int s,i;
s=0;
for(i=1;i<=100;i++) 
s=s+i;
printf("s=%d\n",s);
return 0;
}

改:

for(s=0,i=1;i<=100;s=s+i,i++) 
;
//循环体是空语句
//别漏掉

在这里插入图片描述
3. 在for语句中,若不需要赋初值部分或递变部分,则相应的表达式可以缺省。
即for语句中的表达式1、表达式3均可以缺省
甚至于作为循环条件的表达式2也可以缺省。
例3.用for循环计算n!,直接用n作为循环变量。

#include <stdio.h>
int main(void)
{int n;
long f=1 ;
printf("请输入一个正整数:");
scanf("%d",&n);
for( ;n>=1;n--)
//分号不可少
f=f*n;
printf("f=%ld\n",f);
return 0;
}

这个题就是本来那个f=1
应该做表达式1的
但是他就独立出去了
在定义的时候就赋初值了 
就用不到了

还有就是
for(;n>=1;)
//分号不可少
{f=f*n;
n--;
}
一般来说
表达式3就是
起一个计数器的作用
如果作为计数器
拿到循环里面
跟放在for里面是一样的
都是执行完了循环就+1
只不过很多时候都是单条语句
就跟这个题目一样
你想拿下来
就得都放在{}里面
组成复合语句
这就不如不拿下来直接放进去省事了

  1. 表达式2缺省时,循环条件看作始终为真,从而导致循环永远不会结束。
    while(1)是因为1不等于0 ,所以条件判断永远都是真的
    都是真就不会停下
    所以就想办法让他停下
break;

用break语句就是一个挺好的方法

for(i=1; ;i++)
{if(i>100)
break;
s=s+i ;
}

这个就是把表达式2拿下来了
本来我一条语句
这下子成了复合语句
更费劲了

关于for语句变形总结:

一般来说就是想办法把for语句的条件给提前(通常表达式1)或者说放进循环体里面(通常表达式23),没什么大用处,表达式1缺省一般都是定义变量的时候就初始化赋值,也没多大方便其实
表达式3 如果是计数器的话放在循环语句的最后的话跟在语句里面效果一样,但是如果循环体是单条语句,为了把表达式3拿下来还得用{}括起来,更麻烦人,感觉花里胡哨没啥大用处
建议采用常规写法。
表达式1给循环变量赋初值,
表达式2作为循环的条件,
表达式3递变循环变量的值。
关于这些变形其实不用特殊记忆
懂了原理就知道他们所谓的省略不过就是换个地方而已
看到懂就好
花里胡哨没啥大用处,也就老师出题才会这么干

三、一堆例题

1.

在这里插入图片描述

  1. 问题分析:
    1.可以采用累加的方式求和。
    2.各个累加项是正负交替变化的;
    3.每个累加项是一个分数,其分母以2为步长递增。

  2. 正负怎么搞呢,第一种思路就是(-1)n,-1的n次方,但采用相反数的办法搞一下

  3. 算法设计:
    定义4个变量。
    其中变量p,存放累加和,并赋初值为0。这个挺关键,累加就是0,累乘就是1,目的就是为了避免随机数
    变量n,存放当前累加项的分母,并赋初值为1。
    变量S,控制当前累加项的正负,并赋初值为正1。
    变量t,存放当前累加项,并赋初值为1。
    p=p+t;将当前项累加到p中
    n=n+2;下一项分母递增2
    S=-S;改变下一项的正负(说白了跟-1n次方差不多,只不过拆开了
    t=s*1/n;求得下一项。
    循环执行,循环条件为当前项t的绝对值不小于10-6。
    将p的值乘4输出结果

#include <stdio.h>
#include <math. h>
int main(void)
{float p,t;
int n,S;
p=0; n=1;
s=1; t=1;
while(fabs(t)>=1e-6)

//1e-6就是10的-6次方
{p=p+t;
n=n+2;
S=-S;
t=s*1.0/n;
//这里就是为了防止整除
//5/3=1这种情况
}
p=p*4;
printf("p=%.20f\n",p);
return 0;
}

这个就是一个求圆周率的
把数据改成double
然后1e-6改成一个范围更小的数字
求得的结果更为精确

2.已知m是一个大于1的正整数,编程序判断m是否为素数。

素数(质数)只能被1和自身整除的大于1自然数。(比如RSA非对称密码体系)
编程思路:
要判断m是不是素数,只需要检验m是否能被2到m-1之间的整数整除。
如果m不能被2整除(例如m=7) ; m也不能被3整除; …直到m也不能
被m-1整除;那么.m是素数。(需要同时满足多个条件)
如果m能被2到m-1之间的某一个整数整除(例如m=9),那么.m不是素数。(只需满足一个条件)
在这里插入图片描述在这里插入图片描述

#include <stdio.h>
int main(void)
{int m,i;
printf("请输入一个大于1的整数: \n");
scanf("%d",&m);
i=2;
while(i<m)
{if(m%i==0)
{printf("%d不是素数\n",m);
return 0;
}
else
i++;
}
printf( "%d是素数\n",m);
return 0;
}

//这个是双出口
//基本见不到这种
/*因为按结构化程序设计的思想
结构模块应该具有单入口单出口*/

在这里插入图片描述

#include <stdio.h>
int main(void)
{int m,i;
printf("请输入一个大于1的整数: \n") ;
scanf("%d", &m) ;
i=2;
while(i<m)
{if(m%i==0)
break;
else
i++;
}
if(i==m)
printf("%d是素数\n",m);
else
printf( "%d不是素数\n" ,m);
return 0;
}

算法改进:
根据数论定理,在判断正整数m是不是素数时,除数只需要取2到√m之间的整数即可。
其实前期的话跟数学的关联还不是很大,就是单纯的非计算机专业的学生的学习还问题不大,后期的话名专业计算机学生可能就需要多跟数学打交道了,毕竟算法不是那么友好, 哈哈哈哈。

3.例1.编程序求1!+3!+5!..+19!。

编程思路:
依次求出1!、3!、5!…19!, 并累加到同一个变量中。

碰见大问题,难问题就是分解啊,一看这种求阶乘的就应该反映出来应该是一个循环问题没这样就简单了啊,去找一下他们的共性就ok了啊,然后再动动脑子,想想怎么用共性概括一下,然后就写出来了,然后自己测试一波就OK了,像这种明显控制得一般都是多重循环(二重居多,比如九九乘法表)
计算n!并累加到sum中的程序段:

f=1;
//这个1就有意思了
for(i=l;i<=n;i++)
f=f*i;
sum=sum+f;


n=1;
f=1;
for(i=1;i<=n;i++)
f=f*i;
sum=sum+f ;


n=3;
f=1;
for(i=1;i<=n;i++)
f=f*i;
sum=sum+f ;


.....
n=19;
f=1;
for(i=1;i<=n;i++)
f=f*i;
sum=sum+f;

归纳为一个双重循环:

for(n=l;n<=19;n=n+2)
{f=l;
for(i=1;i<=n;i++)
f=f*i;
sum=sum+f;
}
/*你看
简单的一批吧
就是分解一下共性
然后外面套一个外循环程序
美滋滋*/

完整的源程序:

#include<stdio.h>
int main(void)
{int n,i;
double f, sum;
sum=0;
for(n=1;n<=19;n=n+2)
{f=1;
for(i=1;i<=n;i++)
f=f*i;
sum=sum+f;
}
printf("sum=%.0f\n", sum);
return 0;
}


运行结果是不是挺大的
所以说还是double靠谱
suim=0就很有灵性哦

在这里插入图片描述

4.编程序求解百鸡百钱问题,用100元钱买100只鸡。己知母鸡每只3元,公鸡每只两元,小鸡两只1元,问母鸡、公鸡和小鸡各几何。

编程思路:
假设母鸡、公鸡、小鸡的数量分别为i、j、k,那么由给定的条件,可以列出如下的两个方程:
i+j+k= 100
3i+2j+k/2=100
在这个问题中,有三个变量、两个方程,因此属于数学中的不定方程。
通常采用穷举法求解不定方程。就是将变量所有的取值组合都列举出来,并逐个进行验证。
要列举三个变量的所有取值组合,应采用三重循环实现。

#include <stdio.h>
int main(void)
{int i,j,k;
for(i=1;i<=2;i++)
for(j=1;j<=3;j++)
{for(k=1;k<=4;k++)
printf("%d , %d,%d\t" ,i,j,k);
printf("\n");
}
return 0;
}
要列举三个变量的所有取值组合
应采用三重循环实现。

#include <stdio.h>
int main(void)
{int i,j,k;
for(i=1;i<=2;i++)
for(j=1;j<=3;j++)
{for(k=1;k<=4;k++)
printf( "%d , %d , %d\t",i,j,k);
printf("\n");
}
return 0;
}

在这里插入图片描述
在多重循环最内层的循环体中,能够列举出循环变量的所有取值组合。(这个很好理解啊,外层循环可以不严密的说就是为个对内层循环做一个循环,就比如把内层循环当做一个语句,然后循环,其实最终的结果都是内层循环输出的,内存循环一般就是我们做循环题目找思路的时候写的那个共性的东西,然后通过外层循环加以条件限制)

对于百鸡百钱问题,只需要采用三重循环结构,并在最内层的循环体中,针对每一组i、j、k的取值组合,判断两个方程所代表的等式是否成立。
(就是找出来所有可能,然后根据条件判断一下符合条件的)

#include <stdio.h>
int main(void)
{int i,j,k;
for(i=0;i<=33;i++)
for(j=0;j<=50;j++)
for(k=0;k<=100;k=k+2)
{if((i+j+k==100)&&(3*i+2*j+k/2==100))
printf("母鸡=%-4d公鸡=%-4d
//这个蛮有意思的
//%4d是为了有间隔
/*因为四位数字
但是实际解出来的数字=小于四位
所以有间隔
-4d就是空格在右边补充
*/
小鸡=%-4d\n" ,i,j,k);
}
return 0;
}

在这里插入图片描述在这里插入图片描述
其实做出题目来不是很难,一般来说过学校考试就OK了
但在以后工作中啊啥的
还是得学会怎么让程序简化
程序优化:
只保留i、j两个变量,小鸡的数量可以表示为100-1-j。
从而可以写出一个方程3i+2j+(100-i-j)/2=100。
输出的地方也记得改一下把k改成100-i-j

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值