2013年3月31日 星期日

[C語言]while、switch題目



上次的海龍公式教學,幫助到了很多人。所以又抽空寫了這篇,解題小教學,希望也能夠幫助到大家。這篇會詳細說明基本題、加分題及進階的奇數檢驗方法。



先來看看這次的題目,然後就step-by-step的解題囉

一、考慮變數數量、可能會用到的函數、header file

I.變數數量

這次題目有兩個部分,第一個部分是讓使用者決定n值後,進行小於n的奇數總和sum。第二個部分是輸入阿拉伯數字,輸出對應的星期day
紅字的部分,可以知道我們至少要用三個變數,這次程式的應用上這三個變數僅需要是整數即可,以int宣告他們吧。
接著這次會使用到while這個迴圈,那麼至少得要有一個變數i當作迴圈的條件值,也是以int宣告就可以了
int n,day,i=1,sum=0;

II.可能會用到的函數

printf、scanf及system。

III.Header file

這次只用到三個基本的函數。因此Header file只需要寫下
#include <stdio.h> //輸入與輸出&檔案處理
#include <stdlib.h> //通用工具

二、while、switch語法

I.while

先來看看while語法的結構吧
while(測試條件)
{
	執行內容
}

1.測試條件可以是變數、可以是一個運算是
2.執行內容在測試條件為False之前都會一直被執行
3.while執行模式是,先檢查測試條件→決定是否執行內容。後面學到do-while函數則是先執行一次才檢查測試條件。


接著來看看while的範例
int i=5;
while(i)
{
	printf("這是迴圈內容,直到i=0 即false前都會一直出現,現在i=%d\n",i);
	i--;
}
輸出結果
這個例子當中很明顯可以看到,while先檢查條件再執行的特性。結果中並不會出現i=0的那行。

範例2,利用運算是當作while的條件
int i=5,n=10;
while(i < n)
{
	printf("這是迴圈內容,直到>=10前,即i < n = false前都會一直出現,現在i=%d\n",i);
	i++;
}
輸出結果
在這個例子當中,只要 i >= 10 便會使 i < n 這個運算結果為false。這個例子又再一次見證while"先檢查再執行"的特性。

II.switch

語法結構
switch (算式或變數)
{
case 常數:
	敘述
	break;
case 常數:
	敘述
	break
default:
	敘述;
//default也可省略不寫。但如此一來當沒有相對應的case時,switch當中程式碼將不會被執行,會直接跳離switch
}
範例1
int time;
printf("輸入現在現在時間(0-24) >");
scanf("%d",&time);
switch(time)
{
case 7:
	printf("該吃早餐囉\n");
	break;
case 12:
	printf("該吃午餐囉\n");
	break;
case 17:
	printf("該吃晚餐囉\n");
	break;
default:
	printf("現在不能吃東西,會胖喔>_<");
}
輸出結果



其實switch和else-if有些相似處,卻又有些不同的地方,這邊先不詳述,之後有空會再寫另一篇跟大家詳細介紹這兩個差異....。(其實是還沒想到舉什麼例子說明比較好orz)


三、組裝程式

I.印出學號,提示輸入

首先是印出自己的學號,和提示使用者輸入一些資訊的部分。這邊很簡單,照往常利用printf和scanf去達成就可以了。還不熟悉這兩個語法的同學可以參考上一篇三角形面積解題,裡面介紹scanf和printf的用法。

II.利用while計算小於N的奇數和

利用while我們可以寫出
while(i <= n) //當i小於等於n時迴圈便執行一次
{
	sum=sum+i; //計算目前為止的i總和
	i+=2; //執行一次迴圈i就+2
}
printf("sum = %d\n",sum); //輸出sum
輸出結果

III.利用switch顯示對應的星期

printf("Today is ");
switch(day)
{
case 0:
	printf("Sun.\n");
	break;
case 1:
	printf("Mon.\n");
	break;
case 2:
	printf("Tue.\n");
	break;
case 3:
	printf("Wed.\n");
	break;
case 4:
	printf("Thu.\n");
	break;
case 5:
	printf("Fri.\n");
	break;
case 6:
	printf("Sat.\n");
}
當然,在這裡你可以用else-if來寫
printf("Today is ");
if(day == 0)
	printf("Sun.\n");
else if (day == 1)
	printf("Mon.\n");
else if (day == 2)
	printf("Tue.\n");
else if (day == 3)
	printf("Wed.\n");
else if (day == 4)
	printf("Thu.\n");
else if (day == 5)
	printf("Fri.\n");
else if (day == 6)
	printf("Sat.\n");
最後將他們組裝,你就會看到跟下圖一樣的結果

四、加強和改善程式功能

I.實作加分題 - 顯示N與"+"號

顯示n的方法很簡單,只要在原本的迴圈當中加上print的功能就可以了。不過我們就必須把"sum = "這幾個字移到迴圈之前。
printf("sum = ");
while(i <= n) //當i小於等於n時迴圈便執行一次
{
	sum=sum+i; //計算目前為止的i總和
	printf("%d ",i);//輸出目前的i
	i+=2; //執行一次迴圈i就+2
}
printf("= %d\n",sum); //輸出sum
結果

接著是+號的部分,這邊必須考慮目前的i是否是最後一個,至於實現方法只要加上if就可以了,寫法因人而異,你可以直接在迴圈中加上
if (i < n) printf("+ ");
也可以將原本當中的
printf("%d ",i);//輸出目前的i
改成
if (i < n)
	printf("%d + ",i);
else
	printf("%d",i);
這兩種方法都能夠實現一樣的結果,同樣的功能寫法很多種,找自已習慣的即可,慢慢就會培養出自己寫code的style。

II.檢查奇數

剛剛完成了加分題之後,大家試著輸入偶數看看,出現了bug,多出了+號。
解決方法很多種,可以限制使用者只能輸入奇數、針對偶數做特別處理。不過在解決之前得先知道使用者輸入的是奇數還是偶數才行。
數學上我們常常假設偶數為2k,奇數是2k+1。從這樣的假設上可以看到一個很明顯的特性,奇數除以2必餘1。還記得"%"這個運算子嗎?它是用來取餘數的。如果不記得的話幫大家複習一下。
5%2=1
5%3=2
6%2=0
所以只要n%2=1 便是奇數,n%2=0則為偶數。

解決方法1-只讓使用者輸入奇數

或許大家會立馬想到利用if檢查n%2的結果就好了,不過這樣只能檢查一次,於是乎我們用while來當檢查,直到使用者輸入奇數之前都不執行計算,要求使用者必須輸入奇數。
參考寫法:
while (n%2 !=1)
{
	printf("n can only be odd\n");
	printf("please re-enter n = ");
	scanf("%d",&n);
}

輸出結果:
上圖可以看到,直到使用者輸入奇數之前程式會一直要求重新輸入。

解決方法2-針對偶數做應變

其實這只要更改檢驗是否為最後一數字的檢驗方法就可以了,如果使用者輸入的是偶數,偶數的前一個數字會是運算當中的最後一個數字。
因此可以改成
if (n%2 != 1)
{
	if(i < n-1) printf("+ ");
}
else
{
	if (i < n) printf("+ ");
}
當然也可以改成
if (n%2 != 1 && i < n-1) printf("+ ");
else if (n%2 == 1 && i < n) printf("+ ");
再強調一次,寫出同樣功能的方法很多種,找自己最習慣最直覺的方式去寫即可。

III.驗證星期

上面的程式碼中在顯示星期的部分很明顯有一個bug存在,當使用者輸入大於6的數字會怎麼樣呢?
沒有顯示任何東西??
解決方法類似驗證奇數那樣,這邊就留給大家自己摸索囉。

沒有留言:

張貼留言