




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
在線教務輔導網:://教材其余課件及動畫素材請查閱在線教務輔導網QQ:349134187
或者直接輸入下面地址:第8章結構體、共用體和枚舉類型以及鏈表編程技巧分析C語言編程技巧分析本章概述本章首先簡單介紹結構體、共用體和枚舉類型以及鏈表的相關知識,接著詳細講解運用結構體、共用體和枚舉類型以及鏈表知識時需要注意的問題,并通過實例分析運用結構體、共用體和枚舉類型以及鏈表知識的一些編程技巧。本章的學習目標本章教學目的:
掌握結構體、共用體和枚舉類型以及鏈表知識;理解運用結構體、共用體和枚舉類型以及鏈表知識時需要注意的一些問題;掌握結構體、共用體和枚舉類型以及鏈表知識的相關編程技巧。本章教學重點:
運用結構體、共用體和枚舉類型以及鏈表知識需注意的問題和編程技巧。本章教學難點:
關于結構體、共用體和枚舉類型以及鏈表知識的編程技巧。8.1結構體、共用體和枚舉類型以及鏈表知識簡要介紹8.2運用結構體、共用體和枚舉類型以及鏈表知識時需要注意的問題8.3結構體、共用體和枚舉類型以及鏈表知識編程技巧分析本章主要內容8.1結構體、共用體和枚舉類型以及鏈表知識簡要介紹8.1.1結構體1、結構體類型的聲明struct結構體名{
成員項表列;};例如:structSTU/*聲明一個結構體類型,名稱是structSTU*/{longxh[11];/*xh是一個成員,存放學號*/charxm[20];/*xm是一個成員,存放姓名*/charbj[20];/*bj是一個成員,存放班級*/floatcj[3];/*cj是一個成員,存放三科考試成績*/};8.1結構體、共用體和枚舉類型以及鏈表知識簡要介紹8.1.1結構體2、結構體類型變量的定義結構體類型變量的定義可以有以下三種形式:(1)先聲明結構體類型,再定義結構體類型的變量。例如利用上面的structSTU結構體類型,可以在下面定義structSTU類型的變量:structSTUstudent1,student2(2)聲明結構體類型同時定義結構體類型變量:structDATE/*日期結構體類型*/{intday;
intmonth;
intyear;}time1,time2;/*定義兩個structDATE類型變量*/8.1結構體、共用體和枚舉類型以及鏈表知識簡要介紹8.1.1結構體(3)直接定義結構體類型變量:struct{floatre;/*復數的實部*/floatim;/*復數的虛部*/}a,b;/*定義兩個復數型變量*/3、結構體成員的引用結構體成員的引用格式如下:<結構體類型變量名>.<成員名>如:a.re=2;a.im=2.5;time1.day=23;time2.month=12;strcpy(student1.xm,〞張三〞);8.1結構體、共用體和枚舉類型以及鏈表知識簡要介紹8.1.1結構體4、結構體類型變量的初始化上述對結構體類型變量的三種定義形式均可在定義時初始化,例如:structSTUstudent={1213012,"李強","英語1班",98.5,97.4,95};5、結構體類型的數組結構體類型數組的定義與其它數據類型數組的定義方式一樣,例如:structSTUclass[50];
/*定義一個50個元素的結構體數組*/引用結構體類型數組元素的成員的格式:<結構體類型數組名><[下標]>.<成員>例如:class[i].xm表示第i個學生的姓名,
class[i].bj表示第i個學生的班級。
8.1結構體、共用體和枚舉類型以及鏈表知識簡要介紹8.1.1結構體6、結構體類型的指針變量結構體類型的指針變量的定義格式如下:struct
結構體類型名*變量名;例如:structSTUstudent1,*p=&student1;可以通過結構體指針變量間接訪問結構變量的各個成員。其訪問的格式為:(*結構體指針變量).成員名或結構體指針變量->成員名例如:(*p).xh
或者p->xh
等價于student1.xh
注意:(*p)兩側的括號不可少。8.1結構體、共用體和枚舉類型以及鏈表知識簡要介紹8.1.2共用體1、共用體類型的聲明和共用體類型變量的定義共用體類型的聲明與結構體類型的聲明類似,格式如下:union共用類型名{成員列表};共用變量的定義與結構變量的定義類似,三種格式如下:直接定義:
間接定義:
省略類型名直接定義:union共用體名union共用體名
union{成員列表{成員列表};
{成員列表}變量列表;
union共用體名變量列表;}變量列表;
8.1結構體、共用體和枚舉類型以及鏈表知識簡要介紹8.1.2共用體2、共用體變量的引用引用形式與結構體變量一樣,只能逐個引用共用體變量的成員。注意:不能對共用體變量進行整體的輸入或輸出。假設a是共用體類型變量,那么下面語句都是錯誤的:scdanf(“%d〞,&a);printf(“%d〞,a);訪問共用體類型變量a成員的格式與訪問結構體變量成員格式相同,假設i是a的一個int型成員,那么下面的輸入或輸出格式是正確的:scanf(“%d〞,&a.i);printf(“%d\n〞,a.i);8.1結構體、共用體和枚舉類型以及鏈表知識簡要介紹8.1.2共用體3、共用體與結構體相似之處〔1〕都是由不同類型的數據項組合在一起;〔2〕都只能對分量進行操作和引用。4、共用體變量的特點〔1〕系統采用覆蓋技術,實現共用體變量各成員的內存共享,所以在某一時刻,存放在內存中的和起作用的是最后一次存入的成員值。共用體變量占用的內存空間,等于最長的成員的長度,而不是各成員長度之和。〔2〕由于所有成員共享同一內存空間,故共用體變量的地址與各成員的地址相同。〔3〕不能對共用體變量進行初始化〔而結構體變量可以初始化〕;也不能將共用體變量作為函數參數,以及使函數返回一個共用體數據,但可以使用指向共用體變量的指針。〔4〕共用類型可以出現在結構類型定義中,反之亦然。8.1結構體、共用體和枚舉類型以及鏈表知識簡要介紹8.1.3枚舉類型1、枚舉類型的聲明enum枚舉類型名{取值表};例如enumweekdays{Sun,Mon,Tue,Wed,Thu,Fri,Sat};上面括號中的標識符稱為枚舉常量。它只能為標識符,不能為數字常量或字符常量。2、枚舉變量的定義枚舉變量的定義與結構體變量類似,有下面一些定義形式:〔1〕間接定義,例如:enumweekdaysw1,w2;〔2〕直接定義,例如:enumweekdays{Sun,……}w1,w2;〔3〕省略類型名直接定義枚舉變量,例如:enum{Sun,Mon,Tue,Wed,Thu,Fri,Sat}w3,w4;8.1結構體、共用體和枚舉類型以及鏈表知識簡要介紹8.1.4鏈表鏈表是動態地進行存儲分配的一種結構,鏈表中的數據在內存中不必連續存放,數據之間通過指針鏈接起來,相比于數組結構,鏈表的插入和刪除操作比較方便。1、鏈表中的結點鏈表中的結點是結構體類型的數據,每個結點的所有成員分為兩局部,一局部用來存放數據〔各種實際的信息〕,如編號、姓名和年齡等;另一局部存放指針,用來連接其它結點。例如:定義了一個結構體類型變量a,成員num、name和score用來存放數據〔各種實際的信息〕,成員next用來存放指針〔指向下一個結點的首地址〕。structNODE{intnum;charname[10];intage;structNODE*next;}a;8.1結構體、共用體和枚舉類型以及鏈表知識簡要介紹8.1.4鏈表2、鏈表的種類:〔1〕單向鏈表:每個結點除了一些數據成員外,只包含一個指針成員。單向鏈表通常有一個頭指針〔head),用于指向鏈表頭。單向鏈表有一個尾結點,尾結點的指針成員存放的是空指針〔NULL〕。〔2〕循環鏈表:最后一個結點的指針指向該循環鏈表的第一個結點或者表頭結點,從而構成一個環形的鏈。〔3〕雙向鏈表:結點除含有數據成員外,還有兩個指針成員,一個指針成員存儲直接后繼結點地址;另一個指針成員存儲直接前驅結點地址。8.1結構體、共用體和枚舉類型以及鏈表知識簡要介紹8.1.4鏈表3、單向鏈表的根本操作:〔1〕創立鏈表:從無到有地建立起一個鏈表,即往空鏈表中依次插入假設干結點,并保持結點之間的前驅和后繼關系。〔2〕查找結點:按給定的結點索引號或查找條件,查找某個結點。〔3〕插入操作:在結點a與b之間插入一個新的結點d。〔4〕刪除操作:將結點a與b之間的結點d刪除。〔5〕打印輸出:輸出結點的數據成員值。8.1結構體、共用體和枚舉類型以及鏈表知識簡要介紹8.1.4鏈表4、處理動態鏈表所需的函數:〔1〕void*malloc(unsignedintsize);作用:在內存的動態存儲區中分配一個長度為size的連續空間。〔2〕void*calloc(unsignedn,unsignedsize);作用:在內存動態區中分配n長度為size的連續空間。〔3〕void*realloc(void*mem_address,unsignedintnewsize);作用:擴大mem_address指向的內存塊的大小為newsize。〔4〕voidfree(void*p);作用:釋放由p指向的內存區。8.2運用結構體、鏈表等知識時需要注意的問題關于結構體和共用體的類型聲明〔1〕區分開類型名與變量名結構體類型名和結構體變量名是兩個不同的概念,不能混淆。結構體類型名只能表示一個結構形式,編譯系統并不對它分配內存空間。只有當某變量被說明為這種類型的結構時,才對該變量分配存儲空間。〔2〕結構體與共用體可以相互引用C語言在聲明某個結構體類型或共用體類型時,可以使用已經聲明過的結構體、共用體類型。結構體類型中可以有共用體類型的成員,共用體類型中可以有結構體類型的成員。例如:8.2運用結構體、鏈表等知識時需要注意的問題關于結構體和共用體的類型聲明structdata{intday;intmouth;intyear;};structperson{charname[20];structdatabirthday;/*成員birthday的類型structdata已經在前面聲明過*/union{chardepartment[50];/*假設為教師身份時,成員category為department*/intclass;/*假設為學生身份時,成員category為class*/}category;/*成員category是共用體類型*/}x;8.2運用結構體、鏈表等知識時需要注意的問題關于結構體和共用體的類型聲明〔3〕typedef與結構體的聯合應用使用typedef命令可以取一個新的類型名來代替已有的類型名,一般當有復雜類型定義時,如定義結構體類型、共用體類型時,常常用typedef為剛定義的復雜類型取一個較為簡單、直接的類型名。例如:typedefstructnode{longnum;charname[10];structnode*next;}NODE,*LINK;
8.2運用結構體、鏈表等知識時需要注意的問題關于結構體和共用體的類型聲明上面聲明了一個內容與structnode相同但名為NODE的結構體類型名,還聲明了一個結構體指針類型LINK。注意,LINK不是指針變量,而是一個指針類型。以下定義變量的形式都正確:
structnodestu1,*p;/*定義結構體變量stu1和指針變量p*/NODEstu2,*q;/*定義結構體變量stu2和指針變量q*/LINKr;/*定義結構體指針變量r*/8.2運用結構體、鏈表等知識時需要注意的問題關于結構體和共用體的類型聲明〔4〕不能遞歸定義在定義鏈表的結點類型時常常用結構體類型本身去定義一個指針分量,如前面例子中的next分量,通過這個分量,使鏈表中的結點鏈接起來,這是允許的,也是必須的。但是絕對不能用結構體類型自己去定義自己的一個非指針類型分量,也就是不能遞歸定義。如下是錯誤的:structnode{……;structnodenext;};
8.2運用結構體、鏈表等知識時需要注意的問題關于結構體、共用體變量的輸入和輸出結構體、共用體類型變量的輸入和輸出,必須采用變量的各成員獨立輸入輸出,而不能將結構體、共用體類型變量以整體的形式輸入輸出。可以通過C語言提供的輸入輸出函數完成對結構體、共用體類型變量成員的輸入輸出。結構體、共用體變量各成員的數據類型通常是不一樣的,為了統一輸入過程,可以先將變量的各成員均以字符串形式輸入,然后利用C語言的類型轉換函數將其轉換為所需類型。8.2運用結構體、鏈表等知識時需要注意的問題關于結構體、共用體變量的輸入和輸出類型轉換的函數是:int
atoi(char*str);/*轉換str所指向的字符串為整型*/doubleatof(char*str);/*轉換str所指向的字符串為實型,*/longatol(char*str);/*轉換str所指向的字符串為長整型*/
使用上述函數,要包含頭文件"stdlib.h"。對上述的結構體類型structnode的變量student的成員輸入采用的一般形式:chartemp[20];
gets(student.xm);/*輸入結構體變量的成員xm的值*/gets(temp);student.xh=atol(temp);/*轉換為長整型后賦值*/for(i=0;i<3;i++)
{gets(temp);
student.cj[i]=atoi(temp);/*轉換為整型后賦值*/}8.2運用結構體、鏈表等知識時需要注意的問題關于共用體與結構體的主要區別〔1〕結構體變量占用空間是各成員所占空間之總和;共用體變量占存儲空間是各成員中所占空間最大者。〔2〕結構體變量各成員占用內存中一片連續的存儲區,各成員的地址互不相同;共用體變量各成員在內存中所占空間的起始地址相同。〔3〕結構體變量的各個分量在任何時刻都同時存在,且可同時引用。共用體變量的各個分量在某一時刻只存在其中一個,也只能引用其中的一個。〔4〕結構體變量可以初始化,共用體變量不能初始化。8.2運用結構體、鏈表等知識時需要注意的問題8.2.4關于結構體與函數〔1〕結構體作函數參數將一個結構體變量的值傳遞給另一個函數,可以采用兩種方式:用結構體變量作參數,形參與實參都用結構體變量,參數傳遞時直接將實參結構體變量的各個成員的值全部傳遞給形參的結構體變量。注意:這種方式是按傳值方式傳遞參數的,函數中形參結構體變量的修改不影響實參結構體變量的值;這種方法要將全部成員值一個一個傳遞,開銷大,因此一般不采用。用指向結構體的指針作函數參數,形參為結構體類型的指針變量,實參為結構體變量〔或數組〕的地址或指向結構體變量〔數組〕的指針。這種方式只傳遞地址,不傳遞結構體變量的值,克服了第一種方法的缺點,實際編程中被較多采用。8.2運用結構體、鏈表等知識時需要注意的問題關于結構體與函數〔2〕結構體作函數的返回值與結構體作函數參數相類似,既可以設置函數的返回值為結構體類型的,也可以設置函數的返回值為結構體指針類型的。前者在運行時會有較多的數據復制,不利于提高程序的效率;后者只傳遞指針,開銷小,效率高,多為程序設計者所采用。8.2運用結構體、鏈表等知識時需要注意的問題8.2.5關于枚舉類型〔1〕枚舉類型僅適用于取值有限的數據。例如:1周的7天,1年的12個月。〔2〕取值表中的值為枚舉元素,其含義由程序解釋。例如,不是寫成“Sun〞就自動代表“星期天〞。事實上,枚舉元素用什么表示都可以。〔3〕枚舉類型變量w1,w2只能在定義的取值表中取其中一個枚舉常量作為當前值。〔4〕枚舉元素作為常量是有值的,假設無特殊規定,枚舉元素的值是定義時的順序號。定義時的順序號,從0開始,依次增1。所以枚舉元素可以進行比較,比較規那么是:序號大者為大。例如,上例中的Sun=0、Mon=1、……、Sat=6,所以Mon>Sun、Sat最大。8.2運用結構體、鏈表等知識時需要注意的問題關于枚舉類型〔5〕枚舉元素的值也是可以改變的。可以由程序指定,例如:enumweekdays{Sun=7,Mon=1,Tue,Wed,Thu,Fri,Sat};那么Sun=7,Mon=1,從Tue=2開始,依次增1。〔6〕一個整型數值不能直接賦值給一個枚舉變量。enumweekdays{Sun=7,Mon=1,Tue,Wed,Thu,Fri,Sat};enumweekdayswk1;不允許直接賦值整數:wk1=7;/*數據類型不同*/只能寫成:wk1=Sun;或wk1=(enumweekdays)7;甚至可以是表達式,如:w2=(enumweekday)(5-3);8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于結構體知識編程技巧分析例8.1用結構體類型描述一個一元二次方程〔ax2+bx+c=0〕,并編寫一個求其根的函數。程序如下:#include"stdio.h"#include"math.h"structfaction{floata;floatb;floatc;floatx1,x2;};intjie(structfaction*f){floatdel;del=(f->b)*(f->b)-4*(f->a)*(f->c);if(del>=0){f->x1=(-f->b+sqrt(del))/(2*f->a);f->x2=(-f->b-sqrt(del))/(2*f->a);return1;}elsereturn0;}8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于結構體知識編程技巧分析main(){structfactionf1;intresult;printf("請輸入一個一元二次方程的三個系數");scanf("%f%f%f",&f1.a,&f1.b,&f1.c);result=jie(&f1);if(result=1)printf("x1=%f,x2=%f\n",f1.x1,f1.x2);elseprintf("無實數解");}分析:這個例子通過一個結構體把一個一元二次方程相關的數據都封裝在一起,然后通過相應的函數操作此數據對象,已具備初步的面向對象程序設計的思想。注意兩種引用結構體成員的方法,在main函數中對f1成員的引用直接用f1.x1、f1.x2,而在jie函數中由于f是指針變量,故引用的方法是f->x1、f->x2等等。8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于結構體知識編程技巧分析例8.2輸入3名學生信息〔信息包括學號、姓名和計算機成績〕。然后輸出這3名學生信息,最后將其中成績最高的學生全部信息顯示在屏幕上。程序如下:第1種方法:使用普通的結構體變量,每個學生的信息存放在一個變量中。#include<stdio.h>structstudents{longno;charname[10];intscore;};main(){structstudentss1,s2,s3,max;scanf("%ld%s%d",&s1.no,,&s1.score);scanf("%ld%s%d",&s2.no,,&s2.score);scanf("%ld%s%d",&s3.no,,&s3.score);8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于結構體知識編程技巧分析printf("%d%s%4d\n",s1.no,,s1.score);printf("%d%s%4d\n",s2.no,,s2.score);printf("%d%s%4d\n",s3.no,,s3.score);max=s1;if(max.score<s2.score)max=s2;if(max.score<s3.score)max=s3;printf("Thestudentwithmaxscoreis:\n");printf("%d%10s%4d\n",max.no,,max.score);}
第2種方法:使用指針變量,找出其中成績最高的學生。程序的前面不動,只是定義指針變量p代替上面的max,程序修改如下:8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于結構體知識編程技巧分析structstudents*p;…printf("%d%s%4d\n",s3.no,,s3.score);p=&s1; if(p->score<s2.score)p=&s2;if(p->score<s3.score)p=&s3;printf("Thestudentwithmaxscoreis:\n");printf("%d%10s%4d\n",p->no,p->name,p->score);…8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于結構體知識編程技巧分析分析:在程序中可以看到,對結構體變量賦值時,必須對其每一個分量賦值〔定義時初始化例外〕。但同結構的結構體變量之間可以整體賦值,這與數組的操作完全不同。輸出結構體變量時也只能通過輸出其中的每一個成員來實現,不能整體輸出。對結構體類型數據的根本操作,例如求平均值、最大值、最小值、排序等,算法與簡單型數據的算法是一樣的,只是操作時針對結構體類型數據中的某一個成員而已。針對上面的例子,請讀者自己完成求三個學生平均分的操作,以及完成成績從高到低輸出的操作。8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于結構體知識編程技巧分析例8.3修改例8.2,輸入100名學生信息〔信息包括學號、姓名和計算機成績〕,然后輸出這100名學生信息。最后編寫一函數,求出其中成績最高的學生,通過函數調用輸出此成績最高的學生信息。程序如下:#include<stdio.h>structstudents{longno;charname[10];intscore;};#defineN100intfind(structstudentsa[],intn){intp=0,i;for(i=1;i<n;i++)if(a[i].score>a[p].score)p=i;returnp;}8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于結構體知識編程技巧分析main(){structstudentss[N],max;for(inti=0;i<N;i++)scanf("%ld%s%d",&s[i].no,s[i].name,&s[i].score);for(i=0;i<N;i++)printf("%10d%10s%4d\n",s[i].no,s[i].name,s[i].score);max=s[find(s,N)];printf("Thestudentwithmaxscoreis:\n");printf("%10d%10s%4d\n",max.no,,max.score);}8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于結構體知識編程技巧分析分析:有100個學生,自然不能再用100個變量描述,需設置結構體數組完成。結構體數組作函數的參數用法與其他類型數組作函數參數一樣。函數返回值的設置,可以把成績最高學生的結構體整體設為返回值,也可以只返回他在數組中的下標,也可以返回指向他的指針。考慮到整體返回要進行相應的數據復制,需要較大的系統開銷,因此選擇返回下標。函數的參數和返回值都可能設置為結構體類型的指針變量,請讀者自己修改完成。8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于結構體知識編程技巧分析例8.4模擬一個井字棋雙人對戰游戲。井字棋游戲的棋盤是一個2*2的格子,棋子下在交叉點上,交叉點正好是3行3列,最早連成3個棋子成一線的一方獲勝。程序如右:structposition{intx;inty;};intqipan[3][3]={0};/*棋盤數據結構*/voidprintqipan(intqp[3][3])/*打印棋盤*/{inti;for(i=0;i<3;i++){if(qp[i][0]==0)printf("+--");elseif(qp[i][0]==1)printf("o--");elseprintf("*--");if(qp[i][1]==0)printf("+--");elseif(qp[i][1]==1)printf("o--");elseprintf("*--");if(qp[i][2]==0)printf("+");elseif(qp[i][2]==1)printf("o");elseprintf("*");printf("\n");}}8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于結構體知識編程技巧分析intcheck(structposition*play,inti)/*檢測有無3個棋子連成一線*/{intk;intx=play[i].x;inty=play[i].y;intqizi=qipan[x][y];for(k=0;k<=2;k++)*/檢查所在行是否都是同一棋子*/if(qipan[x][k]!=qizi)break;if(k>2)return1;for(k=0;k<=2;k++)*/檢查所在列是否都是同一棋子*/if(qipan[k][y]!=qizi)break;if(k>2)return1;for(k=0;k<=2;k++)*/檢查所在對角線是否都是同一棋子*/if(qipan[k][k]!=qizi)break;if(k>2)return1;for(k=0;k<=2;k++)*/檢查所在反對角線是否都是同一棋子*/if(qipan[k][2-k]!=qizi)break;if(k>2)return1;return0;}8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于結構體知識編程技巧分析if(check(play1,i)){printf("1號選手勝利了");return;}if(num==9)break;/*最多只有9個位置*/do{printf(“選手2輸入下子的位置:");scanf("%d,%d",&t_x,&t_y);}while(qipan[t_x][t_y]!=0);play2[i].x=t_x;play2[i].y=t_y;qipang[t_x][t_y]=2;num+=1;printqipan(qipan);if(check(play2,i)){printf("2號選手勝利了");return;}i++;}printf("兩人都失敗了");}main(){inti,num=0,t_x,t_y;structpositionplay1[5],play2[5];/*每個選手最多下5次*/printqipan(qipan);i=1;while(num<9){do{printf("選手1輸入下子的位置:");scanf("%d,%d",&t_x,&t_y);}while(qipan[t_x][t_y]!=0);play1[i].x=t_x;play1[i].y=t_y;qipan[t_x][t_y]=1;num+=1;printqipan(qipan);8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于結構體知識編程技巧分析〔1〕棋盤的模擬。因為棋盤上的交叉點正好是3行3列,因此用一個3行3列的二維數組即可。數組元素初始值為0,表示未有棋子落下;值為1表示落下的是1號選手棋子,值為2表示落下的是2號選手的棋子。〔2〕是否連成一線的檢測。對剛落下的棋子檢查所在行是否都是同一個選手的棋子;同樣再檢測所在列是否都是同一選手的棋子;同樣的方法再檢測對角線和反對角線。〔3〕對棋子位置的描述。用一個結構體,把棋子所在的行號和列號組合在一起。程序中對連成一線的檢測是從棋盤的角度出發,檢測有沒有相同值的行、列、對角線,我們也可從選手已下的棋子,即play1、play2數組出發,檢測是否有3個的同值的行號分量或列號分量。程序請讀者編寫。8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析8.3.2關于共用體和枚舉類型知識編程技巧分析例8.6有一個教師與學生通用的表格,教師有姓名、年齡、類型、教研室四項數據。學生有姓名、年齡、類型、班級四項數據。輸入所有教師和學生的數據,再以表格形式輸出。程序如下:#include<stdio.h>#defineN100/*設教師和學生共有N個*/unionc_t{intclassno;/*學生班級號*/charoffice[10];/*教師教研室名*/};structStu_Tea
{charname[10];/*姓名*/intage;/*年齡*/inttype;/*類型*/unionc_tdepart;/*教研室名或班級號*/};8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于共用體和枚舉類型知識編程技巧分析voidmain(){structStu_Teabody[N];inti,k;for(i=0;i<N;i++)/*輸入學生或教師信息*/{printf("輸入姓名、年齡\n");scanf("%s%d",body[i].name,&body[i].age);printf("假設此人是教師,類型請輸入1;假設此人是學生,類型請輸入0。\n");scanf("%d",&body[i].type);if(body[i].type==1)/*此人是教師,輸入教研室名*/{printf("輸入教研室名\n");scanf("%s",body[i].depart.office);}8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于共用體和枚舉類型知識編程技巧分析if(body[i].type==0)/*此人是學生,輸入班級號*/{printf("輸入班級號\n");scanf("%d",&body[i].depart.classno);}}printf("姓名、年齡、教研室或班級\n");/*顯示學生、教師信息*/for(i=0;i<N;i++){if(body[i].type==0)printf("%s\t%4d%4d\n",body[i].name,body[i].age,body[i].depart.classno);if(body[i].type==1)printf("%s\t%4d%s\n",body[i].name,body[i].age,body[i].depart.office);}}8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于共用體和枚舉類型知識編程技巧分析分析:以上程序中,結構體中的一個成員depart的類型是共用體,對于類型是學生或教師,可以選取不同的共用體成員。變量的引用是通過成員引用符“.〞實現的,同結體變量的引用一樣,也可以通過共用體指針變量引用,同樣,需要使用“->〞運算符實現。在計算機硬件編程中,尤其是單片機的C語言編程中,當需要訪問存放器時,經常會通過共用體類型變量來定義存放器,進一步的學習請讀者查閱相關資料。8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于共用體和枚舉類型知識編程技巧分析例8.7口袋中有紅、黃、藍、白、黑5種顏色的球假設干個。每次從口袋中先后取出3個球,問得到3種不同色的球的可能取法,輸出每種可能取法排列的情況。程序如下:#include<stdio.h>main(){enumcolor{red,yellow,blue,white,black};/*聲明枚舉類型color*/enumcolori,j,k,pri;intn=0,loop;/*定義枚舉變量*/for(i=red;i<=black;i++)/*逐個檢查是否符合條件*/for(j=red;j<=black;j++)if(i!=j){for(k=red;k<=black;k++)8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于共用體和枚舉類型知識編程技巧分析
if((k!=i)&&(k!=j)){n=n+1;printf("%-4d",n);for(loop=1;loop<=3;loop++){switch(loop) {case1:pri=i;break;case2:pri=j;break;case3:pri=k;break;default:break;}switch(pri){casered:printf("%-10s","red");break;caseyellow:printf("%-10s","yellow");break;caseblue:printf("%-10s","blue");break;casewhite:printf("%-10s","white");break;caseblack:printf("%-10s","black");break;default:break;}}printf("\n");}}printf("\ntotal:%5d\n",n);}8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析8.3.2關于共用體和枚舉類型知識編程技巧分析
分析:每個球只能是5種色之一,而且要判斷各球是否同色,所以用枚舉類型變量處理。程序采用窮舉法,設取出的球為i、j、k。根據題意,i、j、k分別是5種色球之一,并要求i≠j≠k。通過三重循環把每一種組合都試一下,看哪一組符合條件。8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析8.3.3關于鏈表知識編程技巧分析例8.8從鍵盤輸入假設干個非零整數作為結點的數據元素,創立單向鏈表。程序如下:#include"stdio.h"#include"stdlib.h"#include"malloc.h"structLnode{intdata;structLnode*next;}*p,*q,*head;/*p為跟蹤表尾的指針,q為指向新結點的指針,head是指向頭結點的指針*/8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于鏈表知識編程技巧分析main(){inttemp;head=(structLnode*)malloc(sizeof(structLnode));if(head==NULL){printf("memoryallocatingerror!");exit(0);}head->next=NULL;p=head;printf("inputainteger:");scanf("%d",&temp);while(temp!=0){q=(structLnode*)malloc(sizeof(structLnode));if(q==NULL){printf("memoryallocatingerror!");exit(0);}q->data=temp;q->next=NULL;p->next=q;p=q;printf("inputainteger:");scanf("%d",&temp);}}8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析8.3.3關于鏈表知識編程技巧分析分析:〔1〕為了簡化鏈表操作中對表中有結點和無結點的情況處理,一般會在鏈表中增加一個結點,作為鏈表的第一個結點,但該結點不存放數據元素,特稱之為頭結點。頭結點的指針成員存放下一個數據元素結點的首地址。〔2〕首先建立一個有一個頭結點的單向鏈表,采用每次在鏈表的尾部增加一個結點的方式,將數據元素結點鏈接起來。由于新結點是添加在單向鏈表的尾部,故需要設置一個指向表尾的指針,且每添加一個新結點就要更新此指針。8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于鏈表知識編程技巧分析上述程序建立起來的單鏈表數據的順序正好與輸入的順序一致。如果對數據的順序不作要求,那么可以把新結點添加在鏈表的頭部,這樣就不需要跟蹤表尾指針,新建鏈表的效率更高。程序如下:#include"stdio.h"#include"stdlib.h"#include"malloc.h"structLnode{intdata;structLnode*next;}*q,*head;main(){inttemp;head=(structLnode*)malloc(sizeof(structLnode));8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于鏈表知識編程技巧分析if(head==NULL){printf("memoryallocatingerror!");exit(0);}head->next=NULL;printf("inputainteger:");scanf("%d",&temp);while(temp!=0){q=(structLnode*)malloc(sizeof(structLnode));if(q==NULL){printf("memoryallocatingerror!");exit(0);}q->data=temp;q->next=head->next;head->next=q;printf("inputainteger:");scanf("%d",&temp);}}8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于鏈表知識編程技巧分析例8.9單向鏈表有10個結點,各結點的數據成員data的值分別是1、3、5、7、9、11、13、15、17、19。將一個新結點插入到該單向鏈表的第i個結點位置上〔頭結點之后的第一個元素序號為1〕。程序如下:#include"stdio.h"#include"malloc.h"structnode{intdata;structnode*next;};8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于鏈表知識編程技巧分析structnode*insert(structnode*head,inti,intnewdata){structnode*q,*p;intj;if(i<0){printf("插入位置不存在");returnhead;}q=(structnode*)malloc(sizeof(structnode));q->data=newdata;p=head->next;j=1;while(p!=NULL&&j<i-1){j++;p=p->next;}if(p!=NULL){q->next=p->next;p->next=q;}returnhead;}8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于鏈表知識編程技巧分析main(){structnode*head,*newnode,*rear;inti,x;head=(structnode*)malloc(sizeof(structnode));head->next=NULL;
rear=head;for(i=1;i<=10;i++){newnode=(structnode*)malloc(sizeof(structnode));newnode->data=2*i-1;/*原鏈表的數據為1,3,5,7……*/newnode->next=NULL;
rear->next=newnode;
rear=newnode;}printf("請輸入新結點數據及插入的位置");scanf("%d%d",&x,&i);head=insert(head,i,x);printf("插入后的鏈表數據為:\n");for(structnode*p=head->next;p!=NULL;p=p->next)printf("%d-->",p->data);}8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于鏈表知識編程技巧分析分析:在p指針指向的結點插入之后,設新結點由指針q指向,那么插入的過程為:q->next=p->next;p->next=q;這種方法的關鍵之處是先要找到p的位置。由于新結點是插入在第i個位置上,因此p應該是指向第i-1個結點的指針。上述算法需要先對鏈表進行一次遍歷,如果問題中已告訴插入的位置為p指向的位置,能否不進行遍歷,直接把新結點插入到p指針指向的位置呢?可以采用如下方法,將新結點插入在p指針指向的結點之前。首先分配一個結點q,將q插入在p后,接下來將p結點與q結點的數據域的值作一下交換。這種方法算法就不需要遍歷鏈表了,效率高于前一方法。程序如下:8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于鏈表知識編程技巧分析#include"stdio.h"#include"malloc.h"structnode{intdata;structnode*next;};voidinsert2(structnode*p,intnewdata){structnode*q;intt;q=(structnode*)malloc(sizeof(structnode));q->data=newdata;q->next=p->next;p->next=q;/*將q插入在p的后面*/t=p->data;p->data=q->data;q->data=t;/*交換p和q的data值*/return;}8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于鏈表知識編程技巧分析main(){structnode*head,*newnode,*rear;inti,x;head=(structnode*)malloc(sizeof(structnode));head->next=NULL;rear=head;for(i=1;i<=10;i++){newnode=(structnode*)malloc(sizeof(structnode));newnode->data=2*i-1;/*原鏈表為有序的數據為1,3,5,7……*/newnode->next=NULL;rear->next=newnode;rear=newnode;}printf("請輸入新結點數據");scanf("%d",&x);for(structnode*p=head->next;p->data<x;p=p->next);insert2(p,x);printf("插入后的鏈表數據為:\n");for(p=head->next;p!=NULL;p=p->next)printf("%d-->",p->data);}8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于鏈表知識編程技巧分析例8.10編寫函數,在單向鏈表中刪除指定結點。給定一個特定值,假設單鏈表中某個數據結點的值與此特定值相同,那么刪除該結點;假設不存在,那么給出提示信息。程序如下:#include"stdio.h"#include"stdlib.h"#include"malloc.h"structLNode{intnum;structLNode*next;};8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于鏈表知識編程技巧分析structLNode*del(structLNode*head,longnum){structLNode*p,*q;if(head==NULL){printf("\nlistnull!\n");returnhead;}p=head;while(num!=p->num&&p->next!=NULL){q=p;p=p->next;}if(num==p->num){if(p==head)head=p->next;else{q->next=p->next;free(p);}printf("delete:%ld\n",num);}elseprintf("%ldnotbeenfound!\n",num);return(head);}關于鏈表知識編程技巧分析例8.10分析:〔1〕要刪除特定值結點,需要先遍歷單鏈表,找到待刪除的位置。〔2〕刪除指針變量p指向的結點,首先需要先得到p指向的結點的前面一個結點。因此,需要用指針變量q指向p所指向的結點的前面一個結點。〔3〕刪除結點不僅要修改指針的指向,還要用free函數釋放被刪除結點所占據的內存。8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于鏈表知識編程技巧分析例8.11對于單向鏈表,設計一個函數,從尾到頭反過來輸出每個結點的值,要求不破壞單鏈表。程序如下:voidprint_node(structnode*head){if(head==NULL)return;else{print_node(head->next);printf("%d",head->data);}}分析:〔1〕如果允許破壞此單向鏈表,那么可以先把此單向鏈表倒置,再依次輸出所有結點。這種方法簡單明了,輸出每個結點容易實現。〔2〕本程序用遞歸程序實現,利用遞歸算法可以使得輸出倒序。8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于鏈表知識編程技巧分析〔3〕用上述的遞歸程序需要屢次的函數調用,效率低下,可以考慮直接用堆棧的方法實現。先順序依次訪問單向鏈表,把讀到的數據壓入到堆棧中,全部讀完后再從堆棧中彈出就可以反過來輸出每個結點的值了。考慮到壓棧、出棧的開銷,可以用一個數組代替堆棧。程序如下:structnode{intdata;structnode*next;};voidprint_node(structnode*head){structnode*p=head->next;/*head指向的是頭結點。p指向第一個元素。*/intstack[100];/*模擬堆棧,假定結點元素類型為整型,不超過100個結點*/inti=0;while(p!=NULL){stack[++i]=p->data;p=p->next;}while(i>0)printf(“%d,〞,stack[i--]);}8.3結構體、共用體和枚舉類型以及鏈表編程技巧分析關于鏈表知識編程技巧分析例8.12編寫函數,將兩個有序的單向鏈表合并,要求在原有的結點根底上修改指針的指向,不產生新的結點。程序如下:structNode{intnum;structNode*next;};structNode*MergeList(structNode*head1,structNode*head2)/*按升序合并*/{structNode*head,*temp;if(head1==NULL)returnhead2;if(head2==NULL)returnhead1;if(head1->num<=head2->num){head=head1;head1=head1->next;}else
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 電視行業創新技術與未來發展方向考核試卷
- 監控攝像頭安裝與調試考核試卷
- 日用洗滌劑的清潔效果與環境保護性能考核試卷
- 自行車行業服務標準化建設考核試卷
- 療養院護理政策法規知識考核試卷
- 城市配送與物流配送環節的末端配送創新考核試卷
- 知識產權法律實務考核試卷
- 節日動畫廣告設計勞務合同
- 工業設備采購與設備性能維護合同
- 航天材料研發技術保密協議書
- (二模)2024~2025學年度蘇錫常鎮四市高三教學情況調研(二)物理試卷(含答案)
- 事件網絡輿情傳播機制的建模與仿真-全面剖析
- 初中信息技術蘇科版(2023)七年級下冊第七單元 跨學科主題學習-絲綢之路公開課教案及反思
- 2025年高考語文作文預測52篇(含范文)
- 《昭君出塞》課本劇劇本:感受歷史深處的家國情懷
- 領略文化魅力堅定文化自信(課件)(春晚、文化專題)2024-2025學年統編版道德與法治中考二輪熱點專題復習
- 投融資考試筆試題及答案
- 國內常見模具鋼牌號對照表
- 解聘證明范本
- 混凝土靜力抗壓彈性模量試驗記錄表
- 山東發達面粉集團有限公司 員工手冊
評論
0/150
提交評論