C第八部分(完結(jié))_第1頁
C第八部分(完結(jié))_第2頁
C第八部分(完結(jié))_第3頁
C第八部分(完結(jié))_第4頁
C第八部分(完結(jié))_第5頁
已閱讀5頁,還剩105頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

11.7用指針處理鏈表

main()

{structstudent*head,*stu;

longdel_num;printf("inputrecords:\n");

head=creat();print(head);

printf("\ninputthedeletednumber:");

scanf("%ld",&del_num);

while(del_num!=0){head=del(head,del_num);

print(head);printf("inputthedeletednumber:");

scanf("%ld",&del_num);}printf("\ninputtheinsertedrecord:");stu=(structstudent*)malloc(LEN);

scanf("%ld,%f",&stu->num,&stu->score);

while(stu->num!=0){head=insert(head,stu);printf("inputtheinsertedrecord:");stu=(structstudent*)malloc(LEN);

scanf("%ld,%f",&stu->num,&stu->score);

}}11.7用指針處理鏈表

stu定義為指針變量,在需要插入時(shí)先用malloc函數(shù)開辟一個(gè)內(nèi)存區(qū),將其起始地址經(jīng)強(qiáng)制類型轉(zhuǎn)換后賦給stu,然后輸入此結(jié)構(gòu)體變量中各成員的值。對(duì)不同的插入對(duì)象,stu的值是不同的,每次指向一個(gè)新的structstudent變量。在調(diào)用insert函數(shù)時(shí),實(shí)參為head和stu,將已建立的鏈表起始地址傳給insert函數(shù)的形參,將stu(即新開辟的單元的地址)傳給形參stud,返回的函數(shù)值是經(jīng)過插入之后的鏈表的頭指針(地址)11.7用指針處理鏈表

運(yùn)行結(jié)果:inputrecords:

10101,99

10103,87

10105,770,0Now,These3recordsare:

1010199.0

1010387.0

1010577.0

11.7用指針處理鏈表

intputthedeletednumber10103(刪除)delete:10103↙Now,these4recordsare1010199.01010576.0intputthedeletednumber10103(刪除)delete:10105↙Now,these4recordsare1010199.0

11.7用指針處理鏈表

intputthedeletednumber:0inputtheinsertedrecord10104,87↙Now,these3recordsare1010199.01010487

inputtheinsertedrecord10106,65↙Now,these3recordsare1010199.010104871010665.011.8共用體

11.8.1共用體的概念

使幾個(gè)不同的變量共占同一段內(nèi)存的結(jié)構(gòu)稱為“共用體”類型的結(jié)構(gòu)。定義共用體類型變量的一般形式為:union

共用體名

成員表列

}變量表列;圖11-2411.8共用體

例如:uniondatauniondata

{inti;{inti;charch;或

charch;floatf;floatf;}a,b,c;};uniondataa,b,c;11.8共用體

共用體和結(jié)構(gòu)體的比較:

結(jié)構(gòu)體變量所占內(nèi)存長(zhǎng)度是各成員占的內(nèi)存長(zhǎng)度之和。每個(gè)成員分別占有其自己的內(nèi)存單元。

共用體變量所占的內(nèi)存長(zhǎng)度等于最長(zhǎng)的成員的長(zhǎng)度。

共用體和結(jié)構(gòu)體的比較:

結(jié)構(gòu)體變量所占內(nèi)存長(zhǎng)度是各成員占的內(nèi)存長(zhǎng)度之和。每個(gè)成員分別占有其自己的內(nèi)存單元。

共用體變量所占的內(nèi)存長(zhǎng)度等于最長(zhǎng)的成員的長(zhǎng)度。

例如:上面定義的“共用體”變量a、b、c各占4個(gè)字節(jié)(因?yàn)橐粋€(gè)實(shí)型變量占4個(gè)字節(jié)),而不是各占2+1+4=7個(gè)字節(jié)。

11.8共用體

11.8.2共用體變量的引用方式

只有先定義了共用體變量才能引用它,而且不能引用共用體變量,而只能引用共用體變量中的成員。例如:前面定義了a、b、c為共用體變量

a.i(引用共用體變量中的整型變量i)a.ch(引用共用體變量中的字符變量ch)a.f(引用共用體變量中的實(shí)型變量f)11.8共用體

11.8.3共用體類型數(shù)據(jù)的特點(diǎn)(1)同一個(gè)內(nèi)存段可以用來存放幾種不同類型的成員,但在每一瞬時(shí)只能存放其中一種,而不是同時(shí)存放幾種。(2)共用體變量中起作用的成員是最后一次存放的成員,在存入一個(gè)新的成員后原有的成員就失去作用。

(3)共用體變量的地址和它的各成員的地址都是同一地址。

11.8共用體

(4)不能對(duì)共用體變量名賦值,也不能企圖引用變量名來得到一個(gè)值,又不能在定義共用體變量時(shí)對(duì)它初始化。(5)不能把共用體變量作為函數(shù)參數(shù),也不能使函數(shù)帶回共用體變量,但可以使用指向共用體變量的指針(6)共用體類型可以出現(xiàn)在結(jié)構(gòu)體類型定義中,也可以定義共用體數(shù)組。反之,結(jié)構(gòu)體也可以出現(xiàn)在共用體類型定義中,數(shù)組也可以作為共用體的成員。11.8共用體

例11.12設(shè)有若干個(gè)人員的數(shù)據(jù),其中有學(xué)生和教師。學(xué)生的數(shù)據(jù)中包括:姓名、號(hào)碼、性別、職業(yè)、班級(jí)。教師的數(shù)據(jù)包括:姓名、號(hào)碼、性別、職業(yè)、職務(wù)??梢钥闯觯瑢W(xué)生和教師所包含的數(shù)據(jù)是不同的?,F(xiàn)要求把它們放在同一表格中。圖11-2511.7用指針處理鏈表

算法:圖11-26

11.8共用體

#include<stdio.h> struct { intnum; charname[10]; charsex; charjob; union { intbanji; charposition[10]; }category; }person[2];/*先設(shè)人數(shù)為2*/11.8共用體

voidmain(){inti;for(i=0;i<2;i++){scanf("%d%s%c%c",&person[i].num,&person[i].name,&person[i].sex,&person[i].job);if(person[i].job=='S')scanf("%d",&person[i].category.banji);elseif(person[i].job=='T')scanf("%s",person[i].category.position);elseprintf(“Inputerror!”);}printf("\n");printf("Nsexjobclass/position\n");for(i=0;i<2;i++){if(person[i].job=='S')printf(“%-6d%-10s%-3c%-3c%-6d\n”,person[i].num,person[i].name,person[i].sex,person[i].job,person[i].category.banji);elseprintf(“%-6d%-10s%-3c%-3c%-6s\n”,person[i].num,person[i].name,person[i].sex,person[i].job,person[i].category.position);}}運(yùn)行情況如下:101Lifs501Wangmtprofessor

No.Namesexjobclass/position101Lifs501102Wangmtprofessor11.9枚舉類型枚舉:將變量的值一一列舉出來,變量的值只限于列舉出來的值的范圍內(nèi)。申明枚舉類型用enumenumweekday{sun,mon,tue,wed,thu,fri,sat};

定義變量:enumweekdayworkday,week-day;enum{sun,mon,tue,wed,thu,fri,sat}workday;變量值只能是sun到sat之一。枚舉元素枚舉常量11.9枚舉類型說明:在C編譯中,對(duì)枚舉元素按常量處理,故稱枚舉常量。它們不是變量,不能對(duì)它們賦值。(2)枚舉元素作為常量,它們是有值的,C語言編譯按定義時(shí)的順序使它們的值為0,1,2…

(3)枚舉值可以用來作判斷比較。(4)一個(gè)整數(shù)不能直接賦給一個(gè)枚舉變量。

11.9枚舉類型例11.13口袋中有紅、黃、藍(lán)、白、黑5種顏色的球若干個(gè)。每次從口袋中先后取出3個(gè)球,問得到3種不同色的球的可能取法,輸出每種排列的情況。

算法:圖11-2711-28

§13.9枚舉類型#include<stdio.h>main(){enumcolor{red,yellow,blue,white,black};enumcolori,j,k,pri;intn,loop;n=0;for(i=red;i<=black;i++) for(j=red;j<=black;j++) if(i!=j) {for(k=red;k<=black;k++) 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; }§13.9枚舉類型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);}運(yùn)行情況如下:1redyellowblue2redyellowwhite3redyellowblack58blackwhitered59blackwhiteyellow60blackwhitebluetotal:6011.10用typedef定義類型用typedef聲明新的類型名來代替已有的類型名。聲明INTEGER為整型typedefintINTEGER聲明結(jié)構(gòu)類型Typedefstruct{intmonth;intday;intyear;}DATE;

11.10用typedef定義類型聲明NUM為整型數(shù)組類型:typedefintNUM[100];

聲明STRING為字符指針類型:

typedefchar*STRING;

聲明POINTER為指向函數(shù)的指針類型,該函數(shù)返回整型值:typedefint(*POINTER)()

11.10用typedef定義類型用typedef定義類型的方法:

①先按定義變量的方法寫出定義體(如:inti)。②將變量名換成新類型名(例如:將i換成COUNT)。③在最前面加typedef

(例如:typedefintCOUNT)。④然后可以用新類型名去定義變量。

11.10用typedef定義類型用typedef定義類型的方法(舉例):①先按定義數(shù)組變量形式書寫:intn[100];②將變量名n換成自己指定的類型名:int

NUM[100];③在前面加上typedef,得到typedefintNUM[100];④用來定義變量:NUMn;11.10用typedef定義類型說明:用typedef可以聲明各種類型名,但不能用來定義變量。(2)用typedef只是對(duì)已經(jīng)存在的類型增加一個(gè)類型名,而沒有創(chuàng)造新的類型。(3)當(dāng)不同源文件中用到同一類型數(shù)據(jù)時(shí),常用typedef聲明一些數(shù)據(jù)類型,把它們單獨(dú)放在一個(gè)文件中,然后在需要用到它們的文件中用#include命令把它們包含進(jìn)來。(4)使用typedef有利于程序的通用與移植。11.10用typedef定義類型說明:(5)typedef與#define有相似之處,例如:typedefintCOUNT;#defineCOUNTint的作用都是用COUNT代表int。但事實(shí)上,它們二者是不同的。#define是在預(yù)編譯時(shí)處理的,它只能作簡(jiǎn)單的字符串替換,而typedef是在編譯時(shí)處理的。實(shí)際上它并不是作簡(jiǎn)單的字符串替換,而是采用如同定義變量的方法那樣來聲明一個(gè)類型。第十二章位運(yùn)算

主要內(nèi)容12.1位運(yùn)算符和位運(yùn)算12.2位運(yùn)算舉例12.3位段

概念

位運(yùn)算是指按二進(jìn)制位進(jìn)行的運(yùn)算。因?yàn)樵谙到y(tǒng)軟件中,常要處理二進(jìn)制位的問題。

例如:將一個(gè)存儲(chǔ)單元中的各二進(jìn)制位左移或右移一位,兩個(gè)數(shù)按位相加等。

C語言提供位運(yùn)算的功能,與其他高級(jí)語言(如PASCAL)相比,具有很大的優(yōu)越性。

12.1位運(yùn)算符和位運(yùn)算運(yùn)算符含義運(yùn)算符含義

&按位與~取反

|按位或

<<左移∧按位異或

>>右移(1)位運(yùn)算符中除~以外,均為二目(元)運(yùn)算符,即要求兩側(cè)各有一個(gè)運(yùn)算量。(2)運(yùn)算量只能是整型或字符型的數(shù)據(jù),不能為實(shí)型數(shù)據(jù)。C語言提供的位運(yùn)算符有:

說明:

12.1.1“按位與”運(yùn)算符(&)按位與是指:參加運(yùn)算的兩個(gè)數(shù)據(jù),按二進(jìn)制位進(jìn)行“與”運(yùn)算。如果兩個(gè)相應(yīng)的二進(jìn)制位都為1,則該位的結(jié)果值為1;否則為0。即:0&0=0,0&1=0,1&0=0,1&1=1例:3&5并不等于8,應(yīng)該是按位與運(yùn)算:注意:如果參加&運(yùn)算的是負(fù)數(shù)(如-3&-5),則要以補(bǔ)碼形式表示為二進(jìn)制數(shù),然后再按位進(jìn)行“與”運(yùn)算。

00000011(3)&

00000101(5)

00000001(1)

3&5的值得1按位與的用途:

若想對(duì)一個(gè)存儲(chǔ)單元清零,即使其全部二進(jìn)制位為0,只要找一個(gè)二進(jìn)制數(shù),其中各個(gè)位符合以下條件:原來的數(shù)中為1的位,新數(shù)中相應(yīng)位為0。然后使二者進(jìn)行&運(yùn)算,即可達(dá)到清零目的。(1)清零。

例:

原有數(shù)為00101011,另找一個(gè)數(shù),設(shè)它為10010100,這樣在原數(shù)為1的位置上,該數(shù)的相應(yīng)位值均為0。將這兩個(gè)數(shù)進(jìn)行&運(yùn)算:

00101011&

10010100

00000000

(2)取一個(gè)數(shù)中某些指定位。

如有一個(gè)整數(shù)a(2個(gè)字節(jié)),想要取其中的低字節(jié),只需將a與8個(gè)1按位與即可。0010110010101100abc00000000111111110000000010101100

(3)保留一位的方法:與一個(gè)數(shù)進(jìn)行&運(yùn)算,此數(shù)在該位?。?。即:a=84,b=59c=a&b=16例:有一數(shù)01010100,想把其中左面第3、4、5、7、8位保留下來,運(yùn)算如下:

01010100(84)&

00111011(59)

00010000(16)

12.1.2“按位或”運(yùn)算符(|)

兩個(gè)相應(yīng)的二進(jìn)制位中只要有一個(gè)為1,該位的結(jié)果值為1。即0|0=0,0|1=1,1|0=1,1|1=1例:

060|017,將八進(jìn)制數(shù)60與八進(jìn)制數(shù)17進(jìn)行按位或運(yùn)算。

00110000|

00001111

00111111

應(yīng)用:按位或運(yùn)算常用來對(duì)一個(gè)數(shù)據(jù)的某些位定值為1。例如:如果想使一個(gè)數(shù)a的低4位改為1,只需將a與017進(jìn)行按位或運(yùn)算即可。例:a是一個(gè)整數(shù)(16位),

有表達(dá)式:a|0377

則低8位全置為1,高8位保留原樣。12.1.3“異或”運(yùn)算符(∧)

異或運(yùn)算符∧也稱XOR運(yùn)算符。它的規(guī)則是:若參加運(yùn)算的兩個(gè)二進(jìn)制位同號(hào)則結(jié)果為0(假)

異號(hào)則結(jié)果為1(真)即:0∧0=0,0∧1=1,1∧0=1,1∧1=0即:071∧052=023(八進(jìn)制數(shù))

00111001∧

00101010

00010011

例:(1)使特定位翻轉(zhuǎn)

設(shè)有01111010,想使其低4位翻轉(zhuǎn),即1變?yōu)椋?,0變?yōu)椋???梢詫⑺c00001111進(jìn)行∧運(yùn)算,即:∧運(yùn)算符應(yīng)用:

01111010∧

00001111

01110101

運(yùn)算結(jié)果的低4位正好是原數(shù)低4位的翻轉(zhuǎn)。可見,要使哪幾位翻轉(zhuǎn)就將與其進(jìn)行∧運(yùn)算的該幾位置為1即可。因?yàn)樵瓟?shù)中的1與0進(jìn)行∧運(yùn)算得1,0∧0得0,故保留原數(shù)。例如:012∧00=012(2)與0相∧,保留原值

00001010∧

00000000

00001010(3)交換兩個(gè)值,不用臨時(shí)變量例如:a=3,b=4。想將a和b的值互換,可以用以下賦值語句實(shí)現(xiàn):a=a∧b;b=b∧a;a=a∧b;

a=011(∧)b=100

a=111(a∧b的結(jié)果,a已變成7)(∧)b=100

b=011(b∧a的結(jié)果,b已變成3)(∧)a=111

a=100(a∧b的結(jié)果,a已變成4)①

執(zhí)行前兩個(gè)賦值語句:“a=a∧b;”和“b=b∧a;”相當(dāng)于b=b∧(a∧b)。②

再執(zhí)行第三個(gè)賦值語句:a=a∧b。由于a的值等于(a∧b),b的值等于(b∧a∧b),因此,相當(dāng)于a=a∧b∧b∧a∧b,即a的值等于a∧a∧b∧b∧b,等于b。

a得到b原來的值。即等效于以下兩步:

12.1.4“取反”運(yùn)算符(~)

~是一個(gè)單目(元)運(yùn)算符,用來對(duì)一個(gè)二進(jìn)制數(shù)按位取反,即將0變1,將1變0。例如,~025是對(duì)八進(jìn)制數(shù)25(即二進(jìn)制數(shù)00010101)按位求反。0000000000010101(~)1111111111101010(八進(jìn)制數(shù)177752)

12.1.5左移運(yùn)算符(<<)

左移運(yùn)算符是用來將一個(gè)數(shù)的各二進(jìn)制位全部左移若干位。例如:a=<<2

將a的二進(jìn)制數(shù)左移2位,右補(bǔ)0。若a=15,即二進(jìn)制數(shù)00001111,左移2位得00111100,(十進(jìn)制數(shù)60)

高位左移后溢出,舍棄。

12.1.5左移運(yùn)算符(<<)

左移1位相當(dāng)于該數(shù)乘以2,左移2位相當(dāng)于該數(shù)乘以22=4,15<<2=60,即乘了4。但此結(jié)論只適用于該數(shù)左移時(shí)被溢出舍棄的高位中不包含1的情況。

假設(shè)以一個(gè)字節(jié)(8位)存一個(gè)整數(shù),若a為無符號(hào)整型變量,則a=64時(shí),左移一位時(shí)溢出的是0,而左移2位時(shí),溢出的高位中包含1。

12.1.6右移運(yùn)算符(>>)

右移運(yùn)算符是a>>2表示將a的各二進(jìn)制位右移2位,移到右端的低位被舍棄,對(duì)無符號(hào)數(shù),高位補(bǔ)0。例如:a=017時(shí):

a的值用二進(jìn)制形式表示為00001111,舍棄低2位11:a>>2=00000011右移一位相當(dāng)于除以2

右移n位相當(dāng)于除以2n。在右移時(shí),需要注意符號(hào)位問題:

對(duì)無符號(hào)數(shù),右移時(shí)左邊高位移入0;對(duì)于有符號(hào)的值,如果原來符號(hào)位為0(該數(shù)為正),則左邊也是移入0。如果符號(hào)位原來為1(即負(fù)數(shù)),則左邊移入0還是1,要取決于所用的計(jì)算機(jī)系統(tǒng)。有的系統(tǒng)移入0,有的系統(tǒng)移入1。移入0的稱為“邏輯右移”,即簡(jiǎn)單右移;移入1的稱為“算術(shù)右移”。例:

a的值是八進(jìn)制數(shù)113755:a:1001011111101101(用二進(jìn)制形式表示)a>>1:0100101111110110(邏輯右移時(shí))a>>1:1100101111110110(算術(shù)右移時(shí))

在有些系統(tǒng)中,a>>1得八進(jìn)制數(shù)045766,而在另一些系統(tǒng)上可能得到的是145766。TurboC和其他一些C編譯采用的是算術(shù)右移,即對(duì)有符號(hào)數(shù)右移時(shí),如果符號(hào)位原來為1,左面移入高位的是1。12.1.7位運(yùn)算賦值運(yùn)算符

位運(yùn)算符與賦值運(yùn)算符可以組成復(fù)合賦值運(yùn)算符。例如:&=,|=,>>=,<<=,∧=例:a&=b相當(dāng)于a=a&ba<<=2相當(dāng)于a=a<<2

12.1.8不同長(zhǎng)度的數(shù)據(jù)進(jìn)行位運(yùn)算

如果兩個(gè)數(shù)據(jù)長(zhǎng)度不同(例如long型和int型),進(jìn)行位運(yùn)算時(shí)(如a&b,而a為long型,b為int型),系統(tǒng)會(huì)將二者按右端對(duì)齊。如果b為正數(shù),則左側(cè)16位補(bǔ)滿0;若b為負(fù)數(shù),左端應(yīng)補(bǔ)滿1;如果b為無符號(hào)整數(shù)型,則左側(cè)添滿0。

12.2位運(yùn)算舉例例12.1取一個(gè)整數(shù)a從右端開始的4~7位①先使a右移4位:a>>4

目的是使要取出的那幾位移到最右端

未右移時(shí)的情況右移4位后的情況②設(shè)置一個(gè)低4位全為1,其余全為0的數(shù)。

~(~0<<4)③將上面①、②進(jìn)行&運(yùn)算。

(a>>4)&~(~0<<4)

程序如下:#include<stdio.h>voidmain()

{unsigneda,b,c,d;scanf(“%o”,&a);b=a>>4;c=~(~0<<4);d=b&c;printf(“%o,%d\n%o,%d\n”,a,a,d,d);運(yùn)行情況如下:331(輸入)331,217(a的值)15,13(d的值)輸入a的值為八進(jìn)制數(shù)331,其二進(jìn)制形式為11011001

經(jīng)運(yùn)算最后得到的d為00001101

即八進(jìn)制數(shù)15,十進(jìn)制數(shù)13。例12.2循環(huán)移位。要求將a進(jìn)行右循環(huán)移位將a右循環(huán)移n位,即將a中原來左面(16-n)位右移n位,原來右端n位移到最左面n位。①將a的右端n位先放到b中的高n位中,實(shí)現(xiàn)語句:b=a<<(16-n);②將a右移n位,其左面高位n位補(bǔ)0,實(shí)現(xiàn)語句:c=a>>n;③將c與b進(jìn)行按位或運(yùn)算,即c=c|b;步驟:程序如下:#include<stdio.h>voidmain()

{unsigneda,b,c;intn;scanf(“a=%o,n=%d”,&a,&n);b=a<<(16-n);c=a>>n;c=c|b;printf(“%o\n%o”,a,c);}運(yùn)行情況如下:a=157653,n=315765375765運(yùn)行開始時(shí)輸入八進(jìn)制數(shù)157653,即二進(jìn)制數(shù)1101111110101011循環(huán)右移3位后得二進(jìn)制數(shù)0111101111110101即八進(jìn)制數(shù)75765

12.3位段

信息的存取一般以字節(jié)為單位。實(shí)際上,有時(shí)存儲(chǔ)一個(gè)信息不必用一個(gè)或多個(gè)字節(jié),例如,“真”或“假”用0或1表示,只需1位即可。在計(jì)算機(jī)用于過程控制、參數(shù)檢測(cè)或數(shù)據(jù)通信領(lǐng)域時(shí),控制信息往往只占一個(gè)字節(jié)中的一個(gè)或幾個(gè)二進(jìn)制位,常常在一個(gè)字節(jié)中放幾個(gè)信息??梢匀藶榈貙⒁粋€(gè)整型變量data分為幾部分。

但是用這種方法給一個(gè)字節(jié)中某幾位賦值太麻煩。可以位段結(jié)構(gòu)體的方法。

怎樣向一個(gè)字節(jié)中的一個(gè)或幾個(gè)二進(jìn)制位賦值和改變它的值呢?可以用以下兩種方法:(2)位段C語言允許在一個(gè)結(jié)構(gòu)體中以位為單位來指定其成員所占內(nèi)存長(zhǎng)度,這種以位為單位的成員稱為“位段”或稱“位域”

(bitfield)。利用位段能夠用較少的位數(shù)存儲(chǔ)數(shù)據(jù)。程序如下:structpacked-data{unsigneda:2;unsignedb:6;unsignedc:4;unsignedd:4;inti;

}data;(1)位段成員的類型必須指定為unsigned或int類型。(2)若某一位段要從另一個(gè)字開始存放,可用以下形式定義:unsigneda:1;unsigned

b:2;一個(gè)存儲(chǔ)單元unsigned:0;unsignedc:3;另一存儲(chǔ)單元

a、b、c應(yīng)連續(xù)存放在一個(gè)存儲(chǔ)單元中,由于用了長(zhǎng)度為0的位段,其作用是使下一個(gè)位段從下一個(gè)存儲(chǔ)單元開始存放。因此,只將a、b存儲(chǔ)在一個(gè)存儲(chǔ)單元中,c另存在下一個(gè)單元(“存儲(chǔ)單元”可能是一個(gè)字節(jié),也可能是2個(gè)字節(jié),視不同的編譯系統(tǒng)而異)。

關(guān)于位段的定義和引用的說明:(3)一個(gè)位段必須存儲(chǔ)在同一存儲(chǔ)單元中,不能跨兩個(gè)單元。如果第一個(gè)單元空間不能容納下一個(gè)位段,則該空間不用,而從下一個(gè)單元起存放該位段。(4)可以定義無名位段。(5)位段的長(zhǎng)度不能大于存儲(chǔ)單元的長(zhǎng)度,也不能定義位段數(shù)組。(6)位段可以用整型格式符輸出。(7)位段可以在數(shù)值表達(dá)式中引用,它會(huì)被系統(tǒng)自動(dòng)地轉(zhuǎn)換成整型數(shù)。關(guān)于位段的定義和引用的說明:第十三章文件

本章要點(diǎn)

文件的基本概念文件的基本函數(shù)文件的順序讀寫文件的隨機(jī)讀寫文件簡(jiǎn)單應(yīng)用

主要內(nèi)容13.1C文件概述13.2文件類型指針13.3文件的打開與關(guān)閉13.4文件的讀寫13.5文件的定位13.6出錯(cuò)的檢測(cè)13.7文件輸入輸出小結(jié)13.1C文件概述文件:文件指存儲(chǔ)在外部介質(zhì)(如磁盤磁帶)上數(shù)據(jù)的集合。

操作系統(tǒng)是以文件為單位對(duì)數(shù)據(jù)進(jìn)行管理的。文件程序數(shù)據(jù)區(qū)輸出文件緩沖區(qū)輸入文件緩沖區(qū)13.1C文件概述(續(xù))文件的分類●從用戶觀點(diǎn):特殊文件(標(biāo)準(zhǔn)輸入輸出文件或標(biāo)準(zhǔn)設(shè)備文件)。普通文件(磁盤文件)?!駨牟僮飨到y(tǒng)的角度看,每一個(gè)與主機(jī)相連的輸入輸出設(shè)備看作是一個(gè)文件。例:輸入文件:終端鍵盤輸出文件:顯示屏和打印機(jī)文件的分類●按數(shù)據(jù)的組織形式:ASCII文件(文本文件):每一個(gè)字節(jié)放一個(gè)ASCII代碼二進(jìn)制文件:把內(nèi)存中的數(shù)據(jù)按其在內(nèi)存中的存儲(chǔ)形式原樣輸出到磁盤上存放。例:整數(shù)10000在內(nèi)存中的存儲(chǔ)形式以及分別按ASCII碼形式和二進(jìn)制形式輸出如下圖所示:13.1C文件概述(續(xù))13.1C文件概述(續(xù))文件的分類ASCII文件和二進(jìn)制文件的比較:ASCII文件便于對(duì)字符進(jìn)行逐個(gè)處理,也便于輸出字符。但一般占存儲(chǔ)空間較多,而且要花費(fèi)轉(zhuǎn)換時(shí)間。二進(jìn)制文件可以節(jié)省外存空間和轉(zhuǎn)換時(shí)間,但一個(gè)字節(jié)并不對(duì)應(yīng)一個(gè)字符,不能直接輸出字符形式。一般中間結(jié)果數(shù)據(jù)需要暫時(shí)保存在外存上,以后又需要輸入內(nèi)存的,常用二進(jìn)制文件保存。13.1C文件概述(續(xù))文件的分類C語言對(duì)文件的處理方法:緩沖文件系統(tǒng):系統(tǒng)自動(dòng)地在內(nèi)存區(qū)為每一個(gè)正在使用的文件開辟一個(gè)緩沖區(qū)。用緩沖文件系統(tǒng)進(jìn)行的輸入輸出又稱為高級(jí)磁盤輸入輸出。非緩沖文件系統(tǒng):系統(tǒng)不自動(dòng)開辟確定大小的緩沖區(qū),而由程序?yàn)槊總€(gè)文件設(shè)定緩沖區(qū)。用非緩沖文件系統(tǒng)進(jìn)行的輸入輸出又稱為低級(jí)輸入輸出系統(tǒng)。13.1C文件概述(續(xù))說明:在UNIX系統(tǒng)下,用緩沖文件系統(tǒng)來處理文本文件,用非緩沖文件系統(tǒng)來處理二進(jìn)制文件。ANSIC標(biāo)準(zhǔn)只采用緩沖文件系統(tǒng)來處理文本文件和二進(jìn)制文件。C語言中對(duì)文件的讀寫都是用庫函數(shù)來實(shí)現(xiàn)。13.2文件類型指針TurboC在stdio.h文件中有以下的文件類型聲明:typedefstruct{shortlevel;/*緩沖區(qū)“滿”或“空”的程度*/

unsignedflags;/*文件狀態(tài)標(biāo)志*/charfd;/*文件描述符*/unsignedcharhold;/*如無緩沖區(qū)不讀取字符*/shortbsize;/*緩沖區(qū)的大小*/unsignedchar*buffer;/*數(shù)據(jù)緩沖區(qū)的位置*/unsignedar*curp;/*指針,當(dāng)前的指向*/unsignedistemp;/*臨時(shí)文件,指示器*/shorttoken;/*用于有效性檢查*/}FILE;在緩沖文件系統(tǒng)中,每個(gè)被使用的文件都要在內(nèi)存中開辟一FILE類型的區(qū),存放文件的有關(guān)信息。13.2文件類型指針(續(xù))FILE類型的數(shù)組:FILE

f[5];定義了一個(gè)結(jié)構(gòu)體數(shù)組f,它有5個(gè)元素,可以用來存放5個(gè)文件的信息。文件型指針變量:FILE*fp;fp是一個(gè)指向FILE類型結(jié)構(gòu)體的指針變量??梢允筬p指向某一個(gè)文件的結(jié)構(gòu)體變量,從而通過該結(jié)構(gòu)體變量中的文件信息能夠訪問該文件。如果有n個(gè)文件,一般應(yīng)設(shè)n個(gè)指針變量,使它們分別指向n個(gè)文件,以實(shí)現(xiàn)對(duì)文件的訪問。13.3文件的打開與關(guān)閉一.文件的打開(fopen函數(shù))函數(shù)調(diào)用:FILE*fp;fp=fopen(文件名,使用文件方式);①需要打開的文件名,也就是準(zhǔn)備訪問的文件的名字;②使用文件的方式(“讀”還是“寫”等);③讓哪一個(gè)指針變量指向被打開的文件。

13.3文件的打開與關(guān)閉(續(xù))文件使用方式含義 “r”(只讀)為輸入打開一個(gè)文本文件“w”(只寫)為輸出打開一個(gè)文本文件“a”(追加)向文本文件尾增加數(shù)據(jù)“rb”(只讀)為輸入打開一個(gè)二進(jìn)制文件“wb”(只寫)為輸出打開一個(gè)二進(jìn)制文件"ab“(追加)向二進(jìn)制文件尾增加數(shù)據(jù)"r+“(讀寫)為讀/寫打開一個(gè)文本文件"w+”(讀寫)為讀/寫建立一個(gè)新的文本文件"a+”(讀寫)為讀/寫打開一個(gè)文本文件"rb+“(讀寫)為讀/寫打開一個(gè)二進(jìn)制文件“wb+“(讀寫)為讀/寫建立一個(gè)新的二進(jìn)制文件“ab+”(讀寫)為讀/寫打開一個(gè)二進(jìn)制文件13.3文件的打開與關(guān)閉(續(xù))二.文件的關(guān)閉(fclose函數(shù))函數(shù)調(diào)用:fclose(文件指針);函數(shù)功能:

使文件指針變量不指向該文件,也就是文件指針變量與文件“脫鉤”,此后不能再通過該指針對(duì)原來與其相聯(lián)系的文件進(jìn)行讀寫操作。返回值:關(guān)閉成功返回值為0;否則返回EOF(-1)

。13.4文件的讀寫一、字符輸入輸出函數(shù)(fputs()和fgets())fputs函數(shù)函數(shù)調(diào)用:fputs(ch,fp);函數(shù)功能:

將字符(ch的值)輸出到fp所指向的文件中去。返回值:如果輸出成功,則返回值就是輸出的字符;如果輸出失敗,則返回一個(gè)EOF。13.4文件的讀寫(續(xù))fgets函數(shù)函數(shù)調(diào)用:ch=fgets(fp);函數(shù)功能:

從指定的文件讀入一個(gè)字符,該文件必須是以讀或讀寫方式打開的。

返回值:讀取成功一個(gè)字符,賦給ch。如果遇到文件結(jié)束符,返回一個(gè)文件結(jié)束標(biāo)志EOF。13.4文件的讀寫(續(xù))常見的讀取字符操作從一個(gè)文本文件順序讀入字符并在屏幕上顯示出來:

ch=fgetc(fp);while(ch!=EOF)

{

putchar(ch);ch=fgetc(fp);}

注意:EOF不是可輸出字符,因此不能在屏幕上顯示。由于字符的ASCII碼不可能出現(xiàn)-1,因此EOF定義為-1是合適的。當(dāng)讀入的字符值等于-1時(shí),表示讀入的已不是正常的字符而是文件結(jié)束符。

13.4文件的讀寫(續(xù))常見的讀取字符操作從一個(gè)二進(jìn)制文件順序讀入字符:

while(!feof(fp))

{ch=fgetc(fp);}

注意:ANSIC提供一個(gè)feof()函數(shù)來判斷文件是否真的結(jié)束。如果是文件結(jié)束,函數(shù)feof(fp)的值為1(真);否則為0(假)。以上也適用于文本文件的讀取。

§13.4文件的讀寫(續(xù))fputc和fgetc函數(shù)使用舉例:例13.1從鍵盤輸入一些字符,逐個(gè)把它們送到磁盤上去,直到輸入一個(gè)“#”為止。

#include<stdlib.h>#include<stdio.h>voidmain(void){FILE*fp;charch,filename[10];scanf("%s",filename);if((fp=fopen(filename,"w"))==NULL){ printf("cannotopenfile\n"); exit(0);/*終止程序*/}ch=getchar();/*接收?qǐng)?zhí)行scanf語句時(shí)最后輸入的回車符*/

ch=getchar();/*接收輸入的第一個(gè)字符*/

while(ch!='#'{fputc(ch,fp);putchar(ch); ch=getchar();}fclose(fp);}運(yùn)行情況如下:file1.c(輸入磁盤文件名)computerandc#(輸入一個(gè)字符串)computerandc(輸出一個(gè)字符串)

§13.4文件的讀寫(續(xù))fputc和fgetc函數(shù)使用舉例:例13.2將一個(gè)磁盤文件中的信息復(fù)制到另一個(gè)磁盤文件中

。

#include<stdlib.h>#include<stdio.h>main(){FILE*in,*out;charch,infile[10],outfile[10];printf("Entertheinfilename:\n");scanf("%s",infile);printf("Entertheoutfilename:\n");scanf("%s",outfile);if((in=fopen(infile,"r"))==NULL){ printf("cannotopeninfile\n");exit(0);} if((out=fopen(outfile,"w"))==NULL){ printf("cannotopenoutfile\n");exit(0);} while(!feof(in))fputc(fgetc(in),out);fclose(in);fclose(out);}運(yùn)行情況如下:Entertheinfilenamefile1.c(輸入原有磁盤文件名Entertheoutfilename:file2.c(輸入新復(fù)制的磁盤文件名)程序運(yùn)行結(jié)果是將file1.c文件中的內(nèi)容復(fù)制到file2.c中去。

§13.4文件的讀寫(續(xù))fputc和fgetc函數(shù)使用舉例:例13.2的改進(jìn):復(fù)制一個(gè)二進(jìn)制文件,利用main參數(shù),在輸入命令行是將兩個(gè)文件名輸入。

#include<stdlib.h>#include<stdio.h>main(int

argc,char*argv[

]){FILE*in,*out;charch;if(argc!=3){ printf("Youforgottoenterafilename\n"); exit(0);} if((in=fopen(argv[1],"rb"))==NULL) { printf("cannotopeninfile\n"); exit(0);}if((out=fopen(argv[2],"wb"))==NULL) { printf("cannotopenoutfile\n"); exit(0);} while(!feof(in))fputc(fgetc(in),out);fclose(in);fclose(out);}運(yùn)行方法:設(shè)經(jīng)編譯連接后得到的可執(zhí)行文件名為a.exe,則在DOS命令工作方式下,可以輸入以下的命令行:C>afile1.cfile2.cfile1.c和file2.c,分別輸入到argv[1]和argv[2]中,argv[0]的內(nèi)容為a,argc的值等于3。13.4文件的讀寫(續(xù))二、數(shù)據(jù)塊讀寫函數(shù)(fread()和fwrite())函數(shù)調(diào)用:fread(buffer,size,count,fp);fwrite(buffer,size,count,fp);參數(shù)說明:buffer:是一個(gè)指針。對(duì)fread來說,它是讀入數(shù)據(jù)的存放地址。對(duì)fwrite來說,是要輸出數(shù)據(jù)的地址(均指起始地址)。size:要讀寫的字節(jié)數(shù)。count:要進(jìn)行讀寫多少個(gè)size字節(jié)的數(shù)據(jù)項(xiàng)。fp:文件型指針。13.4文件的讀寫(續(xù))

使用舉例:

若文件以二進(jìn)制形式打開:

fread(f,4,2,fp);

此函數(shù)從fp所指向的文件中讀入2個(gè)4個(gè)字節(jié)的數(shù)

據(jù),存儲(chǔ)到數(shù)組f中。13.4文件的讀寫(續(xù))使用舉例:若有如下結(jié)構(gòu)類型:structstudent_type{charname[10];intnum;intage;charaddr[30];}stud[40];可以用fread和fwrite來進(jìn)行數(shù)據(jù)的操作:for(i=0;i<40;i++)fread(&stud[i],sizeof(structstudent-type),1,fp);

for(i=0;i<40,i++)fwrite(&stud[i],sizeof(structstudent-type),1,fp);

13.4文件的讀寫(續(xù))使用舉例:例13.3從鍵盤輸入4個(gè)學(xué)生的有關(guān)數(shù)據(jù),然后把它們轉(zhuǎn)存到磁盤文件上去。

#include<stdio.h>#defineSIZE4structstudent_type{ charname[10];intnum;intage;charaddr[15];}stud[SIZE];/*定義結(jié)構(gòu)*/§13.4文件的讀寫(續(xù))voidsave(){FILE*fp;inti;if((fp=fopen("stu-list","wb"))==NULL){printf("cannotopenfile\n");return;}for(i=0;i<SIZE;i++)/*二進(jìn)制寫*/if(fwrite(&stud[i],sizeof(structstudent_type),1,fp)!=1)printf(“filewriteerror\n”);/*出錯(cuò)處理*/fclose(fp);}/*關(guān)閉文件*/

main(){inti;for(i=0;i<SIZE;i++)/*從鍵盤讀入學(xué)生信息*/scanf("%s%d%d%s",stud[i].name,&stud[i].num,&stud[i].age,stud[i].addr);save();}/*調(diào)用save()保存學(xué)生信息*/運(yùn)行情況如下:輸入4個(gè)學(xué)生的姓名、學(xué)號(hào)、年齡和地址:Zhang100119room-101Fun100220room-102Tan100321room-103Ling100421room-104

驗(yàn)證在磁盤文件“stu-list”中是否已存在此數(shù)據(jù),用以下程序從“stu-list”文件中讀入數(shù)據(jù),然后在屏幕上輸出。

§13.4文件的讀寫(續(xù))#include<stdio.h>#defineSIZE4structstudent_type{ charname[10];intnum;intage;charaddr[15];}stud[SIZE];main(){ inti; FILE*fp; fp=fopen("stu-list","rb"); for(i=0;i<SIZE;i++){fread(&stud[i],sizeof(structstudent_type),1,fp);printf("%\-10s%4d%4d%\-15s\n",stud[i].name,stud[i].num,stud[i].age,stud[i].addr);}fclose(fp);}屏幕上顯示出以下信息:Zhang100119room-101Fun100220room-102Tan100321room-103Ling100421room-104

如果已有的數(shù)據(jù)已經(jīng)以二進(jìn)制形式存儲(chǔ)在一個(gè)磁盤文件“stu-dat”中,要求從其中讀入數(shù)據(jù)并輸出到“stu-list”文件中,可以編寫一個(gè)load函數(shù),從磁盤文件中讀二進(jìn)制數(shù)據(jù)。13.4文件的讀寫(續(xù))voidload(){FILE*fp;inti;if((fp=fopen("stu-dat","rb"))==NULL){ printf("cannotopeninfile\n");return;}for(i=0;i<SIZE;i++)if(fread(&stud[i],sizeof(structstudent_type),1,fp)!=1){if(feof(fp)){fclose(fp);return;}printf("filereaderror\n");}fclose(fp);}

13.4文件的讀寫(續(xù))三、格式化讀寫函數(shù)(fprintf()和fscanf())函數(shù)調(diào)用:fprintf(文件指針,格式字符串,輸出表列);fscanf(文件指針,格式字符串,輸入表列);

函數(shù)功能:

從磁盤文件中讀入或輸出字符。例:fprintf(fp,”%d,%6.2f”,i,t);Fscanf(fp,”%d,%f”,&i,&t);注意:用fprintf和fscanf函數(shù)對(duì)磁盤文件讀寫,使用方便,容易理解,但由于在輸入時(shí)要將ASCII碼轉(zhuǎn)換為二進(jìn)制形式,在輸出時(shí)又要將二進(jìn)制形式轉(zhuǎn)換成字符,花費(fèi)時(shí)間比較多。因此,在內(nèi)存與磁盤頻繁交換數(shù)據(jù)的情況下,最好不用fprintf和fscanf函數(shù),而用fread和fwrite函數(shù)。13.4文件的讀寫(續(xù))三、其他讀寫函數(shù)putw()和getw()函數(shù)調(diào)用:putw(inti,FILE*fp);inti=getw(FILE*fp);

函數(shù)功能:

對(duì)磁盤文件中讀寫一個(gè)字(整數(shù))。例:putw(10,fp);i=getw(fp);putw函數(shù)定義如下:putw(intI,FILE*fp){chars;s=&I;putc(s[0],fp);putc(s[1],fp);returni;}gutw函數(shù)定義如下:gutw(FILE*fp){chars;s=char*&i;s[0]=getc(fp);s[1]=getc(fp);returni;}13.4文件的讀寫(續(xù))用戶自定義讀取其他類型數(shù)據(jù)的函數(shù)。向磁盤文件寫一個(gè)實(shí)數(shù)(用二進(jìn)制方式)的函數(shù)putfloat:putfloat(floatnum,FILE*fp){ chars; intcount; s=(char*)# for(count=0;count<4;count++) putc(s[count],fp);}13.4文件的讀寫(續(xù))fgets函數(shù)函數(shù)作用:從指定文件讀入一個(gè)字符串。函數(shù)調(diào)用:fgets(str,n,fp);從fp指向的文件輸入n-1個(gè)字符,在最后加一個(gè)’\0’。返回值:str的首地址。13.4文件的讀寫(續(xù))fputs函數(shù)函數(shù)作用:向指定的文件輸出一個(gè)字符串。函數(shù)調(diào)用:fgets(“china”,fp);第一個(gè)參數(shù)可以是字符串常量、字符數(shù)組名或字符型指針。字符串末尾的′\0′不輸出。

返回值:輸入成功,返回值為0;輸入失敗,返回EOF。13.5文件的定位rewind函數(shù)函數(shù)作用:使位置指針重新返回文件的開頭,無返回值。應(yīng)用舉例:例13.4有一個(gè)磁盤文件,第一次將它的內(nèi)容顯示在屏幕上,第二次把它復(fù)制到另一文件上。

#include<stdio.h>main(){ FILE*fp1,*fp2; fp1=fopen("file1.c","r"); fp2=fopen("file2.c","w");while(!feof(fp1))putchar(getc(fp1));

rewind(fp1); while(!feof(fp1))putc(getc(fp1),fp2);fclose(fp1);fclose(fp2);}13.5文件的定位順序讀寫和隨機(jī)讀寫順序讀寫:位置指針按字節(jié)位置順序移動(dòng)。隨機(jī)讀寫:讀寫完上一個(gè)字符(字節(jié))后,并不一定要讀寫其后續(xù)的字符(字節(jié)),而可以讀些文件中任意位置上所需要的字符(字節(jié))。

13.5文件的定位fseek函數(shù)(一般用于二進(jìn)制文件)函數(shù)功能:改變文件的位置指針。函數(shù)調(diào)用形式:fseek(文件類型指針,位移量,起始點(diǎn))起始點(diǎn):文件開頭SEEK_SET0

文件當(dāng)前位置SEEK_CUR1

文件末尾SEEK_END2位移量:以起始點(diǎn)為基點(diǎn),向前移動(dòng)的字節(jié)數(shù)。一般要求為long型。

13.5文件的定位fseek函數(shù)應(yīng)用舉例fseek(fp,100L,0);將位置指針移到離文件頭100個(gè)字節(jié)處。fseek(fp,50L,1);將位置指針移到離當(dāng)前位置50個(gè)字節(jié)處。fseek(fp,50L,2);將位置指針從文件末尾處向后退10個(gè)字節(jié)。

§13.5文件的定位例13.5在磁盤文件上存有10個(gè)學(xué)生的數(shù)據(jù)。要求將第1、3、5、7、9個(gè)學(xué)生數(shù)據(jù)輸入計(jì)算機(jī),并在屏幕上顯示出來。

#include<stdlib.h>#include<stdio.h>structstudent_type{charname[10];intnum;intage;charsex;}stud[10];main(){inti;FILE*fp;if((fp=fopen("stud-dat","rb"))==NULL){printf("cannotopenfile\n");exit(0);}for(i=0;i<10;i+=2){fseek(fp,i*sizeof(structstudent_type),0);fread(&stud[i],sizeof(structstudent_type),1,fp);printf(“%s%d%d%c\n”,stud[i].name,stud[i].num,stud[i].age,stud[i].sex);}fclose(fp)}13.5文件的定位ftell函數(shù)函數(shù)作用:得到流式文件中的當(dāng)前位置,用相對(duì)于文件開頭的位移量來表示。返回值:返回當(dāng)前位置,出錯(cuò)時(shí)返回-1L。應(yīng)用舉例:i=ftell(fp);if(i==-1L)printf(“error\n”);

13.6出錯(cuò)的檢測(cè)ferror函數(shù)調(diào)

溫馨提示

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

最新文檔

評(píng)論

0/150

提交評(píng)論