




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、第九章 流類庫和輸入/輸出本章的最主要目的就是把對(duì)象保存到磁盤文件中并從磁盤文件重建對(duì)象。C+語言中并沒有輸入/輸出語句,而是在標(biāo)準(zhǔn)庫里包含了一個(gè)I/O流類庫,它與標(biāo)準(zhǔn)模板庫同為C+標(biāo)準(zhǔn)庫中最重要的組成部分。數(shù)據(jù)從一個(gè)對(duì)象到另一個(gè)對(duì)象的傳送被抽象為“流”。數(shù)據(jù)的輸入/輸出就是通過輸入/輸出流來實(shí)現(xiàn)的。 流是一種抽象的概念,負(fù)責(zé)在數(shù)據(jù)的產(chǎn)生者和數(shù)據(jù)的使用者之間建立聯(lián)系,并管理數(shù)據(jù)的流動(dòng)。 第九章 流類庫和輸入/輸出9.1 C+的基本流類體系 9.3 標(biāo)準(zhǔn)設(shè)備的輸入/輸出 9.2 輸入輸出的格式控制(選讀) 9.4 文件的輸入與輸出 9.5 字符串流(選讀) 9.6 文件與對(duì)象 9.1 C+的基本
2、流類體系流類體系:以抽象類模板basic_ios為基類,流類模板派生體系見圖9.1。整個(gè)流類模板體系的標(biāo)準(zhǔn)I/O在頭文件中說明,它包含頭文件、和。而輸入輸出文件流部分在頭文件中說明。 圖9.1 主要輸入/輸出流模板層次 basic_ iosbasic_ streambufbasic_ istreambasic_ ostreambasic_ ifstreambasic_ iostreambasic_ ofstreambasic_ fstream指針9.1 C+的基本流類體系 basic_ios類模板提供了對(duì)流進(jìn)行格式化輸入輸出和錯(cuò)誤處理的成員函數(shù)。所有派生都是公有派生。basic_istream
3、類模板提供完成提取(輸入)操作的成員函數(shù),而basic_ostream類模板提供完成插入(輸出)操作的成員函數(shù)。basic_iostream類本質(zhì)上是前兩者的聚合,并沒有增加成員。派生全部為公有派生。 有關(guān)模板派生請(qǐng)參見教學(xué)指導(dǎo)書第8章中“類模板的派生的討論” basic_streambuf不是basic_ios的派生類,而是一個(gè)獨(dú)立的類,只是basic_ios有一個(gè)保護(hù)訪問限制的指針指向它。 類basic_streambuf的作用是管理一個(gè)流的緩沖區(qū)。流類體系說明:9.1 C+的基本流類體系標(biāo)準(zhǔn)輸入/輸出流對(duì)象: 在C+的流類庫中定義了四個(gè)全局流對(duì)象:cin,cout,cerr和clog???/p>
4、以完成人機(jī)交互的功能。 cin標(biāo)準(zhǔn)輸入流對(duì)象,鍵盤為其對(duì)應(yīng)的標(biāo)準(zhǔn)設(shè)備。 cout標(biāo)準(zhǔn)輸出流對(duì)象,顯示器為標(biāo)準(zhǔn)設(shè)備。 cerr和clog標(biāo)準(zhǔn)錯(cuò)誤輸出流,輸出設(shè)備是顯示器。 其中cin、cout和clog是帶緩沖區(qū)的,緩沖區(qū)由streambuf類對(duì)象來管理。而cerr為非緩沖區(qū)流,一旦錯(cuò)誤發(fā)生立即顯示。 要使用這四個(gè)功能,必須包含文件。 9.1 C+的基本流類體系重載的提取運(yùn)算符“”(stream_extraction operator)和插入運(yùn)算符“和(istream&,className&);friend ostream&operator”或“”和“”或“”的左操作數(shù);第二個(gè)參數(shù)為用戶定義類的
5、引用,作為右操作數(shù)。流用作函數(shù)參數(shù),必須是引用調(diào)用,不能是傳值調(diào)用。因?yàn)檫@里要求處理流本身,而不是副本?!纠?.5】改進(jìn)自定義字符串類,重載插入運(yùn)算符“”。【例9.6】用戶定義的復(fù)數(shù)類Complex的輸入與輸出。 9.4 文件的輸入與輸出 本節(jié)中文件指的是磁盤文件。C+根據(jù)文件(file)內(nèi)容的數(shù)據(jù)格式,可分為兩類:二進(jìn)制文件和文本文件。文本文件由字符序列組成,也稱ASCII碼文件,在文本文件中存取的最小信息單位為字符(character),而二進(jìn)制文件中存取的最小信息單位為字節(jié)(Byte)。C+把每一個(gè)文件都看成一個(gè)有序的字節(jié)流,見圖9.2,每一個(gè)文件或者以文件結(jié)束符(end of file
6、 marker)結(jié)束,或者在特定的字節(jié)號(hào)處結(jié)束。 012436578n-1文件結(jié)束符圖9.2 C+把文件看作有序的n個(gè)字節(jié)的流文件的基本概念:9.4 文件的輸入與輸出當(dāng)打開一個(gè)文件時(shí),該文件就和某個(gè)流關(guān)聯(lián)起來了。對(duì)文件進(jìn)行讀寫實(shí)際上受到一個(gè)文件定位指針(file position pointer)的控制。 輸入流的指針也稱為讀指針,每一次提取操作將從讀指針當(dāng)前所指位置開始,每次提取操作自動(dòng)將讀指針向文件尾移動(dòng)。 輸出流指針也稱寫指針,每一次插入操作將從寫指針當(dāng)前位置開始,每次插入操作自動(dòng)將寫指針向文件尾移動(dòng)。9.4.1 文件的打開與關(guān)閉 9.4.2 文本文件的讀寫9.4.3 二進(jìn)制文件的讀寫
7、9.4.4 文件的隨機(jī)訪問(選讀) 9.4.1 文件的打開與關(guān)閉文件使用步驟:1說明一個(gè)文件流對(duì)象,這又被稱為內(nèi)部文件:ifstream ifile;/只輸入用ofstream ofile;/只輸出用fstream iofile;/既輸入又輸出用 9.4.1 文件的打開與關(guān)閉2使用文件流對(duì)象的成員函數(shù)打開一個(gè)磁盤文件。這樣在文件流對(duì)象和磁盤文件名之間建立聯(lián)系。文件流中說明了三個(gè)打開文件的成員函數(shù)。void ifstream:open(const char*,int =ios:in, int=filebuf:openprot);void ofstream:open(const char *,in
8、t=ios:out, int=filebuf:opernprot);void fstream:open(const char*,int, int=filebuf:openprot); 第一個(gè)參數(shù)為要打開的磁盤文件名。第二個(gè)參數(shù)為打開方式,有輸入(in),輸出(out)等,打開方式在ios基類中定義為枚舉類型。第三個(gè)參數(shù)為指定打開文件的保護(hù)方式,一般取默認(rèn)。所以第二步可如下進(jìn)行:iofile.open(“myfile.txt”,ios:in|ios:out);文件打開方式:是由在ios類中定義的公有枚舉成員決定:enum open_mode in=0 x01,out=0 x02,ate=0 x0
9、4,app=0 x08,trunc=0 x10,binary=0 x80;9.4.1 文件的打開與關(guān)閉 in標(biāo)識(shí)打開文件用于輸入操作(從文件讀取)。打開方式只要含in,如文件不存在則返回失敗。在打開為輸入輸出方式時(shí)(同時(shí)用out),編程應(yīng)注意判斷是否失敗,失敗時(shí)千萬不可再寫入文件。 out標(biāo)識(shí)打開文件用于輸出操作(寫入文件)。如文件不存在,則建立新文件,如文件存在,未同時(shí)設(shè)app, in則文件清空。 trunc標(biāo)識(shí)打開文件,并清空它(文件長度截為0)。文件不存在則建立新文件,與out默認(rèn)操作相同。但與in配合,文件不存在則返回失敗。 app標(biāo)識(shí)打開文件用于輸出,原文件內(nèi)容保留,新數(shù)據(jù)接在尾部
10、ate意思是at end,標(biāo)識(shí)打開文件,文件指針在文件尾,但文件指針可以移動(dòng),即新數(shù)據(jù)可寫到任何位置。文件是否清空由其它標(biāo)識(shí)決定。 后三個(gè)標(biāo)識(shí)最好配合out、in等一起用,因?yàn)椴煌腃+平臺(tái),要求不同,一起用不會(huì)出錯(cuò)。如不一起用,至少VC+不認(rèn)這種格式。 binary標(biāo)識(shí)以二進(jìn)制方式打開文件。同時(shí)用out時(shí),如文件不存在,則建立新文件,并且新文件能用,不必清狀態(tài)字。打開方式解釋:9.4.1 文件的打開與關(guān)閉 三個(gè)文件流類都重載了一個(gè)帶默認(rèn)參數(shù)的構(gòu)造函數(shù),功能與open函數(shù)一樣:ifstream:ifstream(const char*, int=ios:in, int=filebuf:open
11、prot);ofstream:ofstream(const char*,int=ios:out, int=filebuf:openprot);fstream:fstream(const char*,int, int=filebuf:operprot);所以1,2兩步可合成:fstream iofile(”myfile.txt”,ios:in|ios:out);9.4.1 文件的打開與關(guān)閉打開文件也應(yīng)該判斷是否成功,若成功,文件流對(duì)象值為非零值,不成功為0(NULL),文件流對(duì)象值物理上就是指它的地址。因此打開一個(gè)文件完整的程序?yàn)椋篺stream iofile(”myfile.txt”,ios:
12、in|ios:out);if(!iofile) /“!”為重載的運(yùn)算符,見9.3.1節(jié) cout”不能打開文件:”myfile.txt”)和插入運(yùn)算符(”完成重構(gòu)對(duì)象,而只用一個(gè)“”完成對(duì)象存入文件。9.4.2 文本文件的讀寫文本數(shù)據(jù)文件的讀寫:按C+的常規(guī),資源獲取是由構(gòu)造函數(shù)實(shí)現(xiàn),而資源釋放是由析構(gòu)函數(shù)完成。所以與內(nèi)存動(dòng)態(tài)分配一樣,由文件重構(gòu)對(duì)象放在構(gòu)造函數(shù)中,把對(duì)象存入文件則放在析構(gòu)函數(shù)中。詳細(xì)內(nèi)容見9.6節(jié),更深層次的理由見下一章異常處理?!纠?.9】只是為了更清楚地顯示文件的操作,常規(guī)做法請(qǐng)讀者參見【例9.13】。9.4.3 二進(jìn)制文件的讀寫對(duì)二進(jìn)制文件進(jìn)行讀寫的成員函數(shù):istre
13、am&istream:read(char *,int); /從二進(jìn)制流提取istream&istream:read(unsigned char*,int);/第一個(gè)參數(shù)指定存放有效輸入的變量地址,必須強(qiáng)制轉(zhuǎn)換為char*類型/第二個(gè)參數(shù)指定提取的字節(jié)數(shù),/函數(shù)從輸入流提取指定數(shù)量的字節(jié)送到指定地址開始的單元ostream&ostream:write(const char *,int);/向二進(jìn)制流插入ostream&ostream:write(const unsigned char *,int);/第一個(gè)參數(shù)指定輸出對(duì)象的內(nèi)存地址,必須強(qiáng)制轉(zhuǎn)換為char*類型/第二個(gè)參數(shù)指定插入的字節(jié)數(shù),/函
14、數(shù)從該地址開始將指定數(shù)量的字節(jié)插入輸入輸出流9.4.3 二進(jìn)制文件的讀寫文件結(jié)束判斷:讀函數(shù)并不能知道文件是否結(jié)束,可用狀態(tài)函數(shù)int ios:eof()來判斷文件是否結(jié)束。必須指出系統(tǒng)是根據(jù)當(dāng)前操作的實(shí)際情況設(shè)置狀態(tài)位,如需根據(jù)狀態(tài)位來判斷下一步的操作,必須在一次操作后立即去調(diào)取狀態(tài)位,以判斷本次操作是否有效。【例9.10】創(chuàng)建二進(jìn)制數(shù)據(jù)文件,以及數(shù)據(jù)文件的讀取。這兩項(xiàng)操作設(shè)計(jì)為成員函數(shù)。給出與【例9.9】不同的讀寫方式:9.4.3 二進(jìn)制文件的讀寫二進(jìn)制文件優(yōu)點(diǎn): 可以控制字節(jié)長度,讀寫數(shù)據(jù)時(shí)不會(huì)出現(xiàn)二義性,可靠性高。同時(shí)不知格式是無法讀取的,保密性好。文件結(jié)束后,系統(tǒng)不會(huì)再讀(見eofb
15、it的說明),但程序不會(huì)自動(dòng)停下來,所以要判斷文件中是否已沒有數(shù)據(jù)。如寫完數(shù)據(jù)后沒有關(guān)閉文件,直接開始讀,則必須把文件定位指針移到文件頭。如關(guān)閉文件后重新打開,文件定位指針就在文件頭。9.4.4 文件的隨機(jī)訪問(選讀)文件的隨機(jī)訪問:在C+中可以由程序控制文件指針的移動(dòng),從而實(shí)現(xiàn)文件的隨機(jī)訪問,即可讀寫流中任意一段內(nèi)容。一般文本文件很難準(zhǔn)確定位,所以隨機(jī)訪問多用于二進(jìn)制文件。如【例9.9】中對(duì)象中兩個(gè)字符串是按實(shí)際串長存放的,不是按數(shù)組元素來存放的,而【例9.10】中是按數(shù)組長度來存放的,每個(gè)對(duì)象數(shù)據(jù)長度固定,所以便于隨機(jī)訪問。在ios類中說明了一個(gè)公有枚舉類型:enum seek_dirbe
16、g=0, /文件開頭cur=1, /文件指針的當(dāng)前位置end=2 /文件結(jié)尾;隨機(jī)訪問指針控制字:9.4.4 文件的隨機(jī)訪問(選讀)輸入流指針控制字設(shè)置成員函數(shù):istream&istream:seekg(streampos); /指針直接定位istream&istream:seekg(streamoff, ios:seek_dir); /指針相對(duì)定位long istream:tellg(); /返回當(dāng)前指針位置流的指針位置類型streampos和流的指針偏移類型streamoff定義為長整型,也就是可訪問文件的最大長度為4G例:datafile.seekg(-20L,ios:cur);/表示
17、將文件定位指針從當(dāng)前位置向文件頭部方向移20個(gè)字節(jié)。datafile.seekg(20L,ios:beg);/表示將文件定位指針從文件頭向文件尾方向移20個(gè)字節(jié)。datafile.seekg(-20L,ios:end);/表示將文件定位指針從文件尾向文件頭方向移20個(gè)字節(jié)。tellg()和seekg()往往配合使用。/指針不可移到文件頭之前或文件尾之后。9.4.4 文件的隨機(jī)訪問(選讀)輸入流指針控制字設(shè)置成員函數(shù):ostream&ostream:seekp(streampos);ostream&ostream:seekp(streamoff,ios:seek_dir);long ostrea
18、m:tellp(); 為了便于記憶,函數(shù)名中g(shù)是get的縮寫,而p是put的縮寫。對(duì)輸入輸出文件定位指針只有一個(gè)但函數(shù)有兩組,這兩組函數(shù)功能完全一樣。 【例9.11】使用隨機(jī)訪問對(duì)【例9.10】進(jìn)行改造。9.5 字符串流(選讀)字符流概念: 字符串(string)也可以看作字符流??梢杂幂斎胼敵霾僮鱽硗瓿纱鞯牟僮鳌4髋c內(nèi)存相關(guān),所以也稱內(nèi)存流。 串流類包括ostrstream、istrstream、strstream,它們?cè)谥姓f明。串流類對(duì)象可以保存字符,也可以保存整數(shù)、浮點(diǎn)數(shù)。串流類對(duì)象采用文本方式。其構(gòu)造函數(shù)常用下面幾個(gè):istrstream:istrstream(const char
19、 * str);istrstream:istrstream(const char * str,int);ostrstream:ostrstream(char *,int,int=ios:out);strstream:strstream(char *,int,int); 其中第二個(gè)參數(shù)說明數(shù)組大小,第三參數(shù)為文件打開方式?!纠?.12】9.6 文件與對(duì)象在面向?qū)ο蟮腃+程序設(shè)計(jì)中,文件應(yīng)該在構(gòu)造函數(shù)中打開,并創(chuàng)建對(duì)象;而在析構(gòu)函數(shù)中保存和關(guān)閉文件,并撤銷對(duì)象。當(dāng)撤銷對(duì)象時(shí),能自動(dòng)釋放資源。釋放資源包括將對(duì)象中的信息再次存入磁盤文件。程序運(yùn)行中,總要對(duì)保存在對(duì)象的數(shù)據(jù)成員里的信息進(jìn)行操作,這時(shí)應(yīng)該
20、將信息適時(shí)保存到相應(yīng)的磁盤文件中,以免數(shù)據(jù)意外丟失。這些都是常規(guī)操作,是面向?qū)ο蟮腃+程序設(shè)計(jì)的固定框架。 規(guī)范化操作:在面向?qū)ο蟮某绦蛟O(shè)計(jì)中,信息總是放在對(duì)象的數(shù)據(jù)成員里。這些信息最終應(yīng)該保存到文件中。當(dāng)程序開始運(yùn)行時(shí)要由打開的文件重新創(chuàng)建對(duì)象。在運(yùn)行過程中,放在對(duì)象的數(shù)據(jù)成員里的信息得到利用和修改。運(yùn)行結(jié)束時(shí)必須把這些信息重新保存到文件中,然后關(guān)閉文件。9.6 文件與對(duì)象【例9.13】將商店的貨物,定義為一個(gè)貨物數(shù)組類。數(shù)組對(duì)象動(dòng)態(tài)建立,初始為2個(gè)元素,不夠用時(shí)擴(kuò)充一倍。用文本數(shù)據(jù)文件建立數(shù)組元素對(duì)象,要求放在構(gòu)造函數(shù)中,而數(shù)據(jù)的保存和文件的關(guān)閉放在析構(gòu)函數(shù)中。第一次運(yùn)行時(shí),建立空的數(shù)據(jù)文
21、件,由鍵盤輸入建立數(shù)組元素對(duì)象,并寫入文件,程序退出時(shí),關(guān)閉文件;下一次運(yùn)行由該文件構(gòu)造對(duì)象,恢復(fù)前一次做過的工作。這是一個(gè)標(biāo)準(zhǔn)的面向?qū)ο蟮某绦蛟O(shè)計(jì),也是對(duì)前面各章內(nèi)容的小結(jié)。注意,本例使用了多重的插入運(yùn)算符重載。 第九章 流類庫和輸入/輸出結(jié)束謝謝!9.2 輸入輸出的格式控制(選讀)訪問x_flags的重載函數(shù)聲明如下:inline long ios:flags() const; /返回當(dāng)前標(biāo)志字inline long ios:flags(long ); /把參數(shù)作為新的標(biāo)志字,并返回原標(biāo)志字(下同)inline long ios:setf(long ,long ); /在原標(biāo)志字上增加控制
22、, /第一個(gè)參數(shù)為增加的控制,第二個(gè)參數(shù)表示取代原來哪幾位inline long ios:setf(long ); /增加控制(多項(xiàng))inline long ios:unsetf(long ); /清除指定位上的控制9.2 輸入輸出的格式控制(選讀)相關(guān)接口函數(shù)為:inline int ios:width() const; /返回當(dāng)前域?qū)抜nline int ios:width(int ); /把參數(shù)作為新的域?qū)?返回原域?qū)抜nline char ios:fill() const; /返回當(dāng)前填充字符inline char ios:fill(char );/參數(shù)為新填充字符,返回原填充字符in
23、line int ios:precision(int ); /參數(shù)作為新精度,返回原精度inline int ios:precision() const; /返回當(dāng)前精度9.2 輸入輸出的格式控制(選讀)【例9.1】整型數(shù)輸出。#includeusing namespace std;int main(void)int inum=255;cout十進(jìn)制方式inumt;cout.flags(ios:oct|ios:showbase); /八進(jìn)制帶數(shù)制基輸出是前面加0;對(duì)VC+參數(shù)等效0 x00a0cout八進(jìn)制方式inumt;cout.setf(ios:hex,ios:basefield );/b
24、asefield代表控制 /進(jìn)位基制的三位ios:dec|ios:oct|ios:hex。 /因是或關(guān)系,仍帶基輸出,格式為0 x.cout十六進(jìn)制方式inumendl;return 0;程序輸出:十進(jìn)制方式255 八進(jìn)制方式0377 十六進(jìn)制方式0 xff9.2 輸入輸出的格式控制(選讀)【例9.2】浮點(diǎn)數(shù)輸出。int main()double fnum=31.415926535;cout默認(rèn)域?qū)挒?cout.width()位n; cout默認(rèn)精度為:cout.precision()位n; cout默認(rèn)表達(dá)方式:fnumn; /按值大小,自動(dòng)決定定點(diǎn)還是科學(xué)數(shù)方式cout.setf(ios:
25、scientific,ios:floatfield); cout科學(xué)數(shù)表達(dá)方式:fnumn;cout.setf(ios:fixed,ios:floatfield); /設(shè)為定點(diǎn),取消科學(xué)數(shù)方式cout定點(diǎn)表達(dá)方式:fnumn;cout.precision(9); /精度9位指小數(shù)點(diǎn)后9位cout.setf(ios:scientific,ios:floatfield); cout 9位科學(xué)數(shù)表達(dá)方式fnumn;return 0;其中floatfield代表浮點(diǎn)數(shù)的兩控制位ios:scientific|ios:fixed為了避免浮點(diǎn)數(shù)互相沖突的雙重規(guī)定,所以先清除原浮點(diǎn)數(shù)兩個(gè)輸出控制位,再用新的一
26、位去代替。9.2 輸入輸出的格式控制(選讀)流操作子(setiosflags stream manipulator)可代替流格式控制成員函數(shù)。它們的使用格式如第一章所介紹的setw()等使用的格式。注意,絕大多數(shù)流操作子僅適用于新的C+標(biāo)準(zhǔn)流類庫(頭文件不帶.h)。操作符含義boolapha把true和false表示為字符串*noboolalpha把true和false表示為0、1showbase產(chǎn)生前綴,指示數(shù)值的進(jìn)制基數(shù)*noshowbase不產(chǎn)生進(jìn)制基數(shù)前綴showpoint總是顯示小數(shù)點(diǎn)*noshowpoint只有當(dāng)小數(shù)部分存在是才顯示小數(shù)點(diǎn)操作符含義showpos在非負(fù)數(shù)值中顯示+*
27、noshowpos在非負(fù)數(shù)值中不顯示+*skipws輸入操作符跳過空白字符noskipws輸入操作符不跳過空白字符uppercase在十六進(jìn)制下顯示0X,科學(xué)計(jì)數(shù)法中顯示E*nouppercase在十六進(jìn)制下顯示0 x,科學(xué)計(jì)數(shù)法中顯示e*dec以十進(jìn)制顯示(VC支持)hex以十六進(jìn)制顯示(VC支持)oct以八進(jìn)制顯示(VC支持)left將填充字符加到數(shù)值的右邊right將填充字符加到數(shù)值的左邊internal將填充字符加到符號(hào)和數(shù)值的中間*fixed以小數(shù)形式顯示浮點(diǎn)數(shù)scientific以科學(xué)計(jì)數(shù)法形式顯示浮點(diǎn)數(shù)flush 刷新ostream緩沖區(qū)(VC支持)操作符含義ends插入字符串結(jié)
28、束符,刷新ostream緩沖區(qū)(VC支持)endl 插入換行符,然后刷新ostream緩沖區(qū)(VC支持)ws“吃掉”空白字符(VC支持)/以下這些參數(shù)化的流操作子要求#includesetfill(ch)用ch填充空白字符(VC支持)setprecision(n)將浮點(diǎn)精度設(shè)置為n (VC支持)setw(n) 按照n個(gè)字符來讀或者寫(VC支持)setbase(b)以進(jìn)制基數(shù)b為輸出整數(shù)值(VC支持)注:*表示默認(rèn)的流狀態(tài)cin,cout和clog都是緩沖流。對(duì)輸出而言,僅當(dāng)輸出緩沖區(qū)滿才將緩沖區(qū)中的信息輸出,對(duì)輸入而言,僅當(dāng)輸入一行結(jié)束,才開始從緩沖區(qū)中取數(shù)據(jù),當(dāng)希望把緩沖區(qū)中的信息立即輸出,
29、可用flush,加endl也有同樣功能,回車并立即顯示,不必等緩沖區(qū)滿(endl清空緩沖區(qū))。 9.2 輸入輸出的格式控制(選讀)【例9.2_1】采用流操作子的浮點(diǎn)數(shù)輸出。#include#includeusing namespace std;int main() double fnum=31.415926535; cout默認(rèn)域?qū)挒?cout.width()位n; cout默認(rèn)精度為:cout.precision()位n; cout默認(rèn)表達(dá)方式:fnumn; /按值大小,自動(dòng)決定定點(diǎn)還是科學(xué)數(shù)方式 cout科學(xué)數(shù)表達(dá)方式:scientificfnumn; /設(shè)為科學(xué)數(shù)方式 cout定點(diǎn)表達(dá)方
30、式:fixedfnumn; /設(shè)為定點(diǎn),取消科學(xué)數(shù)方式 cout9位科學(xué)數(shù)表達(dá)方式setprecision(9)scientificfnumn; return 0;讀取狀態(tài)的有關(guān)操作如下:inline int ios:rdstate() const return state; /讀取狀態(tài)字inline int ios:operator!() constreturn state&(badbit|failbit); /可用操作符!()代替fail()inline int ios:bad() return state & badbit; /返回非法操作位inline void ios:clear(i
31、nt _i) lock();state=_i;unlock(); /人工設(shè)置狀態(tài),可用來清狀態(tài)inline int ios:eof() const return state&eofbit; /返回流(文件)結(jié)束位inline int ios:fail() constreturn state&(badbit|failbit); /返回操作非法和操作失敗這兩位inline int ios:good() constreturn state=0; /正常返回1,否則返回09.3.1 提高標(biāo)準(zhǔn)輸入/輸出的穩(wěn)健性【例9.3】提高輸入的穩(wěn)健性。int main() char str256; int i; c
32、out請(qǐng)輸入整數(shù):i;/可故意輸入若干非數(shù)字字符,下次再輸入若干字符加數(shù)字串 /加若干非數(shù)字字符進(jìn)行檢測 while(cin.fail() cout狀態(tài)字為:cin.rdstate()endl; cin.clear(0); cin.getline(str,255); /讀空緩沖區(qū) cout輸入錯(cuò)誤,請(qǐng)重新輸入整數(shù)i; cin.getline(str,256); /讀空緩沖區(qū),吃掉回車符 cout請(qǐng)輸入字符串endl; cin.getline(str,255); cout輸入整數(shù)為:iendl; cout輸入字符串為:strendl; return 0;9.3.2 標(biāo)準(zhǔn)輸入/輸出成員函數(shù)(選讀)
33、【例9.4】ignore()和gcount()函數(shù)使用。int main() char str255; int i,n; cout輸入字符endl; /輸入Z,一旦輸入Z全部結(jié)束,不能輸入其它字符 i=cin.get(); coutendl; n=cin.rdstate(); /讀取狀態(tài)字 cout狀態(tài)字為:nendl; /狀態(tài)字為1,流結(jié)束 cout當(dāng)輸入字符時(shí),取得的是:iendl; /-1,輸入Z時(shí),返回EOF,即-1 if(n=0) cin.ignore(255,n); /清除多余的字符和回車符 cin.clear(0); / A 使流恢復(fù)正常 cout輸入字符串1:endl; cin
34、.getline(str,255); coutendl;9.3.2 標(biāo)準(zhǔn)輸入/輸出成員函數(shù)(選讀) cout狀態(tài)字為:cin.rdstate()endl; i=cin.gcount(); cout字符串為:strt讀入字符數(shù)為:it; cout串長為:strlen(str)endl; cin.clear(0); / A 使流恢復(fù)正常 cout輸入字符串2:endl; cin.getline(str,255); coutendl; cout狀態(tài)字為:cin.rdstate()endl; i=cin.gcount(); cout字符串為:strt讀入字符數(shù)為:it; cout串長為:strlen(
35、str)endl; return 0;注意,若無兩個(gè)A行,輸入Z后,不再理會(huì)余下的所有輸入。9.3.3 重載插入和提取運(yùn)算符【例9.5】改進(jìn)自定義字符串類,重載插入運(yùn)算符“”:重載插入運(yùn)算符“”聲明為mystring的友元:friend ostream & operator(ostream & ,const mystring &); /流類作為形式參數(shù)必須是引用定義為:ostream & operator(ostream & s,const mystring & cstr) return scstr.strt;本例中線性表Orderedlist的元素Node的數(shù)據(jù)域key類型由模板參數(shù)T決定,
36、實(shí)例化后為mystring,打印函數(shù)為:template void Orderedlist:print() int i; for(i=0;i=last;i+)coutslisti.key;if(i%5=4) coutendl; coutendl;更重要的是不用show()函數(shù),格式一致了,可以同時(shí)用于基本數(shù)據(jù)類型,如整型、實(shí)型、字符型,也可用于標(biāo)準(zhǔn)字符串string。【例9.6】用戶定義的復(fù)數(shù)類型Complex的輸入與輸出。#includeusing namespace std;class Complex double Real,Image;public: Complex(double r=0
37、.0, double i=0.0):Real(r),Image(i) /這里省略若干成員函數(shù),以節(jié)約篇幅,詳見【例4.7】 friend ostream&operator(istream&s,Complex&a); /流類作為形式參數(shù)必須是引用;ostream&operator(ostream&s,const Complex &z) return s(z.Real,z.Image(istream&s,Complex &a) /格式為d,(d),(d,d) double re=0,im=0; char c=0; sc; if(c=()/是否由括號(hào)開始 srec; /實(shí)部 if(c=,) simc
38、; /虛部 if(c!=) s.clear(ios:failbit); /漏了括號(hào)給一個(gè)操作失敗標(biāo)志 else s.putback(c); /無括號(hào),返回一個(gè)字符到輸入緩沖區(qū) sre; /實(shí)數(shù) if(s) a=Complex(re,im); /當(dāng)流s正常,給a賦值 return s;9.3.3 重載插入和提取運(yùn)算符putback()聲明如下:stream&istream:putback(char);它將最后一次從輸入流中得到的字符放回到輸入流中。int main()Complex a,b,c;cout輸入一個(gè)實(shí)數(shù)a;cout輸入一個(gè)用括號(hào)括起來的實(shí)數(shù)b;cout輸入一個(gè)用括號(hào)括起來復(fù)數(shù)c;co
39、uta=atb=bt c=cn;return 0;9.3 標(biāo)準(zhǔn)設(shè)備的輸入/輸出9.4.2 文本文件的讀寫【例9.7】復(fù)制文件。 int main() char ch; ifstream sfile(d:Ex9_6Ex9_6.cpp); ofstream dfile(e:Ex9_6.cpp); /只能創(chuàng)建文件,不能建立子目錄,如路徑不存在則失敗 if(!sfile) cout不能打開源文件:d:Ex9_6Ex9_6.cppendl; return -1; if(!dfile) cout不能打開目標(biāo)文件:e:Ex9_6.cppch)dfile”)運(yùn)算符在默認(rèn)情況下是跳過空白字符的,這樣復(fù)制的文件會(huì)
40、缺少一些字符。第二,該程序能確定文件是否復(fù)制結(jié)束。流類成員函數(shù)和運(yùn)算符全是返回本類型的引用,這里就是流文件對(duì)象自身,當(dāng)文件結(jié)束時(shí),返回NULL,這時(shí)不再復(fù)制,退出循環(huán)。第三,復(fù)制是按字節(jié)進(jìn)行的,效率很低,按字節(jié)傳遞開銷極大,但該程序能正確復(fù)制任意類型的文件,不僅是文本文件(看作按字符),二進(jìn)制文件(看作按字節(jié))也一樣可正確完成。如果是文本文件,我們可以按行進(jìn)行復(fù)制。第四,!sfile中的!是重載的運(yùn)算符,在狀態(tài)函數(shù)中重載,當(dāng)該操作出現(xiàn)不正常狀態(tài),返回操作非法和操作失敗這兩位 ?!纠?.8】按行復(fù)制文本文件。int main() char filename256,buf100; fstream
41、sfile,dfile; cout輸入源文件路徑名:filename; /對(duì)路徑名而言空格是無關(guān)緊要的,否則要用getline()等成員函數(shù) sfile.open(filename,ios:in);/打開一個(gè)已存在的文件 while(!sfile)cout源文件找不到,請(qǐng)重新輸入路徑名:filename;sfile.open(filename,ios:in); cout輸入目標(biāo)文件路徑名:filename; /只能創(chuàng)建文件,不能建立子目錄,如路徑不存在則失敗 dfile.open(filename,ios:out); if(!dfile) cout目標(biāo)文件創(chuàng)建失敗endl; return -1
42、; while(sfile.getline(buf,100),sfile.eof()!=1) /按行復(fù)制 A行 if(sfile.rdstate()=0) dfilebufn; /因讀到回車符,提取但未保存 B行 else dfile”完成重構(gòu)對(duì)象,而只用一個(gè)“”完成對(duì)象存入文件。 class inventory string Description; string No; int Quantity; double Cost; double Retail;public: inventory(string=#,string=0,int=0,double=0,double=0); friend o
43、stream&operator(istream&sour,inventory&iv); ; /流類作為形式參數(shù)必須是引用9.4.2 文本文件的讀寫inventory:inventory(string des,string no,int quan, double cost,double ret) Description=des; No=no; Quantity=quan; Cost=cost; Retail=ret;ostream &operator(ostream&dest,inventory&iv) destleftsetw(20)iv.Descriptionsetw(10)iv.No; d
44、estrightsetw(10)iv.Quantitysetw(10)iv.Cost setw(10)iv.Retail(istream&sour,inventory&iv) souriv.Descriptioniv.Noiv.Quantity iv.Costiv.Retail; return sour; /從文件讀出是自動(dòng)把數(shù)字串轉(zhuǎn)為數(shù)讀出,/函數(shù)體內(nèi)功能不變,會(huì)自動(dòng)轉(zhuǎn)換9.4.2 文本文件的讀寫int main() inventory car1(夏利2000,805637928,156,80000,105000),car2; inventory motor1(金城125,93612575,
45、302,10000,13000),motor2; ofstream destfile(d:Ex9_9.data); destfilecar1motor1; /注意ofstream是ostream的派生類 destfile.close(); coutcar1; coutmotor1; coutcar2; coutcar2motor2; sourfile.close(); coutcar2; cout和插入運(yùn)算符。void inventory:Bdatatofile(ofstream&dest)dest.write(Description.c_str(),20); /由string類的c_str(
46、)函數(shù)轉(zhuǎn)為char*dest.write(No.c_str(),10);dest.write(char*)&Quantity,sizeof(int);/注意指針類型dest.write(char*)&Cost,sizeof(double);/強(qiáng)制轉(zhuǎn)換dest.write(char*)&Retail,sizeof(double);9.4.3 二進(jìn)制文件的讀寫void inventory:Bdatafromfile(ifstream&sour)char k20;sour.read(k,20);Description=k;sour.read(k,10);No=k;sour.read(char*)&Q
47、uantity,sizeof(int);sour.read(char*)&Cost,sizeof(double);sour.read(char*)&Retail,sizeof(double); /讀和寫是完全對(duì)稱的過程,次序決不能錯(cuò)9.4.3 二進(jìn)制文件的讀寫int main() inventory car1(夏利2000,805637928,156,80000,105000),car2; inventory motor1(金城125,93612575,302,10000,13000),motor2; ofstream ddatafile(d:Ex9_10.data,ios:out|ios:b
48、inary); car1.Bdatatofile(ddatafile); motor1.Bdatatofile(ddatafile); cout對(duì)象car1:endl; coutcar1; cout對(duì)象motor1:endl; coutmotor1; cout對(duì)象car2:endl; coutcar2; cout對(duì)象motor2:endl; coutmotor2; ddatafile.close();9.4.3 二進(jìn)制文件的讀寫 ifstream sdatafile(d:Ex9_10.data,ios:in|ios:binary); /重新打開文件,從頭讀取數(shù)據(jù) car2.Bdatafromf
49、ile(sdatafile);/從文件讀取數(shù)據(jù)復(fù)制到對(duì)象car2 if(sdatafile.eof()=0) cout讀文件成功endl; cout對(duì)象car2:endl; coutcar2; motor2.Bdatafromfile(sdatafile); /繼續(xù)從文件讀取數(shù)據(jù)復(fù)制到對(duì)象motor2 if(sdatafile.eof()=0) cout讀文件成功endl; cout對(duì)象motor2:endl; coutmotor2; sdatafile.close(); return 0;9.4.4 文件的隨機(jī)訪問(選讀)【例9.11】使用隨機(jī)訪問對(duì)【例9.10】進(jìn)行改造。將入口(main(
50、))程序中的文件改為輸入輸出文件,寫完后將文件定位指針撥回文件開始處。對(duì)應(yīng)商品類中兩成員函數(shù),參數(shù)類型改為 fsream& : Bdatatofile(fstream&dest); Bdatafromfile(fstream&dest);主函數(shù)相關(guān)部分如下: fstream datafile(d:Ex9_11.data, ios:in|ios:out|ios:binary); /打開輸入輸出文件 car1.Bdatatofile(datafile); /保存對(duì)象 motor1.Bdatatofile(datafile); datafile.seekg(50,ios:beg); /一個(gè)記錄50字
51、節(jié) motor2.Bdatafromfile(datafile); /先重寫motor2 datafile.seekg(ios:beg); /指針回到開始 car2.Bdatafromfile(datafile); /后重寫car29.5 字符串流(選讀)【例9.12】int main() int i; char str36=This is a book.; char ch; istrstream input(str,36); /以串流為信息源 ostrstream output(str,36); cout字符串長度:strlen(str)endl; for(i=0;ich; /從輸入設(shè)備(串
52、)讀入一個(gè)字符,所有空白字符全跳過 coutch; /輸出字符 coutendl;9.5 字符串流(選讀) int inum1=93,inum2; double fnum1=89.5,fnum2; outputinum1 fnum10; /加空格分隔數(shù)字 cout字符串長度:strlen(str)inum2fnum2; cout整數(shù):inum2 t 浮點(diǎn)數(shù):fnum2endl; cout字符串長度:strlen(str)endl; return 0;例9.13 面向?qū)ο蟮腃+程序設(shè)計(jì)的固定框架 class inventory string Description; /商品名稱 string N
53、o; /貨號(hào) int Quantity; /數(shù)量 double Cost; /價(jià)格 double Retail; /零售public: inventory(string =#,string=#,int =0,double =0,double =0); friend ostream&operator(istream&sour,inventory&iv); bool operator=(inventory &); /貨號(hào)為關(guān)鍵字 bool operator=(inventory &);inventory:inventory(string des,string no,int quan, double cost,double ret) Description=des; No=no; Quantity=quan; Cost=cost; Retail=ret;ostream &operator(ostream&dest,inventory&iv) destleftsetw(20)iv.Descriptionsetw(10)iv.No; destrightsetw(10)iv.Quantitysetw(10)iv.Cost setw(10)iv.Retail(istream&sour,inventory&iv) if(sour
溫馨提示
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 衡水高二上數(shù)學(xué)試卷
- 衡陽市三年級(jí)數(shù)學(xué)試卷
- 貴州近五年中考數(shù)學(xué)試卷
- 2025年中國金絲楠木市場深度評(píng)估及行業(yè)投資前景咨詢報(bào)告
- 中國微波菱形盆行業(yè)市場發(fā)展前景及發(fā)展趨勢與投資戰(zhàn)略研究報(bào)告(2024-2030)
- 2025屆重慶市彭水一中高一物理第二學(xué)期期末復(fù)習(xí)檢測試題含解析
- 醫(yī)療美容監(jiān)督管理課件
- 落實(shí)董事會(huì)職權(quán)管理辦法
- 融媒體運(yùn)營中心管理辦法
- 衡陽縣人口管理辦法規(guī)定
- DB34∕T 3830-2021 裝配式建筑評(píng)價(jià)技術(shù)規(guī)范
- 武進(jìn)區(qū)橫山橋高級(jí)中學(xué)申報(bào)四星級(jí)高中自評(píng)報(bào)告
- RB/T 228-2023食品微生物定量檢測的測量不確定度評(píng)估指南
- 貴州省黔東南苗族侗族自治州(2024年-2025年小學(xué)二年級(jí)語文)人教版綜合練習(xí)試卷(含答案)
- 常見輸血不良反應(yīng)的診斷及處理精講課件
- 黑龍江省牡丹江市第十六中學(xué)2023-2024學(xué)年八年級(jí)下學(xué)期期末數(shù)學(xué)試題(原卷版)
- JB∕T 13026-2017 熱處理用油基淬火介質(zhì)
- 道路工程石材檢測報(bào)告及石材單軸抗壓強(qiáng)度檢測原始記錄
- 2024年俄羅斯?jié)窦埥砗蜐窠硇袠I(yè)應(yīng)用與市場潛力評(píng)估
- 正規(guī)挖機(jī)安全協(xié)議責(zé)任書
- 全屋定制直播間話術(shù)
評(píng)論
0/150
提交評(píng)論