C语言 笔记04
本章涉及《啊哈C》第五章内容
1.程序的3种结构
程序在执行时有几种结构,三种:
- 自上而下执行——顺序执行
- 判断条件执行——选择执行
- 循环条件执行——循环执行
2.a++,a--,a+=1
简写 | 实际意义 |
---|---|
a++ | a=a+1 |
a-- | a=a-1 |
a+=2 | a=a+2 |
a-=2 | a=a-2 |
a*=2 | a=a*2 |
a/=2 | a=a/2 |
a%=2 | a=a%2 |
还有++a,--a以后再讲。
3.逻辑挑战7.判断质数很简单
质数(素数)的定义:指大于1的自然数,除了1和该整数自身外,无法被其他自然数整除。
合数的定义:比1大但不是质数的数。
所以我们要判断一个数字a是不是质数,要将a分别除以2,3,4,……,a-2,a-1。如果从2到a-2的所有数都不能被a整除,那么说明a为质数,否则为合数。比如我们判断5是否为质数:
- 5%2!=0
- 5%3!=0
- 5%4!=0
即2 3 4 不能被5整除,所以5是一个质数。
用代码来呈现为:
int a;
a=5;
if(a%2!=0 && a%3!=0 && a%4!=0)
printf("质数");
else
printf("合数");
也可从反面判断:
int a;
a=5;
if(a%2==0 || a%3==0 || a%4==0)
printf("合数");
else
printf("质数");
……
同样的,我们面对较大的数字,要判断它是否为质数则会随着数的增大而程序更加繁琐,所以我们要改进。
比如if条件我们可以用for循环来解决:
我的改进01:
int a,i;
a=5;
f=0;
for(i=2,i<=4,i++) // i总比a小1
{
if a%i==0
printf("合数");
else
printf("质数");
}
输出:
质数质数质数
发现问题:如果这样写,那如果我们要判断一个很大的数比如1000,那么就会打印出998个……
我的改进02:
引入一个新的量f,用f的两个值来对应合数和质数:
f | 质or合 |
---|---|
0 | 质数 |
1 | 合数 |
加入for循环,循环a-2次判断a是否能整除其中某一个数,如果有,则令f=1;如果没有,则令f=0:
int a,i,f;
a=6;
for(i=2;i<=5;i++)
{
if(a%i==0)
f=1;
else
f=0;
}
if(f==0)
printf("质数");
else
printf("合数");
输出:
质数
错误!显然6不是质数啊!回头看看才发现for循环中if虽然起到了判断合数的作用,但由于处于循环之中,6要除以2、3、4、5,那么for循环中f的值的变化为:
1 1 0 0
即最后6/5!=0,所以f=0,判断为质数。这是程序设计上的错误,错误为:虽然我们要对所有的a-2个数都判断,但对于不能被整除的我们不必加入else条件,for循环中只需要存在一个if条件即可。换言之,只需要找到一个余数为0的值,对于余数不为0的值我们不需要在for循环中提到!
我的改进03:
int a,f,i;
a=6;
f=0;
for(i=2;i<=5;i++)
{
if (a%i==0)
f=1;
}
if (f == 0)
printf("质数\n");
else
printf("合数\n");
输出:
合数
正确!
完整代码如下:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a,f,i;
a=8;
f=0;
for(i=2;i<=7;i++)
{
if (a%i==0)
f=1;
}
if (f == 0)
printf("质数\n");
else
printf("合数\n");
system("pause");
return 0;
}
升级01:输入a判断是否为质数
int a,f,i;
f=0;
scanf("%d",&a);
for(i=2;i<=a-1;i++)
{
if (a%i==0)
f=1;
}
if (f == 0)
printf("质数\n");
else
printf("合数\n");
system("pause");
return 0;
升级02:输入a,输出a的所有约数和判断a是否为质数
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a,f,i;
f=0;
scanf("%d",&a);
for(i=2;i<=a-1;i++)
{
if (a%i==0)
{
f=1;
printf("%d",i);
}
}
if (f == 0)
printf("质数\n");
else
printf("合数\n");
system("pause");
return 0;
}
4.更快一点:break
我们可以利用break提高效率,前面我们需要判断所有a-2个数,现在有了break就能达到以下目的:遇到第一个合数,马上退出当前循环。
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a,f,i;
f=0;
scanf("%d",&a);
for(i=2;i<=a-1;i++)
{
if (a%i==0)
{
f=1;
break; //退出循环
}
}
if (f == 0)
printf("质数\n");
else
printf("合数\n");
system("pause");
return 0;
}
再举个例子:
int i,f;
f=0;
for(i=1;i<=10;i++)
{
if(i==6)
break; //退出循环
printf("%d",i);
}
输出:
12345
也就是说当i为6时,直接退出循环,而不会执行for循环中后面的语句printf("%d",i);
5.continue
提到break就要想到continue啦!那么continue的作用是什么呢?
continue:跳过后面语句直接进入下一轮循环
例子:打印100内的所有偶数
int a;
for(i=1;i<=100;i++)
{
if(i%2==1)
contine
printf("%d",i);
}
6.逻辑挑战8:验证哥德巴赫猜想
本节我觉得书本中讲得很好,就不用自己的话来描述了,可以回头复习复习。
int k,a,b,i,fa,fb;
for(k=4;k<=100;k=k+2)
{
for(a=2;a<=k/2;a++)
{
fa=0;
for(i=2;i<a-1;i++) // 判断a是否为质数
{
if(a%i==0) { fa=1; break;}
}
if(fa==0) // 如果a为质数
{
b=k-a;
fb=0;
for(i=2;i<b-1,i++) // 判断b是否为质数
{
if(b%i==0) { fb=1; break;}
}
if (fb==0) // 如果b也是质数
{ printf("%d=%d+%d\n",k,a,b);break; }
// 打印这个解并跳出循环
}
}
}
《啊哈C》:这里只验证了4到100的数,当然你可以验证更大的范围。当然,去验证哥德巴赫猜想有很多种方法,显然这种方法是不够好的,判断质数的部分也不够快,这里只是提供一种思路,等你看完了第6章再回头过来看,我想你一定可以找到更高效的方法。
7.逻辑挑战9:水仙花数
有一种三位数特别奇怪,这种数的“个位数的立方”加上“十位数的立方”再加上“百位数的立方”恰好等于这个数。例如:153=1×1+5×5+3×3,我们为这种特殊的三位数起了一个很好听的名字——“水仙花数”,那么请你找出所有的“水仙花数”吧。
法一:拼接法,列出所有可能拼出3位数
首先用3个循环嵌套打印出100~999所有三位数,然后加入if条件判断后打印出水仙花数:if(i100+j10+k=iii+jjj+kkk)**
int i,j,k;
for(i=1;i<=9;i++)
{
for(j=0;j<=9;j++)
{
for(k=0;k<=9;k++)
{
if(i*100+j*10+k==i*i*i+j*j*j+k*k*k)
printf("%d%d%d\n",i,j,k); // 可以改进:printf("%d",i*100+j*10+k);
}
}
}
完整代码如下:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i,j,k;
for(i=1;i<=9;i++)
{
for(j=0;j<=9;j++)
{
for(k=0;k<=9;k++)
{
if(i*100+j*10+k==i*i*i+j*j*j+k*k*k)
printf("%d\n",i*100+j*10+k);
}
}
}
system("pause");
return 0;
}
输出:
153
370
371
407
简化版:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i,j,k;
for(i=1;i<=9;i++)
for(j=0;j<=9;j++)
for(k=0;k<=9;k++)
if(i*100+j*10+k==i*i*i+j*j*j+k*k*k)
printf("%d\n",i*100+j*10+k);
system("pause");
return 0;
}
括号能够去掉的原因:
for循环i中只嵌套了一个for循环j;
for循环j中只嵌套了一个for循环k;
for循环k中只嵌套了一个if语句;
if语句中只有一个printf语句,因此所有{ }都可以省略。
法二:分割法,将要三位数x分割成a,b,c三个数
那么
百位数为→x/100
十位数为→x/10%10
个位数为→x%10
完整代码:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int x,a,b,c;
for(x=100;x<=999;x++)
{
a=x/100;
b=x/10%10;
c=x%10;
if(x==a*a*a+b*b*b+c*c*c)
printf("%d\n",x);
}
system("pause");
return 0;
}
注:
这里的
a=x/100;
b=x/10%10;
c=x%10;
可以改为:
a=x/100%10
b=x/10%10
c=x/1%10
思考:
8.逻辑挑战10:解决奥数难题
代码如下:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i;
for(i=1;i<=9;i++)
{
if((i*10+3)*6528 == (30+i)*8256 )
printf("%d\n",i);
}
system("pause");
return 0;
}
输出:
9.逻辑挑战11:猜数游戏
游戏规则:计算机随机给出0~99之间的一个整数,你能否猜出这个数?每猜一
次,计算机都会告诉你猜的大了还是小了,直到你猜出这个数为止。
思考:
如何生成一个1~20000000的数?
10.逻辑挑战12:你好坏,挂机啦
这算是本书的一个彩蛋吧,作者真的好棒!
首先介绍关机命令:
system("shutdown -s -t 50");
其中:
shutdown : 表示关机或者重启的命令
-s : 表示关机
-t 50 : 表示在50s时关机
完整代码:
#include <stdio.h>
#include <stdlib.h>
int main()
{
system("shutdown -s -t 50");
return 0;
}
为了方便取用,我将它打出:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a,b,sum;
sum = 6;
srand((unsigned)time(NULL));
a = rand()%100;
while(1)
{
sum--;
scanf("%d",&b);
if(b>a)
printf("大了,还有%d次机会,请继续。\n",sum);
if(b<a)
printf("小了,还有%d次机会,请继续。\n",sum);
if(b==a)
{
printf("恭喜你,答对了!\n");
break;
}
if (sum == 0)
{
printf("没有机会了,系统将在60s内关机!\n");
system("shutdown -s -t 50");
break;
}
}
system("pause");
return 0;
}
对了,还有一个取消关机的命令:
system("shutdown -a");
网友评论