第4章 程序的控制結構_第1頁
第4章 程序的控制結構_第2頁
第4章 程序的控制結構_第3頁
第4章 程序的控制結構_第4頁
第4章 程序的控制結構_第5頁
已閱讀5頁,還剩84頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第4章程序的控制結構C程序設計語言1內容提要算法的描述方法基本控制結構基本控制語句常用算法,如累加、累乘、統(tǒng)計、遞推、迭代、窮舉等結構化程序設計的基本思想C程序結構C程序源程序文件1源程序文件2源程序文件3編譯預處理命令全局變量聲明函數(shù)1函數(shù)n…函數(shù)首部函數(shù)體局部變量聲明執(zhí)行語句什么是結構化程序設計?StructuredProgramming,簡稱SP1965年,最早由E.W.Dijkstra在一次國際會議上提出1966年,C.Bohm和G.Jacopini首先證明了:只用順序、選擇、循環(huán)三種基本的控制結構就能實現(xiàn)任何單入口、單出口的程序給結構化程序設計奠定了基礎1971年,IBM公司的Mills提出:程序應該只有一個入口和一個出口進一步補充了結構化程序的規(guī)則什么是結構化程序設計?目前,還沒有一個嚴格的定義1974年,D.Gries教授將已有的對結構化程序設計的不同解釋歸納為13種。一個比較流行的定義是:結構化程序設計是一種進行程序設計的原則和方法,它避免使用goto語句,采用“自頂向下、逐步求精”方法進行程序設計,按照這種原則和方法設計出的程序的特點為:結構清晰容易閱讀容易修改容易驗證糟糕的gotoSTART_LOOP:if(fStatusOk){

if(fDataAvaiable)

{i=10;

gotoMID_LOOP;}

else

{

gotoEND_LOOP;}}else

{

for(i=0;i<100;i++)

{MID_LOOP://lotsofcodehere

}

gotoSTART_LOOP;}END_LOOP:什么是結構化程序設計?不能簡單的認為避免使用goto語句的程序設計方法就是結構化程序設計方法用goto跳向共同的出口位置`voidInit(void){

char*p1=NULL;

char*p2=NULL;

char*p3=NULL; p1=(char*)malloc(256);

if(p1==NULL)

goto

Exit;

p2=(char*)malloc(256);

if(p2==NULL)

goto

Exit;

p3=(char*)malloc(256);

if(p3==NULL)

goto

Exit;

/*正常處理的代碼*/Exit:

if(p1!=NULL)

free(p1);

if(p2!=NULL)free(p2);if(p3!=NULL)

free(p3);

return;}結構化程序設計關注的焦點結構化程序設計關注的焦點程序結構的好壞有無goto,并不是程序結構好壞的標志限制和避免使用goto,只是得到結構化程序的一個手段,而不是我們的目的結構化程序設計的核心思想采用順序、選擇和循環(huán)三種基本結構作為程序設計的基本單元只有一個入口;只有一個出口;無死語句,即不存在永遠都執(zhí)行不到的語句;無死循環(huán),即不存在永遠都執(zhí)行不完的循環(huán)。采用“自頂向下、逐步求精”和模塊化的方法進行結構化程序設計什么是結構化程序設計?結構化程序設計語言按照結構化程序設計的要求設計出的語言結構化程序利用結構化程序設計語言或按照結構化程序設計思想編制出的程序如何設計結構化的程序?Top-down,Stepwiserefinement自頂向下、逐步求精1971年,wirth提出的結構化程序設計方法先全局后局部先整體后細節(jié)先抽象后具體自頂向下、逐步求精的

結構化程序設計方法BAA2A1B2B1A12A11A22A21B12B11B22B21算法的概念

數(shù)據(jù)結構+算法=程序只對面向過程的語言(C)成立面向對象程序=對象+消息算法:為解決一個具體問題而采取的確定的有限的操作步驟,僅指計算機能執(zhí)行的算法算法的特性

有窮性在合理的時間內完成確定性,無歧義

如果x≥0,則輸出Yes;如果x≤0,則輸出No;有效性

能有效執(zhí)行負數(shù)開平方?jīng)]有輸入或有多個輸入

有一個或多個輸出

算法的分類

數(shù)值運算算法:解決求數(shù)值解問題非數(shù)值運算算法:需要用分析推理、邏輯推理才能解決的問題例如人工智能中的許多問題,查找、分類等算法的表示方法自然語言表示傳統(tǒng)的流程圖表示在1966年,Bohra與Jacopini提出N-S結構化流程圖表示1973年,美國學者I.Nassi和B.Shneiderman提出偽代碼表示起止框輸入框判斷框處理框流程線連接點注釋框BANS圖傳統(tǒng)流程圖順序結構BABN如果

成績<60

那么

通知補考否則

告知你考試成績AY條件PABNY條件P分支結構(選擇結構)當型循環(huán)A真假假條件P循環(huán)結構A當P成立直到型循環(huán)條件PA假真循環(huán)結構A直到P為假A條件PA當型循環(huán)直到型循環(huán)真假假條件P假真循環(huán)結構復合語句{}括住的若干條語句構成一個語句塊,稱為復合語句語句塊內可以定義變量變量僅在定義它的復合語句內有效變量必須在復合語句的開頭定義復合語句可以用在任何可以使用語句的地方if-else選擇結構的一種最常用形式if(表達式)

{

語句1;

} else

{

語句2;

}語句3表達式值非0時,執(zhí)行語句1,然后語句3;表達式值為0時,執(zhí)行語句2,然后語句3{

語句1;

}

{

語句2;

}

if-elseelse部分可以沒有if(表達式)

{

語句1;

} 語句3if-else嵌套使用時,注意else和誰配對的問題當表達式值為0時,直接執(zhí)行語句3{

語句1;

}

例4.4:年齡判斷#include<stdio.h>main(){

intyourAge,hisAge; printf("Pleaseenteryourage:"); scanf("%d",&yourAge);/*輸入你的年齡yourAge*/ printf("Pleaseenteryourfriend'sage:"); scanf("%d",&hisAge);/*輸入你朋友的年齡hisAge*/

if(yourAge>=hisAge) { printf("Youareolder!Yourageis=%d\n",yourAge); }

else

{ printf("Yourfriendisolder!Hisageis=%d\n",hisAge); }}條件表達式含義:如果表達式1的值非0(為真),則該條件表達式的結果就是表達式2的值否則,是表達式3的值

表達式3N表達式2Y表達式1表達式1?表達式2:表達式3例4.4:年齡判斷#include<stdio.h>main(){

intyourAge,hisAge; printf("Pleaseenteryourage:"); scanf("%d",&yourAge);/*輸入你的年齡yourAge*/ printf("Pleaseenteryourfriend'sage:"); scanf("%d",&hisAge);/*輸入你朋友的年齡hisAge*/

max=(yourAge>=hisAge)?yourAge:hisAge;

printf("Theolderageis=%d\n",max);}else-ifif的一種擴展形式——相當于else分支嵌套if(表達式1)

語句1;

elseif(表達式2)

語句2;

elseif(表達式3)

語句3;

…………

else

語句4;

語句5;表達式1

語句1語句2語句3語句4表達式2表達式3

圖4-9多分支選擇結構語句1;語句2;語句3;語句4;例4.5:體型判斷按“體指數(shù)”對肥胖程度進行劃分:

體指數(shù)t=w/h2

(體重w單位為公斤,身高h單位為米)當t<18時,為低體重;當18≤t<25時,為正常體重;當25<t<27時,為超重體重;當t≥27時,為肥胖。編程從鍵盤輸入你的身高h和體重w,根據(jù)給定公式計算體指數(shù)t,然后判斷你的體重屬于何種類型。用3種方法編程:算法1:用不帶else子句的if語句編程算法2:用在if子句中嵌入if語句的形式編程算法3:用在else子句中嵌入if語句的形式編程例4.5用不帶else子句的if語句編程#include<stdio.h>main(){

floath,w,t; printf("Pleaseenterh,w:"); scanf("%f,%f",&h,&w); t=w/(h*h);

if(t<18) { printf("t=%f\tLowerweight!\n",t); }

if(t>=18&&t<25) { printf("t=%f\tStandardweight!\n",t); }

if(t>=25&&t<27) { printf("t=%f\tHigherweight!\n",t); }

if(t>=27) { printf("t=%f\tToofat!\n",t); }}當t<18時,為低體重;當18≤t<25時,為正常體重;當25<t<27時,為超重體重;當t≥27時,為肥胖。例4.5用在if子句中嵌入if語句的形式編程

#include<stdio.h>main(){

floath,w,t; printf("Pleaseenterh,w:"); scanf("%f,%f",&h,&w); t=w/(h*h);

if(t<27) {

if(t<25) {

if(t<18)printf("t=%f\tLowerweight!\n",t);

elseprintf("t=%f\tStandardweight!\n",t); }

elseprintf("t=%f\tHigherweight!\n",t); }

elseprintf("t=%f\tToofat!\n",t);}182527當t<18時,為低體重;當18≤t<25時,為正常體重;當25<t<27時,為超重體重;當t≥27時,為肥胖。例4.5用在else子句中嵌入if語句的形式編程

#include<stdio.h>main(){

floath,w,t; printf("Pleaseenterh,w:"); scanf("%f,%f",&h,&w); t=w/(h*h);

if(t<18)

printf("t=%f\tLowerweight!\n",t);

elseif(t<25) printf("t=%f\tStandardweight!\n",t);

elseif(t<27) printf("t=%f\tHigherweight!\n",t);

else printf("t=%f\tToofat!\n",t);}當t<18時,為低體重;當18≤t<25時,為正常體重;當25<t<27時,為超重體重;當t≥27時,為肥胖。182527switch多路選擇switch(表達式){

case

常數(shù)1:

語句序列1;

case

常數(shù)2:

語句序列2;

…………

default:

語句序列3;

}default可以沒有,但最好不省略不要忘記break語句序列1;語句序列2;語句序列n;例4.8:計算器程序編程設計一個簡單的計算器程序,要求根據(jù)用戶從鍵盤輸入如下形式的表達式:操作數(shù)1運算符op操作數(shù)2

然后,計算并輸出表達式的值指定的運算符為加(+)減(-)乘(*)除(/)main(){

intdata1,data2;/*定義兩個操作符*/

charop;/*定義運算符*/ printf("Pleaseentertheexpression:"); scanf("%d%c%d",&data1,&op,&data2);/*輸入運算表達式*/

switch(op) {

case'+':/*處理加法*/ printf("%d+%d=%d\n",data1,data2,data1+data2);

break;

case'-':/*處理減法*/ printf("%d-%d=%d\n",data1,data2,data1-data2);

break;

case'*':/*處理乘法*/ printf("%d*%d=%d\n",data1,data2,data1*data2);

break;

case'/':/*處理除法*/

if(0==data2) printf("Divisionbyzero!\n");

else

printf("%d/%d=%d\n",data1,data2,data1/data2);

break;

default: printf("Unknownoperator!\n"); }}例4.8思考題語句if(0==data2)的必要性1998年11月《科學美國人》雜志,描述了美國導彈巡洋艦約克敦號上的一起事故,除零錯導致軍艦推進系統(tǒng)的關閉如果要求程序能進行浮點數(shù)的算術運算,語句if(0==data2)還能用于比較實型變量data2和常數(shù)0的大小嗎?if(fabs(data2)<=1e-7)如果要求輸入的算術表達式中的操作數(shù)和運算符之間可以加入任意多個空格符,那么程序如何修改?scanf("%d%c%d",&data1,&op,&data2);scanf("%d%1s%d",&data1,&op,&data2);取絕對值函數(shù)作業(yè)P143~152習題4.7,4.9循環(huán)——while語句,for語句while(表達式)

{

語句;}for(表達式1;表達式2;表達式3)

{

語句;}語句;語句;while語句while(表達式)

{

語句;}只要表達式的值為非0,就重復執(zhí)行語句,直到表達式值為0時止語句真假假表達式語句;for語句for(表達式1;表達式2;表達式3)

{

語句;}首先執(zhí)行表達式1。如果表達式2的值為非0,就重復執(zhí)行語句和表達式3,直到表達式2的值為0時止語句;循環(huán)起始條件循環(huán)結束條件循環(huán)增量for語句for(表達式1;表達式2;表達式3)

{

語句;}相當于:

表達式1和表達式3可以沒有或者是用逗號分隔的多個表達式的組合。但最好不要有太多的表達式組合語句;

表達式1;

while(表達式2){

語句;

表達式3;

}do-while語句do

{

語句;

}while(表達式);首先執(zhí)行語句,然后判斷表達式的值。如果表達式為0,繼續(xù)向下執(zhí)行,否則,再次執(zhí)行語句,再次判斷表達式的值語句會被至少執(zhí)行一次表達式語句假真語句;條件PA當型循環(huán)直到循環(huán)真假假條件PA假真假條件P條件PA假當循環(huán)條件第一次就為假時選擇三種循環(huán)的一般原則如果循環(huán)次數(shù)已知,用for如果循環(huán)次數(shù)未知,用while如果循環(huán)體至少要執(zhí)行一次,用do-while這只是“一般”原則,不是“原則”注意在for和while語句之后一般沒有分號有分號表示循環(huán)體就是分號之前的內容(空循環(huán)體)while(i<100);

i++;for(i=0;i<100;i++);

printf("%d",i);for通常有一個循環(huán)變量控制循環(huán)的次數(shù),不要在循環(huán)體內改變這個變量現(xiàn)場編程計算1+2+…+100=?分別用如下語句編程forwhiledo-while循序漸進式編程

——例4.6:猜數(shù)游戲想一個1~100之間的數(shù)猜對:right猜錯:wrong并提示大小只猜1次直到猜對為止最多猜10次猜多個數(shù)10次猜不對就猜下一個數(shù)循序漸進式編程

——例4.6:猜數(shù)游戲猜數(shù)游戲用到的庫函數(shù)怎樣模擬計算機“想”一個數(shù)呢?隨機函數(shù)rand()產生[0,RAND_MAX]

之間的隨機數(shù)magic=rand();#include<stdlib.h>RAND_MAX在stdlib.h中定義,不大于雙字節(jié)整數(shù)的最大值32767產生[0,b-1]之間的隨機數(shù)magic=rand()%b;產生[a,a+b-1]之間的隨機數(shù)magic=rand()%b+a;#include<stdlib.h>#include<stdio.h>

main(){

intmagic;/*計算機"想"的數(shù)*/

intguess;/*人猜的數(shù)*/

magic=rand()%100+1;/*“想”一個[1,100]之間的數(shù)magic*/ printf("Pleaseguessamagicnumber:"); scanf("%d",&guess);

if(guess>magic) {printf("Wrong!Toohigh!\n"); }

elseif(guess<magic) {printf("Wrong!Toolow!\n"); }

else

{ printf("Right!\n"); printf("Thenumberis:%d\n",magic); }}只猜1次#include<stdlib.h>#include<stdio.h>main(){

intmagic;

intguess;

intcounter;/*記錄人猜次數(shù)的計數(shù)器變量*/ magic=rand()%100+1;

counter=0;/*計數(shù)器變量count初始化為0*/

do{ printf("Pleaseguessamagicnumber:"); scanf("%d",&guess);

counter++;/*計數(shù)器變量count加1*/

if(guess>magic) printf("Wrong!Toohigh!\n");

elseif(guess<magic) printf("Wrong!Toolow!\n");

}while(guess!=magic);

printf("Right!\n"); printf("counter=%d\n",counter);}直到猜對為止#include<stdlib.h>#include<stdio.h>main(){

intmagic;

intguess;

intcounter;

magic=rand()%100+1; counter=0;

do{ printf("Pleaseguessamagicnumber:"); scanf("%d",&guess); counter++;

if(guess>magic) printf("Wrong!Toohigh!\n");

elseif(guess<magic) printf("Wrong!Toolow!\n"); }while((guess!=magic)&&(counter<10));

printf("Right!\n"); printf("counter=%d\n",counter);}最多猜10次例4.11:國王的許諾相傳國際象棋是古印度舍罕王的宰相達依爾發(fā)明的。舍罕王十分喜歡象棋,決定讓宰相自己選擇何種賞賜。這位聰明的宰相指著8×8共64格的象棋盤說:陛下,請您賞給我一些麥子吧,就在棋盤的第一個格子中放1粒,第2格中放2粒,第3格放4粒,以后每一格都比前一格增加一倍,依此放完棋盤上的64個格子,我就感恩不盡了。舍罕王讓人扛來一袋麥子,他要兌現(xiàn)他的許諾。

國王能兌現(xiàn)他的許諾嗎?試編程計算舍罕王共要多少麥子賞賜他的宰相,這些麥子合多少立方米?(已知1立方米麥子約1.42e8粒)

總粒數(shù)為:sum=1+2+22+23+…+263

例4.11方法1#defineCONST1.42e8#include<stdio.h>#include<math.h>main(){

intn;

doubleterm,sum=0;/*累加求和變量賦初值*/

for(n=1;n<=64;n++){

term=pow(2,n-1);

/*根據(jù)累加項的規(guī)律計算累加項

*/sum=sum+term;/*作累加運算*/}

printf("sum=%e\n",sum);/*打印總麥粒數(shù)*/

printf("volum=%e\n",sum/CONST);/*折合總麥粒體積數(shù)*/}

例4.11方法2#defineCONST1.42e8#include<stdio.h>main(){

intn;

doubleterm=1,sum=1;/*累乘求積累加求和變量賦初值*/

for(n=2;n<=64;n++){

term=term*2;/*根據(jù)后項總是前項的2倍計算累加項*/sum=sum+term;/*作累加運算*/}

printf("sum=%e\n",sum);/*打印總麥粒數(shù)*/

printf("volum=%e\n",sum/CONST);/*折合總麥粒體積數(shù)*/}

作業(yè)P143~152習題4.12,4.16,4.18嵌套循環(huán)使用嵌套的循環(huán)體時,應注意以下問題

在嵌套的各層循環(huán)體中,使用復合語句(即用一對大花括號將循環(huán)體語句括起來)保證邏輯上的正確性

內層和外層循環(huán)控制變量不應同名,以免造成混亂

嵌套的循環(huán)最好采用右縮進格式書寫,以保證層次的清晰性

自己閱讀P278-283,代碼風格問題,網(wǎng)站上代碼規(guī)范的ppt循環(huán)嵌套不能交叉,即在一個循環(huán)體內必須完整的包含著另一個循環(huán)

例4.14:打印乘法九九表

例4.14#include<stdio.h>main(){

intm,n;

for(m=1;m<10;m++) printf("%4d",m);/*打印表頭*/ printf("\n");

for(m=1;m<10;m++) printf("-"); printf("\n");

for

(m=1;m<10;m++)

{

for

(n=1;n<10;n++) { printf("%4d",m*n); } printf("\n"); }}例4.15:打印下三角乘法九九表

#include<stdio.h>main(){

intm,n;

for(m=1;m<10;m++) printf("%4d",m);/*打印表頭*/ printf("\n");

for(m=1;m<10;m++) printf("-"); printf("\n");

for

(m=1;m<10;m++)

{

for

(n=1;

n<=m;n++) { printf("%4d",m*n); } printf("\n"); }}例4.15例4.16:馬克思手稿中的趣味數(shù)學題有30個人,其中有男人、女人和小孩,在一家飯館里吃飯共花了50先令,每個男人各花3先令,每個女人各花2先令,每個小孩各花1先令,問男人、女人和小孩各有幾人?

解方程組窮舉法例4.16方法1:

采用三重循環(huán)窮舉x,y,z的全部可能的組合

#include<stdio.h>main(){

intx,y,z;

printf("Man\tWomen\tChildern\n");

for(x=0;x<=30;x++)

for(y=0;y<=30;y++)

for(z=0;z<=30;z++)

if(x+y+z==30&&3*x+2*y+z==50)

printf("%3d\t%5d\t%8d\n",x,y,z);}

例4.16方法2:改進算法

#include<stdio.h>

main(){

intx,y,z;

printf("Man\tWomen\tChildern\n");

for(x=0;x<=16;x++)

for(y=0;y<=25;y++){

z=30–x-y;

if(3*x+2*y+z==50)

printf("%3d\t%5d\t%8d\n",x,y,z);}}

作業(yè)P143~152習題4.20,4.21,4.22,4.25,4.27,4.28流程的轉移控制break語句continue語句goto語句break和continue對for、while、do-while循環(huán)進行內部手術break,退出一層循環(huán)或者switchcontinue,中斷此次循環(huán)體的執(zhí)行,開始下一次break和continue少用為妙break和continue假假真真break表達式1表達式2循環(huán)語句的下一條語句循環(huán)語句的下一條語句假假真真

表達式1表達式2continue例4.17:單步運行演示break語句和continue語句的用法區(qū)別#include<stdio.h>main(){

inti,n;

for(i=1;i<=5;i++) { printf("Pleaseentern:"); scanf("%d",&n);

if(n<0)

break; printf("n=%d\n",n); } printf("Programisover!\n");}Pleaseentern:10↙n=10Pleaseentern:-10↙Programisover!例4.17:單步運行演示break語句和continue語句的用法區(qū)別#include<stdio.h>main(){

inti,n;

for(i=1;i<=5;i++) { printf("Pleaseentern:"); scanf("%d",&n);

if(n<0)

continue; printf("n=%d\n",n); } printf("Programisover!\n");}Pleaseentern:10↙n=10Pleaseentern:-10↙Pleaseentern:20↙n=20Pleaseentern:-20↙Pleaseentern:30↙n=30Programisover!標號舉例error:goto舉例gotoerror;一般形式

goto語句標號;……

語句標號:……或語句標號:…………goto語句標號;goto與標號(label)是goto的過錯?還是程序員的過錯?破壞了結構化設計風格容易帶來錯誤隱患

gotonext;

intsum=0;/*被goto跳過*/…next:Evilgoto’s?MaybeNot…

凌波微步,未必摔跤現(xiàn)代觀點認為:混亂根源不在goto,而在標號任何程序都可以不用goto就實現(xiàn)其功能但在某些情況下,使用goto可以讓程序更清晰兩種適合使用goto的情況跳向共同的出口位置,進行退出前的處理工作跳出多重循環(huán)的一條捷徑{…{…{…gotoerror;}}}使用goto的原則主張少用、慎用,而不是禁用保證使用之后,程序仍然是單入口,單出口不要使用一個以上的標號不要用goto往回跳,要向下跳不要讓goto制造出永遠不會被執(zhí)行的代碼其他流程轉移控制return語句將在第5章講解標準庫函數(shù)exit()

作用是終止整個程序的執(zhí)行,強制返回操作系統(tǒng)調用該函數(shù)需要嵌入頭文件<stdlib.h>例4.19:輸入一個整數(shù),判斷它是否是素數(shù)

goto語句例4.19:方法1#include<math.h>main(){

intm,i,k;

printf("Pleaseenteranumber:");

scanf("%d",&m); k=sqrt(m);

for(i=2;i<=k;i++) {

if(m%i==0) {

printf("No!\n");

gotoend; } }

printf("Yes!\n");end:

printf("Programisover!\n");}Pleaseenteranumber:

6

Programisover!No!#include<math.h>main(){

intm,i,k;

printf("Pleaseenteranumber:");

scanf("%d",&m); k=sqrt(m);

for(i=2;i<=k;i++) {

if(m%i==0) {

printf("No!\n");

gotoend; } }

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論