版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、第八章第八章 c+ 的的 i/o 流庫(kù)流庫(kù)c+ 為什麼要建立自己的輸入輸出系統(tǒng)?1 c 雖然具有一個(gè)靈活和功能強(qiáng)大的輸入輸出系統(tǒng), 但它并不支持自定義類型。例如: class account char name30;double balance; public:account();account(char*, double); ; account acnt; scanf(“%account”, &acnt); / 錯(cuò)誤,不支持 account 類型 account acnt1(john, 3000.0); printf(“%account”, acnt1); / 錯(cuò)誤,不支持 account
2、類型 因?yàn)檩斎牒瘮?shù) scanf 和輸出函數(shù) printf 的格式串形參 只能與系統(tǒng)預(yù)定義類型匹配,而無(wú)法識(shí)別用戶的自 定義類型,并且也不能通過(guò)重載定義 scanf 和 printf 函數(shù)的新版本,使它們的格式串形參能匹配任意用 戶自定義類型。2 面向?qū)ο蟪绦蛟O(shè)計(jì)必須定義眾多的用戶自定義類, 如何以面向?qū)ο蟮脑O(shè)計(jì)原則和方法為自定義類設(shè)計(jì) 既規(guī)格統(tǒng)一,又適應(yīng)個(gè)性化的輸入輸出操作行為是 十分必要的。因此 c+ 必須建立一個(gè)能通過(guò)對(duì)輸入 輸出操作重載的方法實(shí)現(xiàn)對(duì)任意自定義類型對(duì)象輸 入輸出支持的系統(tǒng)。本章要點(diǎn)1 c+ 流庫(kù)結(jié)構(gòu)流庫(kù)結(jié)構(gòu)流庫(kù)的概念、流庫(kù)的組成。2 標(biāo)準(zhǔn)輸入輸出流輸入輸出流類的定義、輸入輸
3、出運(yùn)算符、輸入輸出的格式控制。3 自定義類的輸入輸出輸入輸出運(yùn)算符的重載。4 文件的輸入輸出流文件的打開、關(guān)閉和讀寫。5 使用 mfc 的對(duì)話框類實(shí)現(xiàn)輸入輸出8.1 c+ 流庫(kù)結(jié)構(gòu)流庫(kù)結(jié)構(gòu)8.1.1 流庫(kù)的概念流庫(kù)的概念 流(stream)是從源(數(shù)據(jù)的生產(chǎn)者)到目標(biāo)(數(shù)據(jù)的使用者)被傳輸數(shù)據(jù)的引用。每個(gè)流都是一個(gè)與某種數(shù)據(jù)傳輸設(shè)備相關(guān)聯(lián)的對(duì)象。流具有方向性:輸入流是與輸入設(shè)備(如鍵盤)關(guān)聯(lián)的流。輸出流是與輸出設(shè)備(如顯示器屏幕)關(guān)聯(lián)的流。輸入輸出流是與輸入輸出設(shè)備(如磁盤)關(guān)聯(lián)的流。c+ 中包含的預(yù)定義流:cin 輸入流,與輸入設(shè)備關(guān)聯(lián)。cout 輸出流,與輸出設(shè)備關(guān)聯(lián)。cerr 非緩沖型錯(cuò)
4、誤信息流,與錯(cuò)誤輸出設(shè)備關(guān)聯(lián);clog 緩沖型錯(cuò)誤信息流,與錯(cuò)誤輸出設(shè)備關(guān)聯(lián)。在缺省情況下,指定的輸入設(shè)備是控制臺(tái)鍵盤,輸出設(shè)備是控制臺(tái)顯示器終端。在任何情況下,指定的錯(cuò)誤輸出設(shè)備總是控制臺(tái)顯示器終端。 cin 和 cout 的使用方法我們已經(jīng)很熟悉了。cerr 和 clog 均是用來(lái)輸出錯(cuò)誤信息,它們的使用方法與 cout 基本相同,只不過(guò)它們所關(guān)聯(lián)的設(shè)備始終是控制臺(tái)顯示器,而不隨著 cout 關(guān)聯(lián)設(shè)備的改變而變化。cerr 和 clog 之間的區(qū)別是:cerr 對(duì)輸出的錯(cuò)誤信息不緩沖,因而發(fā)送給它的任何內(nèi) 容都立即輸出。clog 輸出的錯(cuò)誤信息被緩沖,當(dāng)緩沖區(qū)滿時(shí)才進(jìn)行輸 出,也可以通過(guò)刷
5、新流的方式(遇到操縱符 endl 或 flush)強(qiáng)迫刷新緩沖區(qū)導(dǎo)致顯示輸出。下面給出一段使用預(yù)定義輸入輸出流信息的程序: cout sales; cout num; if (num = 0) cerr the average can not be computed.n; else avgsales = sales / num;cout the average selling price per nuit was ;cout avgsales ”和“(signed char*);istream& operator (signed char&);istream& operator (int&);
6、 /對(duì)系統(tǒng)所有的預(yù)定義類型都給出了的重載定義。;class ostream:virtual public iospublic:ostream(streambuf*);/ 構(gòu)造函數(shù)ostream& flush(); / 輸出流刷新。ostream& seekp(streampos);/寫文件指針移到指定位置。ostream& seekp(streamoff, ios:seek_dir);/ 按指定方向和偏移量移動(dòng)文件指針到新位置。ostream& put(char); / 將指定字符輸出到流中。/ 將由char*指向的內(nèi)存空間的n個(gè)字符輸出到流中。ostream& write(const sig
7、ned char*, int);ostream& write(const unsigned char*, int);streampos tellp(); / 返回輸出流中當(dāng)前指針位置。/ 可重載的輸出運(yùn)算符ostream& operator (short);ostream& operator (int);ostream& operator (float); / 對(duì)系統(tǒng)所有的預(yù)定義類型都給出了 的重載定義。;8.2.2 輸入輸出運(yùn)算符的使用輸入輸出運(yùn)算符的使用8.2.3 格式控制的輸入輸出格式控制的輸入輸出輸入輸出的格式控制可以使得人機(jī)交互界面更加友好、美觀。在 c 程序中,輸入輸出是使用 c
8、運(yùn)行庫(kù)的 scanf 和 printf 函數(shù)完成的,輸入輸出的格式是通過(guò)這兩個(gè)函數(shù)的格式描述串參數(shù)控制的。在 c+ 程序中,雖仍然可以使用 scanf 和 printf 函數(shù),但在面向?qū)ο蟮某绦蛟O(shè)計(jì)中,輸入輸出是使用流類庫(kù)中的輸入輸出流完成的,因此輸入輸出的格式控制必須使用流類庫(kù)提供的格式控制的方法: ; 。1 用 ios 類成員函數(shù)進(jìn)行輸入輸出格式化 ios 類提供了用于輸入輸出格式控制的成員函數(shù)。 這些函數(shù)進(jìn)行格式控制的方法是修改以下屬性: 格式標(biāo)志屬性 x_flags:標(biāo)志的不同狀態(tài)值指定輸入輸出數(shù)據(jù)的不同格式(如對(duì)齊規(guī)則、數(shù)值轉(zhuǎn)換基、數(shù)字表示規(guī)則等)。 輸出域?qū)拰傩?x_width:
9、指定輸出數(shù)據(jù)所占顯示區(qū)域的寬度。 填充字符屬性 x_fill:指定輸出顯示域中數(shù)據(jù)為占空間的填充字符; 輸出精度屬性 x_precision:指定浮點(diǎn)數(shù)輸出的小數(shù)部分顯示位數(shù)。 格式標(biāo)志c+ 中每個(gè)流對(duì)象的輸入輸出格式都是依據(jù)指定格式進(jìn)行的,也就是說(shuō),流對(duì)象的每次輸入“” 操作是按照當(dāng)前格式標(biāo)志 x_flags 中的格式狀態(tài)完成的。該屬性是一個(gè) protected 成員,在類外訪問(wèn)該屬性是通過(guò)公有的格式控制成員函數(shù)實(shí)現(xiàn)的。注意,該屬性可以在 ios 的派生類內(nèi)被訪問(wèn)。為了便于提供格式控制成員函數(shù)的參數(shù)和參數(shù)具有良好的可讀性,ios 類定義了一個(gè)公有的無(wú)名枚舉數(shù)據(jù)成員,用戶可以使用這些特定的枚舉
10、元素,形成所需要的格式狀態(tài)傳遞給相應(yīng)的格式控制成員函數(shù)。class _crtimp ios public:enum skipws = 0 x0001, / 跳過(guò)輸入中的空白,用于輸入 left = 0 x0002, / 左對(duì)齊輸出,用于輸出 right = 0 x0004, / 右對(duì)齊輸出,用于輸出 internal = 0 x0008, / 符號(hào)或基數(shù)指示符與數(shù)字之間添加填充符,用于輸出 dec = 0 x0010, / 基數(shù)為 10 進(jìn)制,用于輸入輸出 oct = 0 x0020, / 基數(shù)為 8 進(jìn)制,用于輸入輸出 hex = 0 x0040, / 基數(shù)為 16 進(jìn)制,用于輸入輸出 sh
11、owbase = 0 x0080, / 顯示基數(shù)指示符,用于輸出 showpoint = 0 x0100, / 顯示小數(shù)點(diǎn),用于輸出 uppercase = 0 x0200, / 16 進(jìn)制輸出時(shí),數(shù)基指示符和/ 數(shù)值中的字母一律為大寫,用于輸出 showpos = 0 x0400, / 正數(shù)前顯示+符號(hào),用于輸出 scientific = 0 x0800, / 科學(xué)表示法浮點(diǎn)數(shù),用于輸出 fixed = 0 x1000, / 定點(diǎn)形式顯示浮點(diǎn)數(shù),用于輸出 unitbuf = 0 x2000, /輸出后立即刷新流,用于輸出。 stdio = 0 x4000, / 刷新 stdout 和 std
12、err,用于輸出。;inline long flags() const; / 返回當(dāng)前格式標(biāo)志。inline long flags(long _l);/ 設(shè)置指定格式 _l,返回原有格式。 inline long setf(long _f, long _m); / 依據(jù)掩碼 _m 設(shè)置指定格式 _f,返回原有格式。inline long unsetf(long _l);/ 清除指定格式 _l,并返回原有標(biāo)志。 inline int width() const;/ 返回當(dāng)前域?qū)捴怠?inline int width(int _i);/ 設(shè)置指定域?qū)?_i,并返回原有域?qū)捴?。inline ostr
13、eam* tie(ostream* _os); / 將流連接到_os 指向輸出流,并返回原來(lái)的流指針。 inline ostream* tie() const;/ 返回原來(lái)的流指針。inline fill() const; / 返回當(dāng)前填充字符。inline char fill(char _c); / 設(shè)置指定填充字符,并返回原有填充字符。 inline int precision(int _i);/ 設(shè)置指定浮點(diǎn)數(shù)精度,并返回原有浮點(diǎn)數(shù)精度。 inline int precision() const;/ 返回當(dāng)前的浮點(diǎn)數(shù)精度。 inline int rdstate() const;/ 返回當(dāng)
14、前的錯(cuò)誤狀態(tài)。 inline void clear(int _i = 0);/ 根據(jù)掩碼 _i 設(shè)置或清除錯(cuò)誤狀態(tài)位。protected: long x_flags; int x_precision; char x_fill;int x_width;格式枚舉元素值有一個(gè)共同的特點(diǎn),即使用不同位為 1 二進(jìn)制數(shù)表示不同的格式值,也就是說(shuō),枚舉元素值的二進(jìn)制表示只有一位為 1。例如:skipws0 x0001: 0000 0000 0000 0001left0 x0002: 0000 0000 0000 0010right0 x0004: 0000 0000 0000 0100顯然,所需要的特定格
15、式標(biāo)志將可以是一個(gè)枚舉元素值或幾個(gè)的枚舉元素進(jìn)行或運(yùn)算組合而成,例如,欲設(shè)置左對(duì)齊 10 進(jìn)制科學(xué)表示法顯示浮點(diǎn)數(shù)的輸出格式,則格式標(biāo)志可以通過(guò)ios:left | ios:dec | ios:scientific得到,16 進(jìn)制值為 0 x0812,10 進(jìn)制值為 2066。 用成員函數(shù)對(duì)格式標(biāo)志進(jìn)行操作 置格式標(biāo)志 所謂設(shè)置格式標(biāo)志是將格式屬性 x_flags 的某 一位置1,使該位所對(duì)應(yīng)的格式標(biāo)志有效。設(shè) 置格式標(biāo)志的成員函數(shù)是 setf,調(diào)用該成員函 數(shù)的一般形式為: 例如:istream isobj;ostream osobj;isobj.setf(ios:skipws);osobj
16、.setf(ios:left); 注意: isobj 和 osobj 為 istream 和 ostream 的用戶定 義對(duì)象。在編程中使用最多的是通過(guò)系統(tǒng)預(yù) 定義流對(duì)象設(shè)置格式,例如:cin.setf(ios:skipws);cout.setf(ios:left); 所設(shè)置的格式標(biāo)志不改變格式屬性 x_flags 的 原有的有效位,即在原有基礎(chǔ)上追加設(shè)置。 例如,原來(lái)的狀態(tài)標(biāo)志字為:0 x0011: 0000 0000 0001 0001 執(zhí)行 cout.setf(ios:left) 后, x_flags 的值變?yōu)椋? x0013: 0000 0000 0001 0011 例如:#inclu
17、de main() cout.setf(ios:showpos | ios:scientific); cout 567 567.89 endl; 程序執(zhí)行結(jié)果:+567 +5.6789e02 清除格式標(biāo)志 與設(shè)置格式標(biāo)志操作相反,是將格式屬性 x_flags 的某一位清 0,使該位所對(duì)應(yīng)的格式特 性失效。清除格式的成員函數(shù)是 unsetf,調(diào)用 該成員函數(shù)的一般形式為: 注意:與設(shè)置格式標(biāo)志相似,所清除的格式標(biāo) 志只是使保存在 x_flags 中的當(dāng)前格式屬性的 相應(yīng)位失效,而不改變格式屬性其余的有效 位。例如,原格式屬性為:0 x0013: 0000 0000 0001 0011 執(zhí)行 co
18、ut.unsetf(ios:left) 后,x_flags 的值變?yōu)椋? x0011: 0000 0000 0001 0001 取狀態(tài)屬性 取出保存在 x_flags 中的格式屬性。完成這一 操作的成員函數(shù) flags,該函數(shù)有兩個(gè)重載版 本,調(diào)用它們的格式有兩種:long flags();long flags(long flags); 前一種形式用于返回當(dāng)前格式屬性;后一種是 不僅將當(dāng)前格式屬性返回,并且將格式屬性設(shè) 置為指定值 flags。 注意,帶有參數(shù)的成員函數(shù) flags 與成員函數(shù) setf 不同,它對(duì)格式屬性的修改是覆蓋原值, 而不是在原值的基礎(chǔ)上追加設(shè)置。例如: #includ
19、e void showflags(long f)/ 顯示二進(jìn)制形式的狀態(tài)字 long i; for (i = 0 x8000; i; i = i 1) if (i & f)cout 1; elsecout 0;cout endl; main() long f = cout.flags();showflags(f); cout.setf(ios:showpos | ios:scientific); f = cout.flags(); showflags(f); cout.unsetf(ios:scientific); f = cout.flags(); showflags(f); f = cou
20、t.flags(ios:oct);showflags(f); f = cout.flags(); showflags(f); return 1; 程序執(zhí)行結(jié)果:0000000000000000 0000110000000000 0000010000000000 0000010000000000 0000000000100000 分析程序的執(zhí)行結(jié)果,可以清楚地看到格式屬 性值的變化情況。 設(shè)置域?qū)?域?qū)捴饕脕?lái)控制一個(gè)數(shù)據(jù)輸出時(shí)所占顯示區(qū) 域的寬度,在 ios 類中,域?qū)挻娣旁诒Wo(hù)類數(shù) 據(jù)成員 x_width 中。設(shè)置域?qū)挼某蓡T函數(shù)有兩 個(gè),調(diào)用它們的一般形式為: 第一種形式只用來(lái)返回當(dāng)前的域?qū)?/p>
21、值,后者用 來(lái)設(shè)置指定域?qū)?,并返回原?lái)的域?qū)捴怠?設(shè)置顯示的精度 在 ios 類中,控制浮點(diǎn)數(shù)顯示精度位數(shù)是被保 存在保護(hù)類數(shù)據(jù)成員 x_precision 中的。設(shè)置顯 示精度的成員函數(shù)有兩個(gè),調(diào)用它們的一般形 式為: 第一種形式只用來(lái)返回當(dāng)前的顯示精度,后者 用來(lái)重新設(shè)置顯示精度,并返回原來(lái)的顯示精 度。 設(shè)置填充字符 填充字符的作用是:當(dāng)輸出數(shù)據(jù)的長(zhǎng)度小于顯 示域?qū)挄r(shí),用填充字符來(lái)填充顯示域?qū)捴袛?shù)據(jù) 未占滿的空間。缺省情況下填充字符為空格。 如果輸出數(shù)據(jù)的長(zhǎng)度大于域?qū)挄r(shí),則填充字符 是沒(méi)有意義的。因此,在使用填充字符時(shí),必 須考慮與 width 函數(shù)相配合。在 ios 類中,填 充字符被
22、保存在保護(hù)類數(shù)據(jù)成員 x_fill 中的。 設(shè)置填充字符的成員函數(shù)有兩個(gè),調(diào)用它們的 一般形式為: 第一種形式用來(lái)返回當(dāng)前的填充字符,后者用 來(lái)重新設(shè)置填充字符,并返回原有的填充字 符。例如:#include main() cout x_width = cout.width() endl; cout x_fill = cout.fill() endl; cout x_precision = cout.precision() endl; cout 123 123.45678 endl; cout -n; cout * x_width = 10, x_fill = , x_precision =
23、8 *n; cout.width(10); cout.precision(8); cout 123 123.45678 234.567 endl; cout x_width = cout.width() endl; cout x_fill = cout.fill() endl; cout x_precision = cout.precision() endl; cout -n; cout * x_width = 10, x_fill = &, x_precision = 8 *n; cout.fill(&); cout.width(10); cout 123 123.45678 endl; c
24、out.setf(ios:left); cout.width(10); cout 123 123.45678 endl; cout x_width = cout.width() endl; cout x_fill = cout.fill() endl; cout x_precision = cout.precision() endl; return 1; 程序執(zhí)行結(jié)果:x_width = 0 x_fill =x_precision = 6123 123.457- * x_width = 10, x_fill = , x_precision = 8 * 123 123.45678 234.567
25、x_width = 0 x_fill =x_precision = 8-* x_width = 10, x_fill = &, x_precision = 8 *&123 123.45678123& 123.45678x_width = 0 x_fill = &x_precision = 8分析程序的執(zhí)行結(jié)果,有幾點(diǎn)需要注意: 在缺省情況下,x_width 的值為 0,即無(wú)域 寬,這種情況下輸出數(shù)據(jù)按自身的寬度顯示; x_fill 的值為空格;x_precision 值為 6,因此, 浮點(diǎn)小數(shù) 123.45678 只被顯示了 6 位,并且被 四舍五入。 用 width 函數(shù)設(shè)置的域?qū)捴粚?duì)緊跟它
26、的數(shù)據(jù)輸 出起作用,隨后 x_width 立即自動(dòng)置為0。而用 precision 函數(shù)設(shè)置了 x_precision 和用 fill 函數(shù)設(shè) 置了 x_fill 后,將一直有效,直至它們被重新 設(shè)置。 當(dāng)設(shè)置了 x_precision 后,若實(shí)際輸出數(shù)據(jù)的精 度與其不一致時(shí),將遵循如下的規(guī)則: 當(dāng)實(shí)際輸出的浮點(diǎn)數(shù)位大于 x_precision 時(shí), 則以 x_precision 的位數(shù)按四舍五入輸出; 當(dāng)實(shí)際輸出的浮點(diǎn)數(shù)位小于 x_precision 時(shí), 則按實(shí)際的小數(shù)位數(shù)輸出; 當(dāng) x_precision 為 0 時(shí),x_precision 將被缺省 設(shè)置為 1。 當(dāng)顯示數(shù)據(jù)所需要的寬度
27、比所設(shè)置的域?qū)捫?時(shí),數(shù)據(jù)未占的顯示域部分用填充字符來(lái)填 充,缺省的填充字符為空格。字符的填充位 置由 ios:left 和 ios:right 確定。 使用 ios 的成員函數(shù)控制輸出格式顯示一個(gè)平方根和平方表。2 使用操縱函數(shù)(符)進(jìn)行格式化控制 不難發(fā)現(xiàn),如果希望使用格式成員函數(shù)控制輸入輸 出格式,而不輸出這些成員函數(shù)的返回值時(shí),則函 數(shù)的調(diào)用表達(dá)式必須是一條單獨(dú)的語(yǔ)句,而不能嵌 入到輸入輸出流表達(dá)式中去。c+ 流類庫(kù)提供了另 一種進(jìn)行輸入輸出控制的方法,這種方法使用一種 被稱為操縱符的特殊類外函數(shù)。由于對(duì)操縱符的調(diào) 用表達(dá)式可以嵌入到輸入輸出流表達(dá)式中,所以用 操縱符控制格式比用格式成
28、員函數(shù)更方便。 流類庫(kù)中預(yù)定義的操縱符操縱符是一個(gè)特殊類外函數(shù),該函數(shù)是以一個(gè)“流引用” 作為參數(shù)并將由參數(shù)傳遞來(lái)的 “流引用” 作為函數(shù)的返回。操縱符的一般原型為:可以認(rèn)為操縱符作用是將一個(gè)輸入流或輸出流經(jīng)過(guò)指定的格式處理后又傳遞給下一個(gè)需要對(duì)輸入流或輸出流進(jìn)行的操作。因此操縱符像一個(gè)起到“接力” 作用的 “運(yùn)算符”,可以被嵌入到輸入輸出流表達(dá)式中。預(yù)定義操縱算子如下表所示:操縱符 含義 dechexoctwsendlendsflushresetiosflags(long f)setiosflags(long f)setfill(int c)setprecision(int n)setw(i
29、nt n) 設(shè)置轉(zhuǎn)換基數(shù)為 10 進(jìn)制,可用于輸入和輸出。設(shè)置轉(zhuǎn)換基數(shù)為 16 進(jìn)制,可用于輸入和輸出。設(shè)置轉(zhuǎn)換基數(shù)為 8 進(jìn)制,可用于輸入和輸出。用于在輸入時(shí)跳過(guò)開頭的空白符,僅用于輸入。插入一新行并刷新流,僅用于輸出。插入一個(gè) null 字符,僅用于輸出。刷新輸出流。清除由 f 說(shuō)明的格式,可用于輸入和輸出。設(shè)置由 f 說(shuō)明的格式,可用于輸入和輸出。設(shè)置充填字符 c,可用于輸入和輸出。設(shè)置浮點(diǎn)數(shù)精度為 n,可用于輸入和輸出。設(shè)置域?qū)挒?n,可用于輸入和輸出。 操縱符分別被定義在頭文件 ios.h、istream.h、 ostream.h 和 iomanip.h 中: inline _crt
30、imp ios& _cdecl dec(ios& _strm) _strm.setf(ios:dec,ios:basefield); return _strm; inline _crtimp ios& _cdecl hex(ios& _strm) _strm.setf(ios:hex,ios:basefield); return _strm; inline _crtimp ios& _cdecl oct(ios& _strm) _strm.setf(ios:oct,ios:basefield); return _strm; inline _crtimp istream& _cdecl ws(i
31、stream& _ins) _ins.eatwhite(); return _ins; inline _crtimp ostream& _cdecl endl(ostream& _outs) return _outs n flush; inline _crtimp ostream& _cdecl ends(ostream& _outs) return _outs ” 和輸出運(yùn)算符 “是流類 istream 的成員運(yùn)算符函數(shù),它在類說(shuō)明中被說(shuō)明為:class _crtimp istream : virtual public ios public: inline istream& operator
32、(istream& (_cdecl * _f)(istream&); inline istream& operator(ios& (_cdecl * _f)(ios&); istream& operator(char *); inline istream& operator(unsigned char *); inline istream& operator(signed char *); istream& operator(char &); inline istream& operator(unsigned char &); inline istream& operator(signed c
33、har &); istream& operator(short &); istream& operator(unsigned short &); istream& operator(int &); istream& operator(unsigned int &); istream& operator(long &); istream& operator(unsigned long &); istream& operator(float &); istream& operator(double &); istream& operator(long double &); istream& ope
34、rator(streambuf*); ; 顯然,“” 的眾多重載定義是為了滿足輸入各種預(yù)定義類型數(shù)據(jù)和控制的需要。這些重載函數(shù)的共同點(diǎn)是返回類型和缺省的左操作數(shù)均為輸入流的引用 istream&,而不同點(diǎn)是它們的右操作數(shù)各異,其中以 ios& 和 istream& 為右操作數(shù)的重載版本是用于控制輸入格式。而 “” 是流類 ostream 的成員運(yùn)算符函數(shù),它在類說(shuō)明中被說(shuō)明為:class _crtimp ostream : virtual public iospublic: inline ostream& operator(ostream& (_cdecl * _f)(ostream&); i
35、nline ostream& operator(ios&(_cdecl * _f)(ios&); ostream& operator(const char *); inline ostream& operator(const unsigned char *); inline ostream& operator(const signed char *); inline ostream& operator(char); ostream& operator(unsigned char); inline ostream& operator(signed char); ostream& operator
36、(short); ostream& operator(unsigned short); ostream& operator(int); ostream& operator(unsigned int); ostream& operator(long); ostream& operator(unsigned long); inline ostream& operator(float); ostream& operator(double); ostream& operator(long double); ostream& operator(const void *); ostream& operat
37、or(streambuf*); ;同樣,“重載版本或用于輸出格式控制 “” 或 “” 或 “” 或 “” ,使后續(xù)執(zhí)行的輸入或輸出操作受到所設(shè)置格式的控制。下面再通過(guò)兩個(gè)實(shí)例來(lái)進(jìn)一步理解操縱符的使用。#include main() cout setw(10) 123 567 endl; cout 123 setiosflags(ios:scientific) setw(20) 123.456789 endl; cout 123 setw(10) hex 123 endl; cout 123 setw(10) oct 123 endl; cout 123 setw(10) dec 123 end
38、l; cout resetiosflags(ios:scientific) setprecision(4) 123.456789 endl; cout setiosflags(ios:left) setfill(#) setw(8) 123 endl; cout resetiosflags(ios:left) setfill(&) setw(8) 456 endl; return 1;程序執(zhí)行結(jié)果:123567123 1.234568e+002123 7b7b 173173 123123.5123#&456分析程序執(zhí)行結(jié)果,有兩點(diǎn)需要注意: 操縱算子 setw 與 ios:width 相似,它
39、的作用是 一次性的,即只對(duì)最近的下一次輸出起作用。 此程序中的小數(shù)為浮點(diǎn)數(shù)表示,如果將小數(shù) 的表示設(shè)置為定點(diǎn)表示,則會(huì)使科學(xué)計(jì)數(shù)表示 法失效。 顯示 1 20 的二次方表與二次方根表程序的另一個(gè)版本。這一版本中使用輸入輸出操縱算子代替 ios 類的格式控制成員函數(shù)。 用戶自定義的操縱符c+ 流類庫(kù)除了提供預(yù)定義的操縱符外,也允許用戶利用操縱符的定義機(jī)制自定義操縱符。至此,我們應(yīng)該已經(jīng)深深地感覺(jué)到 c+ 系統(tǒng)自身的許多實(shí)現(xiàn)機(jī)制常??梢员挥脩羰褂茫?c+ 的使用者有一種與系統(tǒng)融合的感受。 用戶自定義操縱符的目的往往是歸納程序中頻繁使用的輸入輸出格式操作,提高輸入輸出代碼的重用度,程序的可讀性和可
40、維護(hù)性。建立自定義操縱符的方法:若為輸出流定義操縱符函數(shù),則定義形式如下:ostream& manip_name(ostream& stream)輸出格式控制代碼return stream;若為輸入流定義操縱符函數(shù),則定義形式如下:istream& manip_name(istream& stream) 輸入格式控制代碼return stream;例如:#include ostream& output (ostream& out) out.setf(ios:left);out setw(10) hex setiosflags(ios:uppercase);return out;int main
41、() cout 123 endl;cout output 123 endl;return 1;程序執(zhí)行結(jié)果:1237b又例如:#include istream& input (istream& in) in hex;cout input i;cout i output i (又稱為流的提取運(yùn)算符)和輸出運(yùn)算符 和輸出運(yùn)算符 或 和 輸入運(yùn)算符 是輸入流類(將在第八章中詳細(xì)講述)的成員函數(shù)。該運(yùn)算符也是一個(gè)雙目運(yùn)算符,它的左操作數(shù)必須是輸入流類對(duì)象的引用,表示被輸入的信息必須來(lái)自標(biāo)準(zhǔn)的輸入流設(shè)備;而右操作數(shù)是接收輸入信息的指定類對(duì)象的引用。因此,為自定義類重載的輸入運(yùn)算符函數(shù)只能是類成員函數(shù)。1
42、 原型 friend 輸入流類& operator (輸入流類&, 類名&); 例如: class point int x, y; public:friend istream& operator (istream&, point&); ;2 定義 輸入流& operator (輸入流& 流對(duì)象名, 類名& 對(duì)象名) return 流對(duì)象名; 例如: istream& operator (istream& in, point& pt); cout pt.x pt.y;return in; 3 調(diào)用 cin 類對(duì)象名; 例如: point pt; cin pt;注意: 輸入運(yùn)算符重載函數(shù)的第一個(gè)參
43、數(shù)的類型必須是輸 入流類 istream 對(duì)象的引用,形參名(流對(duì)象名)可 以使用任何合法的標(biāo)識(shí)符。 輸入運(yùn)算符重載函數(shù)的第二個(gè)參數(shù)的類型必須是接 收輸入信息的指定類對(duì)象的引用,例如 point&, 而 不能使用指定類名,例如 point。 輸入運(yùn)算符重載函數(shù)的返回類型必須是輸入流類 istream 對(duì)象的引用,并且在函數(shù)體中由 return 返回 的輸入流類對(duì)象的引用名必須與第一個(gè)參數(shù)的形參 名(流對(duì)象名)一致。8.3.2 重載輸出運(yùn)算符重載輸出運(yùn)算符 輸出運(yùn)算符 是輸出流類(將在第八章中詳細(xì)講述)的成員函數(shù)。該運(yùn)算符也是一個(gè)雙目運(yùn)算符,它的左操作數(shù)必須是輸出流類對(duì)象的引用,表示信息必須被輸
44、出到標(biāo)準(zhǔn)的輸出流設(shè)備;而右操作數(shù)是輸出信息的指定類對(duì)象。因此,為自定義類重載的輸入運(yùn)算符函數(shù)也只能是類成員函數(shù)。1 原型 friend 輸出流類& operator (istream&, point&); friend ostream& operator (ostream&, point&); ;2 定義 輸出流& operator (輸出流& 流對(duì)象名, 類名 對(duì)象名) return 流對(duì)象名; 例如: ostream& operator (ostream& out, point pt); out “point 對(duì)象的坐標(biāo) x 和 y:”;out pt.x “,” pt.y endl;ret
45、urn out; 3 調(diào)用 cout pt; cout 和輸出運(yùn)算符 和輸出運(yùn)算符 進(jìn)行了重載,使它們能對(duì)按照指定形式(例如由分子分母組成的分?jǐn)?shù)形式,3/8)表示的有理數(shù)進(jìn)行標(biāo)準(zhǔn)輸入輸出操作。返回8.4 文件的輸入輸出流文件的輸入輸出流 文件一般是指存儲(chǔ)在計(jì)算機(jī)的外部介質(zhì)(磁盤、光盤、u盤等)上,按指定的結(jié)構(gòu)組織起來(lái)的數(shù)據(jù)集合。操作系統(tǒng)就是以文件為單位對(duì)數(shù)據(jù)進(jìn)行管理的。對(duì)文件的輸入輸出操作是程序設(shè)計(jì)的重要概念,是數(shù)據(jù)輸入輸出流的又一重要形式。因此,c+ 的流類庫(kù)把文件也按照字節(jié)序列對(duì)待和處理,但組成文件的字節(jié)在不同類型的文件中具有不同的含義,例如:它們可以是字母、符號(hào),也可能是數(shù)值。根據(jù)文件所
46、保存的數(shù)據(jù)組織形式,文件可以分為兩類:1 文本文件:又稱為 ascii 文件,這類文件中的每個(gè) 字節(jié)中存放一個(gè) ascii 代碼,其含義一個(gè)字符。因 此,如果數(shù)據(jù)在內(nèi)存中存放形式是 ascii 代碼,則 這樣的數(shù)據(jù)無(wú)論是輸出到文本文件還是從文本文件 輸入都不需要進(jìn)行任何變換;但如果數(shù)據(jù)在內(nèi)存中 存放形式是二進(jìn)制數(shù),則這樣的數(shù)據(jù)輸出到文本文 件時(shí)必須先變換為 ascii 代碼,而從文件輸入時(shí)必 須先變換為二進(jìn)制數(shù)。例如整數(shù) 100000(0 x186a0) 在內(nèi)存中(二進(jìn)制數(shù))和文本文件中的存放形式:00000000 00000001 10000110 10100000內(nèi)存(二進(jìn)制數(shù))00110
47、001 00110000 00110000 00110000 00110000 00110000文本文件 顯然,這樣的輸出過(guò)程和數(shù)據(jù)表示形式的轉(zhuǎn)換與內(nèi) 存中的二進(jìn)制數(shù)據(jù)輸出到控制臺(tái)顯示器是一致的, 即先將二進(jìn)制數(shù)據(jù)轉(zhuǎn)換為 ascii 代碼,在傳送到顯 示器的顯示存儲(chǔ)中,從而得以在顯示器屏幕上以字 符形式顯示輸出。而輸入過(guò)程和數(shù)據(jù)表示形式的轉(zhuǎn) 換與從控制臺(tái)鍵盤輸入數(shù)據(jù),并以二進(jìn)制形式存放 到內(nèi)存是一致的,即先將鍵盤輸入產(chǎn)生的 ascii 代 碼轉(zhuǎn)換為二進(jìn)制形式后,傳送到指定內(nèi)存單元中。 使用文本文件存放和處理數(shù)據(jù)的特點(diǎn): 優(yōu)點(diǎn):直觀、方便、可讀。 缺點(diǎn):占用空間多,數(shù)據(jù)轉(zhuǎn)換開銷大。2 二進(jìn)制文件
48、:這類文件中的每個(gè)字節(jié)存放二進(jìn)制數(shù) 據(jù)字節(jié),其含義視數(shù)據(jù)表示的內(nèi)容(文本字符、計(jì) 算數(shù)據(jù)值、圖象象素值等)而定。因此,無(wú)論數(shù)據(jù) 在內(nèi)存以何種形式存放,輸入輸出到二進(jìn)制文件中 的存放形式都保持不變,即無(wú)須進(jìn)行任何轉(zhuǎn)換。例 如,同樣是整數(shù) 100000(0 x186a0)在內(nèi)存中(二進(jìn) 制數(shù))和二進(jìn)制文件中的存放形式: 使用二進(jìn)制文件存放和處理數(shù)據(jù)的特點(diǎn): 優(yōu)點(diǎn):占用空間少,無(wú)數(shù)據(jù)轉(zhuǎn)換開銷,保密性好。 缺點(diǎn):不直觀,不方便,不可讀。00000000 00000001 10000110 10100000內(nèi)存(二進(jìn)制數(shù))00000000 00000001 10000110 10100000文本文件 無(wú)
49、論是文本文件還是二進(jìn)制文件,總可以把存放在文件中數(shù)據(jù)看作是一連串的字節(jié)記錄,而不考慮記錄的界限,對(duì)文件的存取都是以字節(jié)為單位進(jìn)行的。我們把這種文件成為流式文件。 對(duì)一個(gè)流式文件進(jìn)行存取操作之前,必須首先創(chuàng)建一個(gè)流,然后建立流與文件的關(guān)聯(lián),即打開文件,完成流的插入或提取操作后,關(guān)閉這個(gè)文件,即解除流與文件的關(guān)聯(lián)。8.4.1 文件的打開與關(guān)閉文件的打開與關(guān)閉 所謂 “打開” 文件就是一個(gè)文件與一個(gè)流建立關(guān)聯(lián)。只有一個(gè)打開的文件才能夠通過(guò)流對(duì)其進(jìn)行輸入輸出操作。為了執(zhí)行對(duì)文件的輸入輸出操作,c+ 流類庫(kù)中有三個(gè)提供了文件讀寫操作的流類名稱基類功能ofstreamifstreamfstream ost
50、reamistreamiostream 用于文件輸出用于文件輸入用于文件輸入或輸出 從它們的類派生層次中可以看出:根基類 ios 和 istream 或 ostream 中定義的操作在這三個(gè)相應(yīng)的派生流類中均可以使用。這三個(gè)類被定義在頭文件 fstream.h 中。執(zhí)行文件輸入輸出,必須做以下三件事:在程序中必須包含系統(tǒng)頭文件 fstream.h。建立流 創(chuàng)建文件流類的對(duì)象,例如: ifstream in;/ 輸入流對(duì)象 ofstream out;/ 輸出流對(duì)象 fstream io;/ 輸入輸出流對(duì)象使用文件流類的成員函數(shù) open 打開文件,也就是使某一個(gè)文件與指定流相關(guān)聯(lián)。open 的原
51、型: void open( const char* szname, int mode, int nprot = filebuf:openprot ); 其中三個(gè)參數(shù)分別為: 1 文件名:字符串常量 szname 用來(lái)傳遞文件名。 2 打開方式:整型值 mode 指定了文件被打開的方 式,其取值范圍如下表所示:mode值文件被打開的模式說(shuō)明ios:appios:ateios:inios:nocreateios:noreplaceios:outios:truncios:binary使輸出追加到文件的尾部查找文件尾打開一個(gè)文件進(jìn)行讀操作文件不存在,導(dǎo)致 open 調(diào)用失敗。注意,在 visual c
52、+ 2005 中無(wú)此方式選擇。 若文件存在,則 open 調(diào)用失敗。注意,在 visual c+ 2005 中無(wú)此方式選擇。 打開一個(gè)文件進(jìn)行寫操作創(chuàng)建新文件,同名文件被刪除二進(jìn)制方式打開文件,缺省時(shí)為文本文件 在 ios 類定義中 mode 值被定義為以下枚舉: enum open_mode in = 0 x01,out = 0 x02,ate = 0 x04,app = 0 x08,trunc = 0 x10,nocreate = 0 x20,noreplace = 0 x40,binary = 0 x80 ; 各個(gè)枚舉值所指定的打開方式的詳細(xì)含義: 追加方式 ios:app: the f
53、unction performs a seek to the end of file. when new bytes are written to the file, they are always appended to the end, even if the position is moved with the ostream:seekp function. 查詢文件尾方式 ios:ate: the function performs a seek to the end of file. when the first new byte is written to the file, it
54、 is appended to the end, but when subsequent bytes are written, they are written to the current position. 輸入方式 ios:in: the file is opened for input. the original file(if it exists) will not be truncated. 輸出方式 ios:out: the file is opened for output. 更新方式 ios:trunc: if the file already exists, its con
55、tents are discarded. this mode is implied if ios:out is specified, and ios:ate, ios:app, and ios:in are not specified. 禁創(chuàng)建方式 ios:nocreate:vc+ 2005 無(wú)此方式 if the file does not already exist, the function fails. 禁替換方式 ios:noreplace:vc+ 2005 無(wú)此方式 if the file already exists, the function fails. 二進(jìn)制方式 ios:
56、binary: opens the file in binary mode (the default is text mode). note that there is no ios:in or ios:out default mode for fstream objects. you must specify both modes if your fstream object must both read and write files. 3 訪問(wèn)保護(hù)方式:整數(shù)值 nprot 指定了被打開文件的 訪問(wèn)保護(hù)方式(文件的訪問(wèn)類型)。從函數(shù)原型 中可以知道 nprot 的缺省值是 filebuf:
57、openprot,該 值對(duì)于 unix 操作系統(tǒng)是 0 x644,即普通文件。在 dos 或 windows 操作系統(tǒng)中, nprot 的值通常對(duì) 應(yīng)文件屬性,它們是:0普通文件1只讀文件2隱含文件4系統(tǒng)文件8備份文件 4 調(diào)用實(shí)例 打開一個(gè)輸出文件 ofstream out; out.open(test, ios:out, 0); 按普通文件訪問(wèn)打開一個(gè)輸出文件 “test”,與輸 出文件流 out 相關(guān)聯(lián)。由于普通文件訪問(wèn)方式 和輸出方式都是輸出文件流的缺省創(chuàng)建方式, 因此,調(diào)用 open 函數(shù)的形式可簡(jiǎn)化為: out.open(test); 打開一個(gè)輸入輸出文件 fstream both
58、; both.open(test, ios:in | ios:out, 0); 由于文件流都提供具有打開文件功能的構(gòu)造函數(shù) (文件名、打開和訪問(wèn)方式均可作為參數(shù)),所 以創(chuàng)建文件流對(duì)象和打開文件用可以一步完成: ofstream out(test); fstream both(test, ios:in | ios:out, 0); 注意,文件打開操作是否成功應(yīng)調(diào)用成員函數(shù) fail 進(jìn)行檢查,避免對(duì)無(wú)效文件讀寫所引起的系統(tǒng)錯(cuò)誤。fstream both;both.open(test, ios:in | ios:out, 0);if (both.fail()cout 和 和 也是 ifstrea
59、m,ofstream 和 fstream 的運(yùn)算符,但調(diào)用時(shí),必須用 ifstream,ofstream 或 fstream 流類對(duì)象替代控制臺(tái)文本信息輸入輸出使用 的輸入流類對(duì)象(例如,cin)和輸出流類對(duì)象(例 如,cout )。istreamostreamfstreambasefstreamifstreamofstreamiostream 把一個(gè)整數(shù)、一個(gè)浮點(diǎn)數(shù)和一個(gè)字符串以文本形式寫入一個(gè)磁盤文件 test 中。顯然,該程序執(zhí)行后,屏幕上是不會(huì)顯示任何與程序有關(guān)的信息的。而程序產(chǎn)生的磁盤文件可以使用 dos 系統(tǒng)的 type 命令或使用 windows 平臺(tái)的 “記事本” 或其他可以讀
60、寫純文本文件的工具查看。文件“test” 中記錄的信息為:10 123.456 this is a text file. 先建立一個(gè)輸出文件 “test2”,向它寫入數(shù)據(jù),然后關(guān)閉文件,再按輸入模式打開 “test2” ,并讀取和顯示文件中的信息。 語(yǔ)句 fout 100 hex 100 str i j; 讀入數(shù)據(jù)后,j 中保存的不是10 進(jìn)制 100,而是10 進(jìn)制 64。如果要使 j = 100,則需要將上述語(yǔ)句改為:fin str i hex j; 此時(shí),程序執(zhí)行結(jié)果為:hello!100 100從鍵盤讀入字符串、并將它們寫入磁盤。當(dāng)用戶輸入空白字符時(shí),程序停止。 問(wèn)題分析: 本程序采用
溫馨提示
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 《從傳統(tǒng)到時(shí)尚》課件
- 七大洲四大洋的位置
- 山東省煙臺(tái)市招遠(yuǎn)市(五四學(xué)制)2024-2025學(xué)年九年級(jí)上學(xué)期期末考試道德與法治試卷(含答案)
- 2024年全國(guó)社會(huì)工作者初級(jí)職業(yè)水平《社會(huì)工作實(shí)務(wù)》考試題參考答案
- 單位管理制度展示合集【人事管理篇】
- 單位管理制度展示大合集職員管理十篇
- 定期報(bào)告:一月可能繼續(xù)震蕩偏強(qiáng)中小盤成長(zhǎng)占優(yōu)
- 2024-2030年中國(guó)偶氮顏料行業(yè)市場(chǎng)深度分析及發(fā)展趨勢(shì)預(yù)測(cè)報(bào)告
- 單位管理制度展示大合集職工管理篇十篇
- 單位管理制度品讀選集【員工管理篇】
- 網(wǎng)絡(luò)賭博、網(wǎng)絡(luò)借貸和網(wǎng)絡(luò)詐騙的危害
- 《中西醫(yī)的區(qū)別》課件
- RFID電子標(biāo)簽制作方法
- 智能制造企業(yè)數(shù)字化轉(zhuǎn)型建設(shè)方案
- 病理生理學(xué)課件脂代謝紊亂
- 教師幽默朗誦節(jié)目《我愛(ài)上班》
- 《細(xì)胞工程學(xué)》考試復(fù)習(xí)題庫(kù)(帶答案)
- 中學(xué)課堂教學(xué)評(píng)價(jià)量表
- 食堂食材配送以及售后服務(wù)方案
- 塊單項(xiàng)活動(dòng)教學(xué)材料教案丹霞地貌
- 青年人應(yīng)該如何樹立正確的人生觀
評(píng)論
0/150
提交評(píng)論