C語言 筆記04
本章涉及《啊哈C》第五章內容
1.程序的3種結構
程序在執(zhí)行時有幾種結構温亲,三種:
- 自上而下執(zhí)行——順序執(zhí)行
- 判斷條件執(zhí)行——選擇執(zhí)行
- 循環(huán)條件執(zhí)行——循環(huán)執(zhí)行
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.邏輯挑戰(zhàn)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循環(huán)來解決:
我的改進01:
int a,i;
a=5;
f=0;
for(i=2,i<=4,i++) // i總比a小1
{
if a%i==0
printf("合數");
else
printf("質數")哄芜;
}
輸出:
質數質數質數
發(fā)現問題:如果這樣寫貌亭,那如果我們要判斷一個很大的數比如1000,那么就會打印出998個……
我的改進02:
引入一個新的量f认臊,用f的兩個值來對應合數和質數:
f | 質or合 |
---|---|
0 | 質數 |
1 | 合數 |
加入for循環(huán)圃庭,循環(huán)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不是質數笆樵凇!回頭看看才發(fā)現for循環(huán)中if雖然起到了判斷合數的作用胯陋,但由于處于循環(huán)之中蕊温,6要除以2袱箱、3遏乔、4义矛、5,那么for循環(huán)中f的值的變化為:
1 1 0 0
即最后6/5!=0,所以f=0盟萨,判斷為質數凉翻。這是程序設計上的錯誤,錯誤為:雖然我們要對所有的a-2個數都判斷捻激,但對于不能被整除的我們不必加入else條件制轰,for循環(huán)中只需要存在一個if條件即可。換言之胞谭,只需要找到一個余數為0的值垃杖,對于余數不為0的值我們不需要在for循環(huán)中提到!
我的改進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就能達到以下目的:遇到第一個合數彩库,馬上退出當前循環(huán)先蒋。
#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; //退出循環(huán)
}
}
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; //退出循環(huán)
printf("%d",i);
}
輸出:
12345
也就是說當i為6時,直接退出循環(huán)竞漾,而不會執(zhí)行for循環(huán)中后面的語句printf("%d",i);
5.continue
提到break就要想到continue啦!那么continue的作用是什么呢业岁?
continue:跳過后面語句直接進入下一輪循環(huán)
例子:打印100內的所有偶數
int a;
for(i=1;i<=100;i++)
{
if(i%2==1)
contine
printf("%d",i);
}
6.邏輯挑戰(zhàn)8:驗證哥德巴赫猜想
本節(jié)我覺得書本中講得很好坦仍,就不用自己的話來描述了,可以回頭復習復習叨襟。
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; }
// 打印這個解并跳出循環(huán)
}
}
}
《啊哈C》:這里只驗證了4到100的數繁扎,當然你可以驗證更大的范圍。當然糊闽,去驗證哥德巴赫猜想有很多種方法梳玫,顯然這種方法是不夠好的,判斷質數的部分也不夠快右犹,這里只是提供一種思路提澎,等你看完了第6章再回頭過來看,我想你一定可以找到更高效的方法念链。
7.邏輯挑戰(zhàn)9:水仙花數
有一種三位數特別奇怪盼忌,這種數的“個位數的立方”加上“十位數的立方”再加上“百位數的立方”恰好等于這個數积糯。例如:153=1×1+5×5+3×3,我們?yōu)檫@種特殊的三位數起了一個很好聽的名字——“水仙花數”谦纱,那么請你找出所有的“水仙花數”吧看成。
法一:拼接法,列出所有可能拼出3位數
首先用3個循環(huán)嵌套打印出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循環(huán)i中只嵌套了一個for循環(huán)j川慌;
for循環(huán)j中只嵌套了一個for循環(huán)k;
for循環(huán)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.邏輯挑戰(zhàn)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.邏輯挑戰(zhàn)11:猜數游戲
游戲規(guī)則:計算機隨機給出0~99之間的一個整數琴拧,你能否猜出這個數?每猜一
次嘱支,計算機都會告訴你猜的大了還是小了蚓胸,直到你猜出這個數為止。
思考:
如何生成一個1~20000000的數馍盟?
10.邏輯挑戰(zhàn)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次機會柱查,請繼續(xù)。\n",sum);
if(b<a)
printf("小了研乒,還有%d次機會淋硝,請繼續(xù)宽菜。\n",sum);
if(b==a)
{
printf("恭喜你铅乡,答對了仰楚!\n");
break;
}
if (sum == 0)
{
printf("沒有機會了隆判,系統(tǒng)將在60s內關機!\n");
system("shutdown -s -t 50");
break;
}
}
system("pause");
return 0;
}
對了,還有一個取消關機的命令:
system("shutdown -a");