高級(jí)語(yǔ)言程序設(shè)計(jì)(C語(yǔ)言版 第2版)-基于計(jì)算思維能 課件 第8-10章-結(jié)構(gòu)體及其應(yīng)用、文件及其應(yīng)用、C綜合性程序設(shè)計(jì)案例分析_第1頁(yè)
高級(jí)語(yǔ)言程序設(shè)計(jì)(C語(yǔ)言版 第2版)-基于計(jì)算思維能 課件 第8-10章-結(jié)構(gòu)體及其應(yīng)用、文件及其應(yīng)用、C綜合性程序設(shè)計(jì)案例分析_第2頁(yè)
高級(jí)語(yǔ)言程序設(shè)計(jì)(C語(yǔ)言版 第2版)-基于計(jì)算思維能 課件 第8-10章-結(jié)構(gòu)體及其應(yīng)用、文件及其應(yīng)用、C綜合性程序設(shè)計(jì)案例分析_第3頁(yè)
高級(jí)語(yǔ)言程序設(shè)計(jì)(C語(yǔ)言版 第2版)-基于計(jì)算思維能 課件 第8-10章-結(jié)構(gòu)體及其應(yīng)用、文件及其應(yīng)用、C綜合性程序設(shè)計(jì)案例分析_第4頁(yè)
高級(jí)語(yǔ)言程序設(shè)計(jì)(C語(yǔ)言版 第2版)-基于計(jì)算思維能 課件 第8-10章-結(jié)構(gòu)體及其應(yīng)用、文件及其應(yīng)用、C綜合性程序設(shè)計(jì)案例分析_第5頁(yè)
已閱讀5頁(yè),還剩269頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

高級(jí)語(yǔ)言程序設(shè)計(jì)高級(jí)語(yǔ)言程序設(shè)計(jì)——基于計(jì)算思維能力培養(yǎng)高級(jí)語(yǔ)言程序設(shè)計(jì)——基于計(jì)算思維能力培養(yǎng)第8章結(jié)構(gòu)體及其應(yīng)用主要內(nèi)容結(jié)構(gòu)體類(lèi)型與結(jié)構(gòu)體變量指針結(jié)構(gòu)體的指針向函數(shù)傳遞結(jié)構(gòu)體結(jié)構(gòu)體數(shù)組動(dòng)態(tài)數(shù)據(jù)結(jié)構(gòu)——單鏈表本章思維導(dǎo)圖為何要用結(jié)構(gòu)體8.18.1為何要用結(jié)構(gòu)體C語(yǔ)言中學(xué)習(xí)的基本數(shù)據(jù)類(lèi)型都不能獨(dú)立地來(lái)表示這些對(duì)象的全部屬性。結(jié)構(gòu)體類(lèi)型與

結(jié)構(gòu)體變量8.28.2.1結(jié)構(gòu)體類(lèi)型的聲明結(jié)構(gòu)體類(lèi)型定義的一般格式為: struct結(jié)構(gòu)體類(lèi)型名 {

數(shù)據(jù)類(lèi)型

屬性1;

數(shù)據(jù)類(lèi)型

屬性2; …

數(shù)據(jù)類(lèi)型

屬性n;};例如,structstudent{ charid[13]; //學(xué)號(hào) charname[9]; //姓名 intage; //年齡 charsex; //性別 charsfzh[19]; //身份證號(hào) charaddress[61]; //家庭住址 chartelNumber[12]; //電話號(hào)碼 charclassName[21]; //班級(jí)名稱};structdate{intyear;intmonth;intday;};結(jié)構(gòu)體類(lèi)型的定義可以嵌套,即可以利用一個(gè)已定義的結(jié)構(gòu)體類(lèi)型作為別外一個(gè)結(jié)構(gòu)體類(lèi)型的屬性。structstudent{ charid[13]; //學(xué)號(hào) charname[9]; //姓名

structdatebirthday; //生日 charsex; //性別 charsfzh[19]; //身份證號(hào) charaddress[61]; //家庭住址 chartelNumber[12]; //電話號(hào)碼 charclassName[21]; //班級(jí)名稱};8.2.2結(jié)構(gòu)體變量的定義1、結(jié)構(gòu)體變量定義的格式我們可以利用之前已定義好的structstudent結(jié)構(gòu)體類(lèi)型來(lái)聲明學(xué)生結(jié)構(gòu)體變量。structstudents1,s2;注意:結(jié)構(gòu)體類(lèi)型的完整名稱為structstudent。為方便書(shū)寫(xiě),我們可以用類(lèi)型定義符typedef將structstudent命名為一個(gè)新的名稱。如:typedefstructstudentstuStru;//將structstudent命名為stuStru之后,便可在程序中使用stuStru等價(jià)地表示structstudent。例如:stuStrus1,s2;定義了兩個(gè)學(xué)生結(jié)構(gòu)體變量s1和s2。2、結(jié)構(gòu)體變量占用的字節(jié)數(shù)結(jié)構(gòu)體中的成員按定義順序占用連續(xù)的存儲(chǔ)空間。每個(gè)結(jié)構(gòu)體變量占用的字節(jié)數(shù)至少需等于所有成員(屬性)占用的內(nèi)存之和。我們可以用sizeof運(yùn)算符來(lái)獲得結(jié)構(gòu)體變量占用的字節(jié)數(shù)。 sizeof(stuStru);

或 sizeof(s1);8.2.3對(duì)結(jié)構(gòu)體變量的操作對(duì)結(jié)構(gòu)體變量的操作應(yīng)以其屬性為基本單位,具體格式如下:

結(jié)構(gòu)體變量名.成員名

其中“.”運(yùn)算符為成員運(yùn)算符。例如: stuStrus1,s2;

則s1.id表示s1的學(xué)號(hào),表示s1的姓名等。注意事項(xiàng):(1)在訪問(wèn)結(jié)構(gòu)體變量的成員時(shí),要根據(jù)結(jié)構(gòu)體變量的成員類(lèi)型來(lái)進(jìn)行相應(yīng)的操作。例如:strcpy(s1.id,"201400120001");

可將"201400120001"存入s1的學(xué)號(hào)。注意:s1.id="201400120001"是錯(cuò)誤的。注意事項(xiàng):(2)對(duì)于嵌套的結(jié)構(gòu)體變量,應(yīng)該逐級(jí)訪問(wèn)其成員,直至非結(jié)構(gòu)體成員。如:s1.birthday.year=1996;s1.birthday.month=10;s1.birthday.day=20;完成將s1的生日設(shè)置為1996年10月20日。注意事項(xiàng):(3)不能將結(jié)構(gòu)體變量作為一個(gè)整體進(jìn)行輸入輸出,只能對(duì)變量中的各個(gè)成員輸入輸出。例如:gets(); //輸入s1的姓名printf("%s",); //輸出s1的姓名scanf("%d",&s1.birthday.year);//輸入s1的出生年份printf("%d",s1.birthday.year);//輸出s1的出生年份注意事項(xiàng):(4)兩個(gè)同類(lèi)型的結(jié)構(gòu)體變量可以直接賦值,賦值號(hào)右邊結(jié)構(gòu)體變量的成員將依次賦值給左邊結(jié)構(gòu)體變量的各個(gè)成員。例如:s2=s1;將使s2與s1具有相同的屬性值。8.2.4結(jié)構(gòu)體變量的初始化結(jié)構(gòu)體變量可以在聲明時(shí)進(jìn)行初始化,變量后面的一組數(shù)據(jù)用“{}”括起來(lái),其順序應(yīng)該與結(jié)構(gòu)體中的成員(屬性)順序保持一致,且對(duì)應(yīng)的類(lèi)型應(yīng)賦值相容。例如: stuStrus1={"201400120001","李明",{1996,10,20},'M',"36010119961020****","南昌市東湖區(qū)","","物聯(lián)網(wǎng)1班"};【例8.1】結(jié)構(gòu)體類(lèi)型定義及結(jié)構(gòu)體變量的定義與初始化示例。#include<stdio.h>structdate{ intyear; intmonth; intday;};【例8.1】結(jié)構(gòu)體類(lèi)型定義及結(jié)構(gòu)體變量的定義與初始化示例。structstudent{ charid[13]; //學(xué)號(hào) charname[9]; //姓名

structdatebirthday; //生日 charsex; //性別 charsfzh[19]; //身份證號(hào) charaddress[61]; //家庭住址 chartelNumber[12]; //電話號(hào)碼 charclassName[21]; //班級(jí)名稱};typedefstructstudentstuStru;intmain(){stuStrus1={"201400120001","李明",{1996,10,20},'M',"36010119961020****","南昌市東湖區(qū)","","物聯(lián)網(wǎng)1班"};stuStrus2;

s2=s1; //結(jié)構(gòu)體變量賦值printf("學(xué)

號(hào):%s\n",s2.id);printf("姓

名:%s\n",);printf("出生日期:%d-%d-%d\n",s2.birthday.year,s2.birthday.month,s2.birthday.day);printf("性

別:%s\n",s2.sex=='M'?"男":"女");printf("身份證號(hào):%s\n",s2.sfzh);printf("家庭住址:%s\n",s2.address);printf("電話號(hào)碼:%s\n",s2.telNumber);printf("班級(jí)名稱:%s\n",s2.className);return0;}學(xué)號(hào):201400120001姓名:李明出生日期:1996-10-20性別:男身份證號(hào):36010119961020****家庭住址:南昌市東湖區(qū)電話號(hào)碼:班級(jí)名稱:物聯(lián)網(wǎng)1班程序運(yùn)行情況如下:指向結(jié)構(gòu)體的指針8.38.3指向結(jié)構(gòu)體的指針結(jié)構(gòu)體指針變量的定義格式如下:結(jié)構(gòu)體類(lèi)型名*指針變量名;例如,對(duì)例8.1定義的結(jié)構(gòu)體類(lèi)型stuStru,可以定義結(jié)構(gòu)體變量和指針變量: stuStrus,*p; p=&s;將使指針p保存s的首地址。當(dāng)結(jié)構(gòu)體指針指向某結(jié)構(gòu)體變量后,借助指針有兩種方式來(lái)訪問(wèn)該指針指向的對(duì)象屬性。(1)通過(guò)“(*指針).屬性名”來(lái)訪問(wèn)指針指向的對(duì)象的屬性。例如,若p為指向結(jié)構(gòu)體變量s的指針,則:scanf("%d",&(*p).birthday.year);printf("%s",(*p).name);分別完成p指向?qū)ο蟮某錾攴莸妮斎牒托彰妮敵?。?)通過(guò)“指針->屬性名”來(lái)訪問(wèn)指針指向的對(duì)象的屬性(->運(yùn)算符由減號(hào)-和大于號(hào)>組合而成)。當(dāng)p為指向結(jié)構(gòu)體變量s的指針時(shí)p->birthday.year可引用s的出生年份即s.birthday.year;p->name可引用。特別地,當(dāng)p為結(jié)構(gòu)體類(lèi)型的指針時(shí),可以通過(guò)malloc函數(shù)來(lái)為p動(dòng)態(tài)分配結(jié)構(gòu)體空間,如: stuStru*p; p=(stuStru*)malloc(sizeof(stuStru));當(dāng)p指向的動(dòng)態(tài)結(jié)構(gòu)體使用完成后,應(yīng)采用free(p);語(yǔ)句來(lái)將該空間釋放。向函數(shù)傳遞結(jié)構(gòu)體8.48.4.1值傳遞傳值調(diào)用為單向值傳遞,函數(shù)調(diào)用發(fā)生時(shí),系統(tǒng)將結(jié)構(gòu)體變量的值拷貝一份給形式參數(shù),在函數(shù)中所有的操作都是針對(duì)形式參數(shù)進(jìn)行的,實(shí)際參數(shù)的值不會(huì)因形參值的改變而改變。#include<stdio.h>structdate{ intyear; intmonth; intday;};【例8.2】結(jié)構(gòu)體變量傳值調(diào)用示例。voidfun(structdated){d.year=2008;d.month=8;d.day=8;}intmain(){structdated={2014,9,1};printf("%d-%d-%d\n",d.year,d.month,d.day);fun(d); //傳值調(diào)用printf("%d-%d-%d\n",d.year,d.month,d.day);return0;}2014-9-12014-9-18.4.2地址傳遞當(dāng)函數(shù)的形參為指向結(jié)構(gòu)體變量的指針類(lèi)型時(shí),可以將結(jié)構(gòu)體變量的地址作為函數(shù)的實(shí)參,完成結(jié)構(gòu)體變量的按地址調(diào)用?!纠?.3】結(jié)構(gòu)體變量傳地址調(diào)用示例。#include<stdio.h>structdate{ intyear; intmonth; intday;};voidfun(structdate*p){

p->year=2008;p->month=8;

p->day=8;}intmain(){structdated={2014,9,1};printf("%d-%d-%d\n",d.year,d.month,d.day);fun(&d); //傳地址調(diào)用printf("%d-%d-%d\n",d.year,d.month,d.day);return0;}2014-9-12008-8-8如果結(jié)構(gòu)體變量只想被函數(shù)引用,而不想被其修改,可以用const修辭函數(shù)的形參聲明。如:voidfun(conststructdate*p)

則在程序中只能訪問(wèn)p指向的結(jié)構(gòu)體變量,而不能對(duì)它進(jìn)行修改。結(jié)構(gòu)體數(shù)組8.58.5結(jié)構(gòu)體數(shù)組序號(hào)班級(jí)名稱姓名學(xué)號(hào)022級(jí)網(wǎng)絡(luò)工程聶加望2208066047122級(jí)網(wǎng)絡(luò)工程潘杰2208066048222級(jí)網(wǎng)絡(luò)工程秦彪2208066049322級(jí)網(wǎng)絡(luò)工程邱強(qiáng)2208066051422級(jí)網(wǎng)絡(luò)工程唐重喜22080660548.5結(jié)構(gòu)體數(shù)組8.5.1結(jié)構(gòu)體數(shù)組的定義最常用的結(jié)構(gòu)體一維數(shù)組的定義格式如下:結(jié)構(gòu)體類(lèi)型

數(shù)組名[數(shù)組大小];例如,假設(shè)stuStru是已定義好的學(xué)生結(jié)構(gòu)體類(lèi)型,則下面的語(yǔ)句定義了大小為10的學(xué)生結(jié)構(gòu)體數(shù)組s。stuStrus[10];訪問(wèn)結(jié)構(gòu)體數(shù)組的方法與普通數(shù)組類(lèi)似,通過(guò)下標(biāo)來(lái)引用數(shù)組元素。例如: printf("%s",s[2].id);當(dāng)然,我們也可以用動(dòng)態(tài)內(nèi)存分配的方法,來(lái)獲得動(dòng)態(tài)結(jié)構(gòu)體數(shù)組。例如: stuStru*s; s=(stuStru*)malloc(10*sizeof(stuStru));8.5.2結(jié)構(gòu)體數(shù)組的初始化與引用1、結(jié)構(gòu)體數(shù)組的初始化結(jié)構(gòu)體數(shù)組在定義的同時(shí),可以進(jìn)行初始化,初始化結(jié)構(gòu)體數(shù)組的規(guī)則與初始化普通數(shù)組具有類(lèi)似的規(guī)則。8.5.2結(jié)構(gòu)體數(shù)組的初始化與引用1、結(jié)構(gòu)體數(shù)組的初始化結(jié)構(gòu)體數(shù)組的初始化列表包括在一對(duì)“{}”內(nèi),在其內(nèi)部每個(gè)元素的成員初始化列表用“{}”括起來(lái)。若只對(duì)部分元素初始化,則其它元素將被自動(dòng)初始化為0。當(dāng)省略數(shù)組大小時(shí),系統(tǒng)會(huì)根據(jù)初始化列表的項(xiàng)數(shù)來(lái)自動(dòng)確定數(shù)組大小?!纠?.4】結(jié)構(gòu)體數(shù)組的初始化與引用示例。#include<stdio.h>#defineN5structbook{charid[6]; //圖書(shū)編號(hào)charname[31]; //書(shū)名floatprice; //單價(jià)charauthor[13]; //作者};typedefstructbookbookStru;intmain(){bookStrub[N]={{"10001","C語(yǔ)言程序設(shè)計(jì)現(xiàn)代方法",79,"K.N.King"},{"10002","CPrimerPlus(第五版)",60,"StephenPrata"},{"10003","C語(yǔ)言程序設(shè)計(jì)",43,"蘇小紅等"},{"10004","程序設(shè)計(jì)基礎(chǔ)(第3版)",35,"吳文虎"}};inti;printf("編號(hào)

圖書(shū)名稱

單價(jià)

作者\(yùn)n");for(i=0;i<N;i++){ printf("%-8s",b[i].id); //輸出圖書(shū)編號(hào) printf("%-30s",b[i].name); //輸出書(shū)名 printf("%-8.2f",b[i].price); //輸出單價(jià) printf("%-12s\n",b[i].author); //輸出作者}return0;}2、利用指針訪問(wèn)結(jié)構(gòu)體數(shù)組當(dāng)結(jié)構(gòu)體指針指向結(jié)構(gòu)體數(shù)組時(shí),可以通過(guò)結(jié)構(gòu)體指針來(lái)訪問(wèn)數(shù)組各元素,對(duì)結(jié)構(gòu)體指針執(zhí)行算術(shù)運(yùn)算是以結(jié)構(gòu)體變量占用的字節(jié)數(shù)為基本單位的?!纠?.5】指針訪問(wèn)結(jié)構(gòu)體數(shù)組示例#include<stdio.h>#defineN100structbook{charid[6]; //圖書(shū)編號(hào)charname[31]; //書(shū)名floatprice; //單價(jià)charauthor[13]; //作者};typedefstructbookbookStru;intmain(){bookStrub[N],*p;intn;p=b;printf("請(qǐng)輸入圖書(shū)數(shù)量:");scanf("%d",&n);if(n<N){printf("請(qǐng)按以下格式輸入%d本圖書(shū)信息(用Tab鍵分隔):\n",n);printf("編號(hào)

圖書(shū)名稱

單價(jià)

作者\(yùn)n");while(p<b+n){scanf("%s",p->id); //輸入圖書(shū)編號(hào)scanf("%s",p->name); //輸入圖書(shū)名稱scanf("%f",&p->price); //輸入圖書(shū)單價(jià)scanf("%s",p->author); //輸入圖書(shū)作者p++;}

printf("編號(hào)

圖書(shū)名稱

單價(jià)

作者\(yùn)n");printf("----------------------------------------------------\n");for(p=b;p<b+n;p++){printf("%-8s",p->id); printf("%-30s",(*p).name);printf("%-8.2f",(*p).price);printf("%-12s\n",p->author);}}return0;}請(qǐng)輸入圖書(shū)數(shù)量:3↙請(qǐng)按以下格式輸入3本圖書(shū)信息(用Tab鍵分隔):編號(hào)圖書(shū)名稱

單價(jià)作者10001C語(yǔ)言程序設(shè)計(jì)現(xiàn)代方法79.00K.N.King↙10002CPrimerPlus(第五版)

60.00StephenPrata↙10003C語(yǔ)言程序設(shè)計(jì)

43.00蘇小紅等↙編號(hào)圖書(shū)名稱

單價(jià)作者------------------------------------------------------------------------10001C語(yǔ)言程序設(shè)計(jì)現(xiàn)代方法79.00K.N.King10002CPrimerPlus(第五版)60.00StephenPrata10003C語(yǔ)言程序設(shè)計(jì)43.00蘇小紅等8.5.3結(jié)構(gòu)體數(shù)組的應(yīng)用準(zhǔn)考證號(hào)姓名語(yǔ)文數(shù)學(xué)英語(yǔ)綜合總分110100101張三120123110265

110100102李四96102130242

【例8.5】試編寫(xiě)程序,定義用于存儲(chǔ)學(xué)生信息的結(jié)構(gòu)體數(shù)組,輸入學(xué)生的準(zhǔn)考證號(hào)、姓名和成績(jī)信息,計(jì)算每位學(xué)生的總分,并按總分由高到低輸出學(xué)生信息表。成績(jī)統(tǒng)計(jì)輸入求和排序輸出#include<stdio.h>#defineN10000structstudent{charid[10]; //準(zhǔn)考證號(hào)charname[9]; //姓名floatscore[4]; //大小為4的數(shù)組,分別存儲(chǔ)4門(mén)課程分?jǐn)?shù)floattotal; //總分};typedefstructstudentstuStru;/*@函數(shù)名稱:input入口參數(shù):stuStrus[]@函數(shù)功能:學(xué)生信息錄入,函數(shù)返回信息輸入成功的學(xué)生人數(shù)*/intinput(stuStrus[]){intn=-1,i;printf("請(qǐng)按下列格式輸入學(xué)生信息(行首輸入q結(jié)束輸入):\n");printf("----------------------------------------------------\n");printf("準(zhǔn)考證號(hào)\t姓名\t語(yǔ)文\t數(shù)學(xué)\t英語(yǔ)\t綜合\n");do{n++;

scanf("%s",s[n].id); //輸入準(zhǔn)考證號(hào)if(s[n].id[0]=='q'||s[n].id[0]=='Q')

break;scanf("%s",s[n].name); //輸入姓名for(i=0;i<4;i++) //輸入4門(mén)課程成績(jī)scanf("%f",&s[n].score[i]);}while(1);returnn; //返回有效學(xué)生人數(shù)}/*@函數(shù)名稱:sum入口參數(shù):stuStru*s,intn@函數(shù)功能:求學(xué)生的高考總分*/voidsum(stuStru*s,intn){inti,j;stuStru*p=s; //采用指針?lè)ㄔL問(wèn)數(shù)組while(p<s+n){p->total=0; //總分清0for(j=0;j<4;j++)p->total+=p->score[j];

p++;}}/*@函數(shù)名稱:selectSort入口參數(shù):stuStrus[],intn@函數(shù)功能:采用選擇排序法對(duì)學(xué)生信息按總分由高到低排序*/voidselectSort(stuStrus[],intn){inti,j,k,maxIndex;stuStrutemp;for(i=0;i<n-1;i++){maxIndex=i;for(j=i+1;j<n;j++) //查找最高分所在記錄if(s[j].total>s[maxIndex].total)maxIndex=j;if(i!=maxIndex){temp=s[i];s[i]=s[maxIndex];s[maxIndex]=temp;}}}/*@函數(shù)名稱:print入口參數(shù):stuStrus[],intn@函數(shù)功能:輸出學(xué)生信息*/voidprint(stuStru*s,intn){inti,j;if(n>0){printf("%-12s%-12s","準(zhǔn)考證號(hào)","姓名"); //輸出表頭printf("%-8s%-8s%-8s%-8s%-8s\n","語(yǔ)文","數(shù)學(xué)","英語(yǔ)","綜合","總分");printf("----------------------------------------------------\n");for(i=0;i<n;i++,s++){printf("%-12s",s->id); //輸出準(zhǔn)考證號(hào)printf("%-12s",s->name); //輸出姓名for(j=0;j<4;j++) //輸出成績(jī)printf("%-8.2f",s->score[j]);printf("%-8.2f\n",s->total); //輸出總分}}}intmain(){stuStrus[N];intn;

n=input(s); //輸入

sum(s,n); //求和selectSort(s,n); //按總分由高到低排序print(s,n); //輸出return0;}請(qǐng)按下列格式輸入學(xué)生信息(行首輸入q結(jié)束輸入):-----------------------------------------------------------------------------準(zhǔn)考證號(hào)姓名語(yǔ)文數(shù)學(xué)英語(yǔ)綜合110100101王曉東112120121230↙110100102李科108130125241↙110100103趙國(guó)慶9998101200↙110100104鄒婕121105130250↙110100105楊婷130132128256↙q↙準(zhǔn)考證號(hào)姓名語(yǔ)文數(shù)學(xué)英語(yǔ)綜合總分-----------------------------------------------------------------------------110100105楊婷130.00132.00128.00256.00646.00110100104鄒婕121.00105.00130.00250.00606.00110100102李科108.00130.00125.00241.00604.00110100101王曉東112.00120.00121.00230.00583.00110100103趙國(guó)慶99.0098.00101.00200.00498.00動(dòng)態(tài)數(shù)據(jù)結(jié)構(gòu)

——單鏈表8.68.6動(dòng)態(tài)數(shù)據(jù)結(jié)構(gòu)——單鏈表數(shù)組要求在內(nèi)存中占用連續(xù)的存儲(chǔ)空間。一方面,當(dāng)某程序運(yùn)行時(shí)需分配的數(shù)組規(guī)模較大時(shí),常會(huì)出現(xiàn)內(nèi)存無(wú)法提供滿足程序要求的空閑區(qū)的情況發(fā)生。另一方面,由于數(shù)組在定義時(shí)大小固定,當(dāng)數(shù)據(jù)量超出數(shù)組容量時(shí),不便動(dòng)態(tài)擴(kuò)展新的存儲(chǔ)空間。而采用鏈表可以有效解決這一問(wèn)題,鏈表是線性結(jié)構(gòu)的另一種有效存儲(chǔ)結(jié)構(gòu)。它為線性結(jié)構(gòu)中的各元素獨(dú)立地申請(qǐng)存儲(chǔ)空間,并且在每個(gè)元素內(nèi)增設(shè)指針來(lái)記錄其前驅(qū)或后續(xù)元素的位置。這種結(jié)構(gòu)不要求表中邏輯上相鄰的元素占用物理上相鄰的存儲(chǔ)空間。因此,能提高內(nèi)存空間利用率,同時(shí)便動(dòng)態(tài)擴(kuò)展。8.6動(dòng)態(tài)數(shù)據(jù)結(jié)構(gòu)——單鏈表8.6.1單鏈表的定義鏈表首結(jié)點(diǎn)指針結(jié)點(diǎn)結(jié)點(diǎn)值后續(xù)結(jié)點(diǎn)地址8.6.1單鏈表的定義為建立單鏈表,首先需要一個(gè)表示表中單個(gè)結(jié)點(diǎn)的結(jié)構(gòu)體類(lèi)型。structnode{ intdata; structnode*next;

};typedefstructnodelinknode;

typedeflinknode*linklist;

屬性域后續(xù)結(jié)點(diǎn)指針結(jié)點(diǎn)類(lèi)型結(jié)點(diǎn)指針類(lèi)型可根據(jù)需要擴(kuò)展屬性域接下來(lái),便可用linknode來(lái)聲明結(jié)構(gòu)體變量,用linklist來(lái)聲明指向結(jié)構(gòu)體的指針變量。例如:linklisthead=NULL;定義了一個(gè)結(jié)構(gòu)體指針,并將其初始化為空,表示初始鏈表head為空表。8.6.1單鏈表的定義8.6.2在單鏈表插入新結(jié)點(diǎn)要在單鏈表中插入值為x的結(jié)點(diǎn),首先要生成結(jié)點(diǎn)結(jié)構(gòu)體,我們可以定義指針q來(lái)指向新生成的結(jié)點(diǎn)空間(q指向的結(jié)點(diǎn)可簡(jiǎn)稱為結(jié)點(diǎn)q)。linklistq; //結(jié)點(diǎn)指針生成新結(jié)點(diǎn),并將待插入數(shù)據(jù)存入結(jié)點(diǎn)的語(yǔ)句為:q=(linklist)malloc(sizeof(linknode)); q->data=x; //假設(shè)x為待存入的數(shù)據(jù)下面討論如何將q指向的結(jié)點(diǎn)插入到單鏈表head中。根據(jù)鏈表狀態(tài)和插入的位置,通??梢苑譃槿N情況:8.6.2在單鏈表插入新結(jié)點(diǎn)原單鏈表head為空表(head==NULL),新加入的結(jié)點(diǎn)成為鏈表的第1個(gè)結(jié)點(diǎn)。原鏈表不為空,新結(jié)點(diǎn)q插入在單鏈表的最前面。原鏈表不為空,新結(jié)點(diǎn)q插入到鏈表中由p指向的結(jié)點(diǎn)后面。8.6.3建立單鏈表【例8.6】編寫(xiě)函數(shù),將鍵盤(pán)輸入的整數(shù)序列依次存入初始為空的單鏈表,函數(shù)返回新建單鏈表第一個(gè)結(jié)點(diǎn)地址。尾插法建立單鏈表#include<stdio.h>#include<stdlib.h>structnode{intdata;structnode*next;};typedefstructnodelinknode;typedeflinknode*linklist;Linklist.h/*@函數(shù)名稱:creatLink入口參數(shù):無(wú)@函數(shù)功能:建立單鏈表,函數(shù)返回單鏈表首結(jié)點(diǎn)地址*/linklistcreatLink(){linklisthead,tail,q;intx;head=tail=NULL; //初始化空鏈表printf("請(qǐng)輸入整數(shù)序列(以空格分隔,以0作為結(jié)束):\n");scanf("%d",&x);while(x!=0){q=(linklist)malloc(sizeof(linknode));//生成新結(jié)點(diǎn)q->data=x;if(head==NULL) //原鏈表為空head=tail=q;else //原鏈表不為空{(diào)tail->next=q;tail=q;} scanf("%d",&x);}if(tail!=NULL) tail->next=NULL;//置鏈表結(jié)束標(biāo)志returnhead;}#include"linklist.h"intmain(){linklisthead;head=creatLink();return0;}8.6.4單鏈表的遍歷所謂單鏈表的遍歷就是對(duì)單鏈表的所有結(jié)點(diǎn)進(jìn)行一遍訪問(wèn)?!纠?.7】請(qǐng)?jiān)趌inklist.h中定義函數(shù)voidprint(linklisthead),輸出單鏈表head的所有結(jié)點(diǎn)值。p=head;printf(“%5d”,p->data);p=p->next;/*@函數(shù)名稱:print入口參數(shù):linklisthead@函數(shù)功能:輸出單鏈表內(nèi)容*/voidprint(linklisthead){linklistp=head;printf("List:\n")while(p!=NULL)//當(dāng)p未遇到鏈表結(jié)束標(biāo)志時(shí){printf("%5d",p->data); //輸出當(dāng)前結(jié)點(diǎn)值

p=p->next; //指向下一個(gè)結(jié)點(diǎn)}printf("\n");}#include"linklist.h"intmain(){linklisthead;head=creatLink(); //建立單鏈表print(head); //輸出單鏈表return0;}請(qǐng)輸入整數(shù)序列(以空格分隔,以0作為結(jié)束):1020304050600List:1020304050608.6.5在單鏈表中查找結(jié)點(diǎn)在單鏈表中查找結(jié)點(diǎn)可采用順序查找的方法,其查找過(guò)程可借助于對(duì)單鏈表的遍歷來(lái)完成?!纠?.8】編寫(xiě)函數(shù)linklistsearchLink(linklisthead,intx),在單鏈表head中查找值為x的結(jié)點(diǎn),若查找成功返回該結(jié)點(diǎn)地址,否則返回NULL?!痉治觥坑靡粋€(gè)指針p,從單鏈表的第一個(gè)結(jié)點(diǎn)開(kāi)始,依次向后查找。linklistsearchLink(linklisthead,intx){linklistp=head;while(p!=NULL&&p->data!=x)p=p->next;returnp;}intmain(){linklisthead,p;intx;head=creatLink(); //建立單鏈表print(head); //輸出單鏈表printf("請(qǐng)輸入要查找的結(jié)點(diǎn)值:");scanf("%d",&x);p=searchLink(head,x);if(p!=NULL)printf("查找成功!");elseprintf("查找失??!\n");return0;}8.6.6在單鏈表中刪除結(jié)點(diǎn)在單鏈表中刪除結(jié)點(diǎn)需要知道被刪除結(jié)點(diǎn)前驅(qū)結(jié)點(diǎn)的位置。假設(shè)p指向被刪除結(jié)點(diǎn),pre指向p的前驅(qū)結(jié)點(diǎn),則刪除操作分兩種情況:(1)被刪除結(jié)點(diǎn)是單鏈表的第一個(gè)結(jié)點(diǎn)(2)被刪除結(jié)點(diǎn)不是單鏈表的第一個(gè)結(jié)點(diǎn)(1)被刪除結(jié)點(diǎn)是單鏈表的第一個(gè)結(jié)點(diǎn)(2)被刪除結(jié)點(diǎn)不是單鏈表的第一個(gè)結(jié)點(diǎn)【例8.9】編寫(xiě)一個(gè)函數(shù)linklistdeleteList(linklisthead,intx),刪除單鏈表head中值為x的結(jié)點(diǎn)。#include"linklist.h"/*@函數(shù)名稱deleteList入口參數(shù):linklisthead,intx@函數(shù)功能:在鏈表head中刪除第一個(gè)值為x的結(jié)點(diǎn)@出口參數(shù):返回刪除后的鏈表首結(jié)點(diǎn)地址*/linklistdeleteList(linklisthead,intx){ linklistpre,p; pre=NULL; p=head; while(p!=NULL&&p->data!=x) { pre=p; p=p->next; }if(p) //查找成功{if(pre==NULL) //情況(1):被刪除結(jié)點(diǎn)是鏈表的第一個(gè)結(jié)點(diǎn)head=head->next;else//情況(2):被刪除結(jié)點(diǎn)不是鏈表的第一個(gè)結(jié)點(diǎn)pre->next=p->next;free(p); //釋放p結(jié)點(diǎn)空間}returnhead;}intmain(){linklisthead,p;intx;head=creatLink(); //建立單鏈表print(head); //輸出單鏈表printf("請(qǐng)輸入要?jiǎng)h除的結(jié)點(diǎn)值:");scanf("%d",&x);head=deleteList(head,x);//刪除head中第一個(gè)值為x的結(jié)點(diǎn)print(head);return0;}請(qǐng)輸入整數(shù)序列(以空格分隔,以0作為結(jié)束):1234560List:123456請(qǐng)輸入要?jiǎng)h除的結(jié)點(diǎn)值:3List:12456編寫(xiě)一個(gè)函數(shù)freeLinklist(linklisthead),釋放單鏈表head的全部結(jié)點(diǎn)空間。voidfreeLinklist(linklisthead){linklistp;while(head!=NULL){p=head; head=head->next; free(p);}}學(xué)習(xí)本章后應(yīng)達(dá)到以下要求:(1)理解為何為使用結(jié)構(gòu)體。(2)掌握結(jié)構(gòu)體類(lèi)型與結(jié)構(gòu)體變量的定義方法。(3)掌握利用指針訪問(wèn)結(jié)構(gòu)體變量成員的方法。(4)掌握向函數(shù)傳遞結(jié)構(gòu)體的慣用法。(5)掌握應(yīng)用結(jié)構(gòu)體數(shù)組存儲(chǔ)復(fù)雜對(duì)象集合的方法。(6)掌握利用指針與結(jié)構(gòu)體實(shí)現(xiàn)單鏈表的基本方法。(7)掌握基于單鏈表的插入、查找、刪除等基本算法。本章小結(jié)實(shí)驗(yàn)八1.手機(jī)通信錄包括“姓名”“移動(dòng)電話”“固定電話”“e-mail”等信息。編寫(xiě)程序設(shè)計(jì)一個(gè)存儲(chǔ)手機(jī)通信錄的結(jié)構(gòu)體類(lèi)型,并定義結(jié)構(gòu)體變量,輸入某通信錄信息并在屏幕上輸出。2.完善例8.5程序功能,為其增加下列功能函數(shù):(1)學(xué)生信息查詢功能,即設(shè)計(jì)函數(shù),根據(jù)學(xué)生的準(zhǔn)考證號(hào)查詢學(xué)生成績(jī)信息。實(shí)驗(yàn)八(2)學(xué)生信息插入功能,即設(shè)計(jì)函數(shù),在結(jié)構(gòu)體數(shù)組的指定位置插入學(xué)生信息。(3)學(xué)生信息刪除功能,即設(shè)計(jì)函數(shù),根據(jù)準(zhǔn)考證號(hào)來(lái)刪除滿足條件的學(xué)生信息。(4)學(xué)生信息修改功能,即設(shè)計(jì)函數(shù),根據(jù)準(zhǔn)考證號(hào)修改指定學(xué)生的成績(jī)信息。實(shí)驗(yàn)八(5)按準(zhǔn)考證號(hào)排序的功能,即設(shè)計(jì)函數(shù),按學(xué)生準(zhǔn)考證號(hào)對(duì)學(xué)生信息表遞增排序。上述函數(shù)可逐個(gè)增加,并編寫(xiě)主函數(shù)進(jìn)行測(cè)試。實(shí)驗(yàn)八3.(選做)快速排序是一種高效的排序算法,其基本思想是:(1)分割。當(dāng)待排序數(shù)組段的元素個(gè)數(shù)大于1時(shí),取未排序數(shù)組中的第一個(gè)元素,以它為參照,將待排序數(shù)組段進(jìn)行劃分,使大于它的元素放到其左邊,小于或等于它的元素放到其右邊。至此,該劃分元素已經(jīng)處于它該處的最終位置,另外產(chǎn)生了兩個(gè)未排序的子數(shù)組。實(shí)驗(yàn)八(2)遞歸。對(duì)每一個(gè)未排序的數(shù)組段執(zhí)行步驟(1)。請(qǐng)?jiān)O(shè)計(jì)快速排序函數(shù)voidquickSort(stuStrus[],intlow,inthigh),采用快速排序法對(duì)例8.5中的學(xué)生信息(存儲(chǔ)在s[low..high]中)按總成績(jī)降序排序。實(shí)驗(yàn)八4.編寫(xiě)程序,在按結(jié)點(diǎn)值遞增有序的單鏈表中插入一個(gè)結(jié)點(diǎn),使單鏈表保持有序。5.編寫(xiě)程序,從鍵盤(pán)上輸入無(wú)序的數(shù)據(jù),建立有序的單鏈表。6.編寫(xiě)一個(gè)函數(shù)freeLinklist(linklisthead),將單鏈表head所有的結(jié)點(diǎn)空間釋放。高級(jí)語(yǔ)言程序設(shè)計(jì)高級(jí)語(yǔ)言程序設(shè)計(jì)——基于計(jì)算思維能力培養(yǎng)高級(jí)語(yǔ)言程序設(shè)計(jì)——基于計(jì)算思維能力培養(yǎng)第9章文件及其應(yīng)用主要內(nèi)容文件概述文件的打開(kāi)和關(guān)閉文件檢測(cè)函數(shù)文件讀寫(xiě)操作文件隨機(jī)讀寫(xiě)本章思維導(dǎo)圖學(xué)生

文件信息的創(chuàng)建9.19.1引例——學(xué)生文件信息的創(chuàng)建例如,在命令行下執(zhí)行:8_5<stu.txt>out.txtStu.txt輸入輸出重定向文件概述9.29.2文件概述9.2.1流的概念在C語(yǔ)言中的每個(gè)串行輸入源和輸出目標(biāo)被稱為“流”。輸入流是一個(gè)串行數(shù)據(jù)源,可以為程序提供輸入數(shù)據(jù)輸出流是串行數(shù)據(jù)的目的地,可以接收程序的輸出。流充當(dāng)了程序和輸入輸出設(shè)備之間的橋梁,這使得程序在輸入輸出數(shù)據(jù)時(shí)可以采用統(tǒng)一的方式來(lái)工作,而不必去關(guān)注具體的物理設(shè)備是什么。<stdio.h>提供了3個(gè)標(biāo)準(zhǔn)流流名稱流含義默認(rèn)連接外設(shè)stdin標(biāo)準(zhǔn)輸入鍵盤(pán)stdout標(biāo)準(zhǔn)輸出屏幕stderr標(biāo)準(zhǔn)錯(cuò)誤屏幕9.2.2文件的分類(lèi)1、文本文件與二進(jìn)制文件

C語(yǔ)言的<stdio.h>支持兩種類(lèi)型的文件:文本文件(也稱ASCII文件)和二進(jìn)制文件。在文本文件中,用字節(jié)來(lái)存儲(chǔ)字符,這使人們可以檢查或編輯文件。在二進(jìn)制文件中,字節(jié)不一定表示字符,有可能是某數(shù)值型數(shù)據(jù)的某些bit位。例如,假設(shè)有變量聲明語(yǔ)句: shortinta=32767;在二進(jìn)制文件中,變量a僅占2個(gè)字節(jié)的存儲(chǔ)空間,如圖9-3所示。圖9-31、文本文件與二進(jìn)制文件

圖9-4而把變量a的值存入到文本文件中則需要5個(gè)字節(jié)的存儲(chǔ)空間,如圖9-4所示。例如,假設(shè)有變量聲明語(yǔ)句: shortinta=32767;1、文本文件與二進(jìn)制文件

另外,文本文件還有以下特性:文本文件分為若干行。文本文件的每一行通常以一兩個(gè)特殊字符結(jié)尾,在Windows中,行末的標(biāo)記是回車(chē)符與換行符。文本文件可以包含一個(gè)特殊的“文件末尾”標(biāo)記。一些操作系統(tǒng)允許在文本文件的末尾使用一個(gè)特殊的字節(jié)作為標(biāo)記。在Windows中,標(biāo)記為'\x1a'(Ctrl+Z)。1、文本文件與二進(jìn)制文件

2、緩沖文件與非緩沖文件

C語(yǔ)言中可使用以下兩種文件系統(tǒng):緩沖文件系統(tǒng),又稱為標(biāo)準(zhǔn)文件系統(tǒng)或高級(jí)文件系統(tǒng)。是一種高效、方便且常用的文件系統(tǒng)。后面要學(xué)習(xí)的文件操作函數(shù)都是基于緩沖文件系統(tǒng)的。非標(biāo)準(zhǔn)緩沖文件系統(tǒng),又稱低級(jí)文件系統(tǒng)。該系統(tǒng)與機(jī)器有關(guān),節(jié)省內(nèi)存,執(zhí)行效率高,但是應(yīng)用難度大。圖9-5文件緩沖區(qū)工作原理9.2.3文件指針stdio.h中定義了文件結(jié)構(gòu)體類(lèi)型FILE。typedefstruct{ shortlevel; /*緩沖區(qū)‘滿’或‘空’的程度*/ unsignedflags; /*文件狀態(tài)標(biāo)志*/ charfd; /*文件描述符*/ unsignedcharhold; /*如無(wú)緩沖區(qū)不讀字符*/ shortbsize; /*緩沖區(qū)的大小*/ unsignedchar*buffer; /*數(shù)據(jù)緩沖區(qū)的位置*/ unsignedchar*curp; /*指針當(dāng)前的指向*/ unsignedistemp; /*臨時(shí)文件指示器*/ shorttoken; /*用于有效性檢查*/}FILE; C語(yǔ)言中對(duì)流的訪問(wèn)是通過(guò)文件指針實(shí)現(xiàn)的,文件指針的類(lèi)型為FILE*。用文件指針表示特定的流具有標(biāo)準(zhǔn)的名字,如stdin、stdout和stderr等;我們可以根據(jù)程序需要聲明一些另外的文件指針。例如:FILE*fp1,*fp2;定義了兩個(gè)文件指針fp1和fp2。可以通過(guò)文件打開(kāi)函數(shù)將文件指針連接到指定的文件上。文件的打開(kāi)與關(guān)閉9.39.3.1文件的打開(kāi)1、fopen函數(shù)打開(kāi)文件要使用庫(kù)函數(shù)fopen(),其函數(shù)原型為:FILE*fopen(constchar*filename,constchar*mode);fopen函數(shù)返回一個(gè)文件指針。例如:fp=fopen("in.dat","r");fp=fopen("d:\\cprogram\\test.c","r");為何要用\\注意:當(dāng)打開(kāi)的文件不存在或建立新文件時(shí)沒(méi)有訪問(wèn)權(quán)限等將導(dǎo)致無(wú)法打開(kāi)文件,此時(shí)fopen函數(shù)會(huì)返回空指針。因此打開(kāi)文件后要測(cè)試fopen函數(shù)返回值以確保文件是否被正確打開(kāi)。2、讀寫(xiě)模式模式字符串含義"r"或"rt"打開(kāi)文本文件用于讀"rb"打開(kāi)二進(jìn)制文件用于讀"w"或"wt"打開(kāi)文本文件用于寫(xiě)(文件不需要存在)"wb"打開(kāi)二進(jìn)制文件用于寫(xiě)(文件不需要存在)"a"或"at"打開(kāi)文本文件用于追加(文件不需要存在)"ab"打開(kāi)二進(jìn)制文件用于追加(文件不需要存在)"r+"或"rt+"打開(kāi)文本文件用于讀和寫(xiě),從文件頭開(kāi)始"rb+"打開(kāi)二進(jìn)制文件用于讀和寫(xiě),從文件頭開(kāi)始模式字符串含義"w+"或"wt+"打開(kāi)文本文件用于讀和寫(xiě)(如果文件存在就覆蓋原文件)"wb+"打開(kāi)二進(jìn)制文件用于讀和寫(xiě)(如果文件存在就覆蓋原文件)"a+"或"at+"打開(kāi)文本文件用追加方式進(jìn)行讀和寫(xiě)"ab+"打開(kāi)二進(jìn)制文件用追加方式進(jìn)行讀和寫(xiě)2、讀寫(xiě)模式9.3.2文件的關(guān)閉C語(yǔ)言使用fclose函數(shù)來(lái)關(guān)閉已打開(kāi)的文件。其函數(shù)原型如下:intfclose(FILE*filename);其中filename是文件指針,指向已打開(kāi)的文件。9.3.2文件的關(guān)閉文件檢測(cè)函數(shù)9.49.4.1檢測(cè)文件末尾函數(shù)feof()函數(shù)用來(lái)檢測(cè)文件讀寫(xiě)位置指針是否已到文件末尾。feof()的調(diào)用格式為:feof(fp);fp是文件指針,如果文件讀寫(xiě)位置指針已到文件末尾,則函數(shù)返回非0值(邏輯真);否則函數(shù)返回0值(邏輯假)。例如,我們常用下面的語(yǔ)句來(lái)控制文件讀寫(xiě):

while(!feof(fp))

文件讀/寫(xiě)語(yǔ)句;9.4.1檢測(cè)文件末尾函數(shù)9.4.2檢測(cè)出錯(cuò)函數(shù)ferror()函數(shù)可用來(lái)檢測(cè)輸入輸出函數(shù)的每次調(diào)用是否有錯(cuò),函數(shù)的調(diào)用格式是:ferror(fp)正常時(shí)函數(shù)返回0值,出錯(cuò)時(shí)函數(shù)返回非值(邏輯真)。一般在調(diào)用輸入輸出函數(shù)后可調(diào)用該函數(shù),以檢查輸入輸出函數(shù)的引用是否正確。例如:

文件讀寫(xiě)語(yǔ)句; if(ferror(fp)) printf("文件讀寫(xiě)錯(cuò)誤!\n");9.4.2檢測(cè)出錯(cuò)函數(shù)文件的讀寫(xiě)操作9.59.5.1字符讀/寫(xiě)函數(shù)1、字符讀函數(shù)fgetc()該函數(shù)用來(lái)從文件讀取一個(gè)字符,其函數(shù)原型為:intfgetc(FILE*fp);從fp讀出一個(gè)字符,將位置指針指向下一個(gè)字符,若讀成功,則返回該字符;若讀到文件尾,則返回EOF。常見(jiàn)的用法:while(!feof(fp)) {ch=fgetc(fp); … }

對(duì)文本文件還可以用以下的形式來(lái)判斷文件是否已讀到文件末尾。while((ch=fgetc(fp))!=EOF) …9.5.1字符讀/寫(xiě)函數(shù)2、字符寫(xiě)函數(shù)fputc()該函數(shù)用來(lái)將一個(gè)字符寫(xiě)入文件。其函數(shù)原型為:intfputc(intch,FILE*fp);其中,ch是字符常量或字符變量,fp是文件指針。該語(yǔ)句的功能是把字符ch寫(xiě)入到fp所指向的文件中;如果函數(shù)執(zhí)行成功,則返回ch;否則,返回EOF。例如:fputc('A',fp);

將大寫(xiě)字母'A'寫(xiě)入fp指示的文件中。9.5.2字符讀/寫(xiě)函數(shù)應(yīng)用實(shí)例【例9.1】編寫(xiě)一個(gè)程序,將從鍵盤(pán)輸入若干行字符串存入9_1.txt文件,并將文件中的內(nèi)容重新讀出顯示到屏幕上(以'#'作為輸入結(jié)束標(biāo)志)?!痉治觥靠墒紫葘㈡I盤(pán)上輸入的若干文本行寫(xiě)入文件,再重新以只讀方式打開(kāi)文件,將其內(nèi)容讀出后顯示在屏幕上。#include<stdio.h>intmain(){charch;FILE*fp;

fp=fopen("9_1.txt","w"); //以寫(xiě)方式打開(kāi)文本文件if(fp!=NULL){printf("請(qǐng)輸入若干行文本,以#結(jié)束輸入:\n");while((ch=getchar())!='#')//循環(huán)寫(xiě)入fputc(ch,fp);fclose(fp);}elseprintf("文件創(chuàng)建失敗!\n");fp=fopen("9_1.txt","r"); //以讀方式打開(kāi)文本文件if(fp!=NULL){printf("文件內(nèi)容是:\n");while(!feof(fp)) //循環(huán)讀出{ch=fgetc(fp);putchar(ch); //可用fputc(ch,stdout)代替putchar(ch)}fclose(fp); //關(guān)閉文件}elseprintf("文件打開(kāi)失??!\n");return0;}請(qǐng)輸入若干行文本,以#結(jié)束輸入:

TeachyouhowtoreadCprograms↙TeachyouhowtowriteCprograms↙TeachyouhowtodebugCprograms#↙文件內(nèi)容是:TeachyouhowtoreadCprogramsTeachyouhowtowriteCprogramsTeachyouhowtodebugCprograms9.5.3字符串讀/寫(xiě)函數(shù)函數(shù)fgets和fputs分別用于從指定的文件中讀出一個(gè)字符串和把一個(gè)字符串寫(xiě)入指定的文件。1、字符串讀函數(shù)fgets()函數(shù)fgets可以從指定文件中讀入一行字符串并存入到字符數(shù)組中。其函數(shù)原型為:char*fgets(char*s,intn,FILE*fp);

例如,若字符數(shù)組s的大小為20,則:fgets(s,20,fp);

從fp指向的文件中讀取最大長(zhǎng)度為19的字符串存入s。

利用這一特性,我們可以用:fgets(s,sizeof(s),stdin);

來(lái)限定從鍵盤(pán)輸入的字符串的大小,這比直接用gets(s)函數(shù)要安全,可以防止輸入數(shù)據(jù)過(guò)長(zhǎng)而導(dǎo)致非法訪問(wèn)內(nèi)存。2、字符串寫(xiě)函數(shù)fputs()函數(shù)fputs可以將一個(gè)字符串寫(xiě)入指定的文件,其函數(shù)原型為:intfputs(constchar*s,FILE*fp);9.5.4字符串讀/寫(xiě)函數(shù)應(yīng)用實(shí)例【例9.2】從鍵盤(pán)輸入一行字符串:“TeachyouhowtodesigngoodCprograms”,將其追加到text01.txt文本中去?!痉治觥恳蛞騮ext01.txt中追加信息,所以應(yīng)該將其打開(kāi)方式設(shè)置為a。#include<stdio.h>#defineN80intmain(){chars[N];FILE*fp;

fp=fopen("text01.txt","a");if(fp!=NULL){printf("請(qǐng)輸入一行文本:\n");fgets(s,N,stdin); //從鍵盤(pán)輸入字符串fputs(s,fp); //寫(xiě)入文件fclose(fp); //關(guān)閉文件}elseprintf("文件打開(kāi)失??!\n");}9.5.5格式化讀/寫(xiě)函數(shù)1、格式化讀函數(shù)fscanf()fscanf的函數(shù)原型為:intfscanf(FILE*fp,constchar*format,變量地址列表);如果函數(shù)執(zhí)行成功,則返回正確輸入項(xiàng)的個(gè)數(shù);若執(zhí)行失敗,則返回0。例:

fscanf(fp,"%s%d",name,&age);2、格式化寫(xiě)函數(shù)fprintf()fprintf的函數(shù)原型為:intfprintf(FILE*fp,constchar*format,輸出項(xiàng)列表);例如:fprintf(fp,"%12s%6d",name,age);將字符串name和整型變量age的值存入fp指向的文件。9.5.6格式化讀/寫(xiě)函數(shù)應(yīng)用實(shí)例【例9.3】為例8.5中的程序設(shè)計(jì)從文件讀數(shù)據(jù)的函數(shù)和將學(xué)生數(shù)據(jù)存盤(pán)的函數(shù)。(1)增加從文件讀數(shù)據(jù)函數(shù)intreadData(stuStrus[],char*filename),從文件filename中讀入學(xué)生信息,存入學(xué)生數(shù)組s,函數(shù)返回讀取的學(xué)生人數(shù);(2)增加函數(shù)voidsaveData(stuStrus[],char*filesname,intn),將學(xué)生信息存入filename文件。數(shù)據(jù)格式:可以通過(guò)feof函數(shù)來(lái)判斷對(duì)文件的讀寫(xiě)是否到達(dá)文件末尾。/*@函數(shù)名稱:readData入口參數(shù):stuStrus[],char*filename@函數(shù)功能:從文件filename讀入學(xué)生信息存入s,返回正確讀取的學(xué)生人數(shù)*/intreadData(stuStrus[],char*filename){FILE*fp;fp=fopen(filename,"r");if(fp!=NULL){intn=0,i;while(!feof(fp)){fscanf(fp,"%s",s[n].id); //讀入準(zhǔn)考證號(hào)fscanf(fp,"%s",s[n].name); //讀入姓名for(i=0;i<4;i++) //讀入4門(mén)課程成績(jī)fscanf(fp,"%f",&s[n].score[i]);n++;}fclose(fp);returnn; //返回有效學(xué)生人數(shù)}elsereturn0;}/*@函數(shù)名稱:saveData入口參數(shù):stuStrus[]char*filename,intn@函數(shù)功能:學(xué)生信息存盤(pán)函數(shù)*/voidsaveData(stuStru*s,char*filename,intn){FILE*fp;inti,j;fp=fopen(filename,"w");if(fp!=NULL){for(i=0;i<n;i++,s++){fprintf(fp,"%-12s",s->id); //輸出準(zhǔn)考證號(hào)fprintf(fp,"%-12s",s->name); //輸出姓名for(j=0;j<4;j++) //輸出成績(jī)fprintf(fp,"%-8.2f",s->score[j]);fprintf(fp,"%-8.2f\n",s->total);//輸出總分}fclose(fp);//關(guān)閉文件}elseprintf("文件保存失敗!\n");}intmain(){stuStrus[N];intn;n=readData(s,"studata.txt"); //從文件讀數(shù)據(jù)sum(s,n); //求和quickSort(s,0,n-1); //按總分由高到低排序print(s,n); //輸出saveData(s,"9_3.txt",n); //存盤(pán)return0;}準(zhǔn)考證號(hào)姓名語(yǔ)文數(shù)學(xué)英語(yǔ)綜合總分-----------------------------------------------------------------------------110100105楊婷130.00132.00128.00256.00646.00110100104劉潔121.00105.00130.00250.00606.00110100102李科108.00130.00125.00241.00604.00110100101王曉東112.00120.00121.00230.00583.00110100103趙國(guó)慶99.0098.00101.00200.00498.009.5.7數(shù)據(jù)塊讀/寫(xiě)函數(shù)1、數(shù)據(jù)塊讀函數(shù)fread()fread函數(shù)用于從文件中讀出一個(gè)數(shù)據(jù)塊,其函數(shù)原型為:unsignedfread(void*buffer,unsignedsize,unsignedcount,FILE*fp);fwrite函數(shù)用于向文件寫(xiě)入一個(gè)數(shù)據(jù)塊,其函數(shù)原型為:unsignedfwrite(constvoid*buffer,unsignedsize,unsignedcount,FILE*fp);2、數(shù)據(jù)塊寫(xiě)函數(shù)fwrite()例9.3中的saveData函數(shù)對(duì)每一個(gè)學(xué)生數(shù)據(jù),是采用逐個(gè)數(shù)據(jù)項(xiàng)的方式來(lái)輸出到文件中的,這種方式的優(yōu)點(diǎn)是文件中的數(shù)據(jù)按固定的格式呈現(xiàn),便于用戶用記事本直接瀏覽,但操作的效率較低。采用fwrite()函數(shù)一次性將學(xué)生結(jié)構(gòu)體數(shù)組的n個(gè)元素寫(xiě)入文件具有較高的存取效率。但該函數(shù)寫(xiě)入數(shù)據(jù)時(shí)是將內(nèi)存數(shù)據(jù)塊直接寫(xiě)入文件,因此宜采用二進(jìn)制文件為宜。同時(shí)應(yīng)注意,用fwrite()寫(xiě)入文件的數(shù)據(jù)應(yīng)該用fread()函數(shù)按相應(yīng)地格式來(lái)進(jìn)行讀取,才能正確的還原數(shù)據(jù)。9.5.8數(shù)據(jù)塊讀/寫(xiě)函數(shù)應(yīng)用實(shí)例(1)wirteToFile函數(shù),采用fwrite函數(shù)保存學(xué)生數(shù)據(jù)至文件。(2)readFromFile函數(shù),采用fread函數(shù)從文件讀入學(xué)生數(shù)據(jù)至某學(xué)生結(jié)構(gòu)體數(shù)組,并將結(jié)果顯示到屏幕上?!纠?.4】為例9.3的程序設(shè)計(jì)函數(shù):voidwriteToFile(stuStrus[],char*filename,intn){FILE*fp;fp=fopen(filename,"wb"); //打開(kāi)文件if(fp!=NULL){ fwrite(s,sizeof(stuStru),n,fp); //寫(xiě)文件 fclose(fp);}elseprintf("文件保存失??!\n");}/*@函數(shù)名稱:readFromFile入口參數(shù):stuStrus[]char*filename@函數(shù)功能:從文件filename讀入學(xué)生信息存入s,返回正確讀取的學(xué)生人數(shù)*/intreadFromFile(stuStrus[],char*filename){FILE*fp;intn=0,k;fp=fopen(filename,"rb");//打開(kāi)文件if(fp!=NULL){while(1){k=fread(s+n,sizeof(stuStru),1,fp);//讀取一條記錄if(k!=1)

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(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)論