第13章C++流和文件流_第1頁
第13章C++流和文件流_第2頁
第13章C++流和文件流_第3頁
第13章C++流和文件流_第4頁
第13章C++流和文件流_第5頁
已閱讀5頁,還剩55頁未讀, 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第13章C++流和文件流C++語言中沒有專門的輸入/輸出(I/O)語句,C++中的I/O操作是通過一組標準I/O函數和I/O流來實現的。C++的標準I/O函數是從C語言繼承而來的,同時對C語言的標準I/O函數進行了擴充。C++的I/O流不僅擁有標準I/O函數的功能,而且比I/O函數更方便、更可靠。13.1什么是流C++中把數據之間的傳輸操作稱作流。在C++中,流既可以表示數據從內存傳送到某個載體或設備中,即輸出流;也可以表示數據從某個載體或設備傳送到內存緩沖區變量中,即輸入流。在進行I/O操作時,操作步驟如下:(1)打開操作,使流和文件發生聯系,建立聯系后的文件才允許數據流入或流出;(2)輸入或輸出操作;(3)結束后,使用關閉操作使文件與流斷開聯系。C++中所有流都是相同的,但操作的文件可以不同。使用流以后,程序用流統一對各種計算機設備和文件進行操作,使程序與設備、程序與文件無關,從而提高了程序設計的通用性和靈活性。也就是說,無論與流相聯系的實際物理設備差別有多大,流都采用相同的方式運行。這種機制使得流可以跨越物理設備平臺,實現流的透明運作,而與實際的物理設備無關。例如,往顯示器上輸出字符和向磁盤文件或打印機輸出字符,盡管接收輸出的物理設備不同,但具體操作過程是相同的。13.1.1預定義流在程序開始運行時,C++會自動打開4個流,這些流是C++流類庫的預定義流,如下表所列。流含義所屬類庫默認設備cin標準輸入iostream.h鍵盤cout標準輸出iostream.h顯示器cerr沒有被緩沖的標準錯誤輸出iostream.h顯示器clog被緩沖了的標準錯誤輸出iostream.h顯示器C++的流通過重載運算符“<<”和“>>”執行輸出和輸入操作。輸出操作是向流中插入一個字符序列,因此,在流操作中,將運算符“<<”稱為插入運算符。輸入操作是從流中提取一個字符序列,因此,將運算符“>>”稱為提取運算符。1.coutcout是與標準輸出設備連接的預定義輸出流,稱為匯。C++的插入運算符“<<”向輸出流發送字符。實際上,位于插入運算符右側的字符串被存儲在“<<”左側的流中。例如:cout<<name<<""<<number<<'\n';cout是數據的目的地,插入運算符“<<”把對象或文字數據(字符串、數字或任何對象)傳送到cout。cout一般連接到標準輸出設備即顯示器(默認設備)。2.cincin是與標準輸入設備連接的預定義輸入流,稱為源。它從輸入流中取出數據,數據從輸入提取運算符“>>”處流進程序。為了保留輸入數據,輸入語句要求有目的地址,即指定數據類型的存儲單元,例如:inti;cin>>i;這段代碼所進行的操作是:提取運算符“>>”從cin參數中提取一個整型輸入數據,并存入一個對象(變量),在此例中即為整型數i。cin一般連接到標準輸入設備即鍵盤(默認設備)。3.cerrcerr類似標準錯誤文件。cerr與cout的差別在于:(1)cerr是不能重定向的;(2)cerr不能被緩沖,它的輸出總是直接傳送到標準輸出設備上。錯誤信息是寫到cerr的項。即使在各種其他輸出語句中,如果使用下列語句,則錯誤信息“Error”總能保證在顯示器上顯示出來:cerr<<"Error"<<"\n";4.clogclog是不能重定向的,但是可以被緩沖。在某些系統中,由于緩沖,使用clog代替cerr可以改進顯示速度:clog<<"Error"<<"\n";13.1.2C++的流類庫C++提供了一個流類庫,流類庫由若干完成I/O操作的基礎類以及若干支持特定種類的源和目標的I/O操作類組成。流類庫的基礎類利用繼承關系組織起來,其類層次如下圖所示,這些類的說明如表13.2所列。所有使用流類庫的程序必須用“#include”編譯指令將iostream.h包含進來。I/O流類庫的類層次輸入流類istream通用輸入流類和其他輸入流的基類iostream.hifstream輸入文件流類fstream.histream_withassigncin的輸入流類iostream.histrstream輸入字符串流類strstrea.h輸出流類ostream通用輸出流類和其他輸出流的基類iostream.hofstream輸出文件流類fstream.hostream_withassigncout、cerr和clog的輸出流類iostream.hostrstream輸出字符串流類strstrea.hI/O流類iostream通用I/O流類和其他I/O流的基類iostream.hfstreamI/O文件流類fstream.hstrstreamI/O字符串流類strstrea.h13.2格式化I/O在以前的程序中,所有I/O采用的格式都是由C++流類庫提供的默認方式。在實際應用中,常常需要準確控制數據(特別是整數、浮點數與字符串)的I/O格式。流類庫可用兩種方法控制數據的格式:使用ios類的成員函數和使用I/O操縱符。13.2.1使用ios成員函數每一個C++流都有自己當前的數據格式控制狀態,這些狀態用一個長整數表示,即ios類的數據成員x_flags,稱為格式化標志字。這些格式化標志字在ios類中定義為公有的枚舉量。在iostream.h頭文件中定義了以下枚舉類型:enum{skipws=0x0001,//跳過輸入中的空白(空格、制表符、回車、換行等)left=0x0002, //輸出左對齊right=0x0004, //輸出右對齊internal=0x0008, //在符號或基位與數值之間補齊空格dec=0x0010, //按十進制I/Ooct=0x0020, //按八進制I/Ohex=0x0040, //按十六進制I/Oshowbase=0x0080,//輸出數制的基showpoint=0x0100,//強制浮點數輸出小數點uppercase=0x0200,//十六進制采用大寫輸出showpos=0x0400,//在正數前加上“+”scientific=0x0800, //浮點數使用科學記數法fixed=0x1000,//浮點數使用普通記數法unitbuf=0x2000, //每次插入后刷新所有流stdio=0x4000 //每次插入后刷新標準輸出和標準錯誤輸出流};(1)setf()成員函數setf()用于設置狀態標志。例如,設置輸出流cout的showbase標志使用如下語句:

cout.setf(ios::showbase);設置輸入流cin的skipws標志使用如下語句:

cin.setf(ios::skipws);

注意:格式標志前的限定“ios::”不可缺少,因為這些標志是在ios類中定義的。在setf()中還可用位或操作“|”將多個標志連在一起。例如:

cout.setf(ios::scientific|ios::showpoint);同時設置scientific和showpoint兩個標志。(2)unsetf()成員函數unsetf()用來取消格式標志,unsetf()的用法與setf()相似。(3)flags()成員函數flags()用于獲取當前格式標志的狀態,即返回保護成員x_flags的當前值。(4)precision()該函數的說明如下:intprecision([intnum]);用于設置或返回(不帶參數時)浮點數的輸出精度,也就是通過這個公共成員函數設置ios類的保護數據成員x_precision的值,該成員的默認值為6。precision()函數的設置值一直有效,直到下一個precision()函數改變該值為止。(5)width()該函數的說明如下:intwidth([intlen]);用于設置或返回(不帶參數時)輸出數據的字段寬度,也就是通過這個公共成員函數設置ios類的保護數據成員x_width的值。width()函數的設置值只對下一個輸出有效。(6)fill()該函數的說明如下:charfill([charch]);用于設置或返回(不帶參數時)輸出的填充字符,也就是通過這個公共成員函數設置ios類的保護數據成員x_fill的值,該成員的默認值為空格。fill()函數的設置值一直有效,直到下一個fill()函數改變該值為止?!纠糠治鲆韵鲁绦虻膱绦薪Y果。#include<iostream.h>voidmain(){intn=123;doubled=1234.5678;cout.precision(10);cout.width(10);cout.fill('*');cout<<n<<endl;cout<<d<<endl;cout.precision(6);cout.width(6);cout<<n<<endl;cout<<d<<endl;}*******1231234.5678***1231234.57

右對齊13.2.2使用I/O操縱符除ios類成員函數之外,C++的流類庫還提供了另一種更方便的I/O格式化方法,這種方法使用一種稱為操縱符的特殊函數,操縱符的特點是可以直接包含在I/O表達式中。所有不帶形參的操縱符都定義在頭文件iostream.h中,而帶形參的操縱符則定義在頭文件iomanip.h中,因而使用相應的操縱符就必須包含相應的頭文件。表13.3列出了這些I/O操縱符。已在第3章已介紹,這是不再討論。13.3重載I/O運算符C++的I/O系統的另一個優點是可以重載I/O運算符。通過重載I/O運算符,可以建立適合于類需要的輸入和輸出界面。I/O運算符重載的實質就是把用于變量輸入輸出的運算符轉化為對于類對象的輸入輸出操作。13.3.1重載輸出運算符“<<”在C++中,輸出操作稱為插入,“<<”稱為插入運算符。當重載輸出運算符“<<”用于輸出時,相當于創建一個插入符函數。插入符函數的格式如下:

friendostream&operator<<(ostream&stream,類名&類引用名){函數體;returnstream;}該插入符函數是以友元方式說明的。其中的第一個參數是ostream類對象的一個引用,即stream必須是一個輸出流。“類引用名”接收待輸出的對象。該函數返回ostream的一個引用stream。“函數體”中給出實現該插入符重載目的的代碼?!纠糠治鲆韵鲁绦虻膱绦薪Y果。#include<iostream.h>classSample{intx,y;public:Sample(intm,intn){x=m;y=n;}friendostream&operator<<(ostream&stream,Sample&s){cout<<"x="<<s.x<<",y="<<s.y<<endl;returnstream;}};voidmain(){SampleA(1,2),B(3,4);cout<<A<<B;}x=1,y=2x=3,y=413.3.2重載輸入運算符“>>”在C++中,“>>”運算符稱為提取運算符,對它進行重載的函數稱為提取符函數。這個運算符函數接收流的輸入信息。其格式如下:

friendistream&operator>>(istream&stream,類名&類引用名){函數體;returnstream;}該提取符函數是以友元方式說明的。其中的第一個參數是istream類對象的一個引用,即stream必須是一個輸入流?!邦愐妹苯邮蛰斎雽ο蟮囊?。該函數返回istream的一個引用stream?!昂瘮刁w”中給出實現該提取符重載目的的代碼?!纠糠治鲆韵鲁绦虻膱绦薪Y果。#include<iostream.h>classSample{intx,y;public:Sample(){}friendistream&operator>>(istream&stream,Sample&s){cout<<"輸入x和y的值"<<endl;cout<<"x:";stream>>s.x;cout<<"y:";stream>>s.y;returnstream;}friendostream&operator<<(ostream&stream,Sample&s){cout<<"輸出x和y的值"<<endl;cout<<"x="<<s.x<<",y="<<s.y<<endl;returnstream;}};voidmain(){SampleA;cin>>A;cout<<A;}輸入x和y的值x:5<Enter>y:8<Enter>輸出x和y的值x=5,y=813.4檢測流操作的錯誤在I/O流的操作過程中可能出現各種錯誤,每一個流都有一個狀態標志字,以指示是否發生了錯誤以及出現了哪種類型的錯誤,這種處理技術與格式控制標志字是相同的。ios類定義了以下枚舉類型:enumio_state{goodbit=0x00,//不設置任何位,一切正常eofbit=0x01,//輸入流已經結束,無字符可讀入failbit=0x02,//上次讀/寫操作失敗,但流仍可使用badbit=0x04,//試圖作無效的讀/寫操作,流不再可用hardfail=0x80//不可恢復的嚴重錯誤};對應于這個標志字各狀態位,ios類還提供了以下成員函數來檢測或設置流的狀態:intrdstate(); //返回流的當前狀態標志字inteof(); //返回非0值表示到達文件尾intfail(); //返回非0值表示操作失敗intbad(); //返回非0值表示出現錯誤intgood(); //返回非0值表示流操作正常intclear(intflag=0); //將流的狀態設置為flag為提高程序的可靠性,我們應在程序中檢測I/O流的操作是否正常。當檢測到流操作出現錯誤時,可以通過異常處理來解決問題。13.5文件流文件是存儲在磁盤、磁帶等外部設備上的數據集合,每一個文件都必須有一個惟一名字。使用文件前必須首先打開,使用完畢后必須關閉文件。對文件的操作是由文件流類完成的。文件流類在流與文件之間建立連接,使用這些文件流類必須用#include編譯指令將頭文件fstream.h包含進來。13.5.1文件的打開與關閉流可以分為3類:輸入流、輸出流以及輸入/輸出流,相應地必須將流說明為ifstream、ofstream以及fstream類的對象。例如:ifstreamifile; //說明一個輸入流ofstreamofile; //說明一個輸出流fstreamiofile; //說明—個輸入/輸出流說明了流對象之后,可使用函數open()打開文件。文件的打開即是在流與文件之間建立一個連接。open()的函數原型為:voidopen(constchar*filename,intmode,intprot=filebuf::openprot);其中,filename是文件名字,它可包含路徑說明。mode說明文件打開的模式,它對文件的操作影響重大,mode的取值必須是以下值之一:?

ios::in打開文件進行讀操作?

ios::out打開文件進行寫操作?

ios::ate打開時文件指針定位到文件尾?

ios::app添加模式,所有增加都在文件尾部進行?

ios::trunc如果文件已存在則清空原文件?

ios::nocreate如果文件不存在則打開失敗?

ios::noreplace如果文件存在則打開失敗?

ios::binary二進制文件(非文本文件)對于ifstream流,mode的默認值為ios::in;對于ofstream流,mode的默認值為ios::out。prot決定文件的訪問方式,取值如下:?

0普通文件?

1只讀文件?

2隱含文件?

4系統文件一般情況下,該訪問方式使用默認值。與其他狀態標志一樣,mode的符號常量可以用位或運算“|”組合在一起,如ios::in|ios::binary表示以只讀方式打開二進制文件。例如:ifstreamifile;ifile.open("c:\\vc\\abc.txt",ios::ate);表示以文本文件形式打開C:\vc目錄下的abc.txt文件,文件指針定位到文件尾,準備進行讀文件操作。而操作:ofstreamofile;ofile.open("c:\\vc\\abc.txt",ios::binary);表示以二進制文件形式打開C:\vc目錄下的abc.txt文件,準備進行寫文件操作。其中,文件名中“\\”的第一個“\”為轉義字符。除了open()成員函數外,ifstream、ofstream和fstream三類流的構造函數也可以打開文件,其參數同open()函數。例如:ifstreamifile("c:\\vc\\abc.txt");說明一個輸入流對象的同時,將這個流與文件“c:\vc\abc.txt”連接起來,使流ifile可以用文本形式對該文件進行讀操作。13.5.2文件的讀寫通過打開文件就建立I/O流與文本文件的連接,之后就可以進行文件的讀寫操作了。1.文件讀寫方法在C++中提供了幾種文件讀寫方法。(1)使用流運算符直接讀寫。文件的讀/寫操作可以直接使用流的插入運算符“<<”和提取運算符“>>”,這些運算符將完成文件的字符轉換工作。

(2)使用流成員函數。常用的輸出流成員函數如下:

?put函數該函數把一個字符寫到輸出流中。下面兩個語句默認是相同的,但第二個受該流的格式化參數的影響:

cout.put('A');//精確地輸出一個字符cout<<'A';//輸出一個字符,但此前設置的寬度和填充方式在此起作用?write函數該函數把內存中的一塊內容寫到一個輸出文件流中,長度參數指出寫的字節數。write函數當遇到空字符時并不停止,因此能夠寫入完整的類結構,該函數帶兩個參數:一個char指針(指向內存數據的起始地址)和一個所寫的字節數。

注意,在該結構對象的地址之前需要char做強制類型轉換。常用的輸入流成員函數如下:

?

get函數該函數的功能與提取運算符(>>)很相似,主要的不同點是get函數在讀取數據時包括空白字符,而提取運算符在默認情況下拒絕接受空白字符。

?getline函數該函數的功能是允許從輸入流中讀取多個字符,并且允許指定輸入終止字符(默認值是換行字符),在讀取完成后,從讀取的內容中刪除該終止字符。?read函數該函數從一個文件讀字節到一個指定的存儲器區域,由長度參數確定要讀的字節數。雖然給出長度參數,但當遇到文件結束或者在文本模式文件中遇到文件結束標記字符時讀就結束。2.文本文件的讀寫文本文件只適用于那些解釋為ASCII碼的文件。處理文本文件時將自動作一些字符轉換,如輸出換行字符0x0A時將轉換為回車0x0D與換行0x0A兩個字符存入文本文件,讀入時也會將回車與換行兩個字符合并為一個換行字符,這樣內存中的字符與寫入文件中的字符之間就不再是一一對應關系。文本文件的結束以ASCII碼的控制字符0x1A表示?!纠糠治鲆韵鲁绦虻膱绦薪Y果。#include<iostream.h>#include<fstream.h>intmain(){ofstreamofile("test");//打開test文件用于寫,即輸出if(!ofile){cout<<"test文件不能打開"<<endl;return0;}ofile<<"ThisbookisC++"<<""<<12345<<endl;ofile.close();ifstreamifile("test");//打開test文件用于讀,即輸入if(!ifile){cout<<"test文件不能打開"<<endl;return0;}charstr[80];ifile>>str;ifile.close();cout<<str<<endl;return1;}本程序先在當前目錄下建立一個test文本文件,并寫入“ThisbookisC++12345”數據,然后打開該文件,將其中的數據輸入到變量str中,由于讀時遇到空格時終止,所以str為“This”。程序的執行結果如下:This【例】編寫一個程序,將文本文件abc.txt復制到文本文件xyz.txt。解:使用輸入流成員函數get()從文本文件abc.txt中讀取一個字符ch,然后使用輸出流成員函數put()將字符ch寫入文本文件xyz.txt中,繼續這一過程直到get()讀完為止。實現本例功能的程序如下:#include<iostream.h>#include<fstream.h>intmain(){ifstreamifile("abc.txt");charch;if(!ifile){cout<<"abc.txt文件不能打開"<<endl;return0;}ofstreamofile("xyz.txt");if(!ofile){cout<<"xyz.txt文件不能打開"<<endl;return0;}while(ifile.get(ch))ofile.put(ch);ifile.close();ofile.close();return1;}3.二進制文件的讀寫二進制文件不同于文本文件,它可用于任何類型的文件(包括文本文件),讀寫二進制文件的字符不作任何轉換,讀寫的字符與文件之間是完全一致的。一般地,對二進制文件的讀寫可采用兩種方法:一種是使用get()和put();另一種是使用read()和write()?!纠恳韵鲁绦蚪⒁粋€輸出文件流并將一個Date結構體變量的二進制值寫入到該文件中。#include<fstream.h>structDate{ intmo,da,yr;};voidmain(){Datedt={2,20,2001};ofstreamofile("data.dat",ios::binary);ofile.write((char*)&dt,sizeofdt);ofile.close();}4.文件的隨機讀寫每一個文件都有兩個指針:一個是讀指針,說明輸入操作當前在文件中的位置;另一個是寫指針,說明下次寫操作的當前位置。每次執行輸入或輸出時,相應的讀/寫指針將自動向后移動。C++語言的文件流不僅可以按這種順序方式進行讀/寫,而且還可以隨機地移動文件的讀/寫指針。有一些外部設備(如磁帶、行式打印機等)關聯的流只能作順序訪問,但在許多情況下使用隨機方式訪問文件更加方便靈活。(1)輸出流隨機訪問函數輸出流隨機訪問函數有seekp和tellp。一個輸出文件流保存一個內部指針以指出下一次寫數據的位置。seekp成員函數設置這個指針,因此可以以隨機方式向磁盤文件輸出。tellp成員函數返回該文件位置指針值。這兩個成員函數的原型如下:ostream&ostream::seekp(流中的位置);ostream&ostream::seekp(偏移量,參照位置);streamposostream::tellp();其中,streampos被定義為long型,并以字節數為單位。“參照位置”具有如下含義:?

cur=1相對于當前寫指針所指定的位置。?

beg=0相對于流的開始位置。?

end=2相對于流的結尾處。(2)輸入流隨機訪問函數。輸入流隨機訪問函數有seekg和tellg。在輸入文件流中,保留著一個指向文件中下一個將要讀數據的位置的內部指針,可以用seekg函數來設置這個指針。使用seekg可以實現面向記錄的數據管理系統,用固定長度的記錄大小乘以記錄號便得到相對于文件末尾的字節位置,然后使用get讀這個記錄。tellg成員函數返回當前文件讀指針的位置,這個值是streampos類型,該typedef結構定義在iostream.h中。這兩個成員函數的說明原型如下:istream&istream::seekg(流中的位置);istream&istream::seekg(偏移量,參照位置);streamposistream::tellg();其中,streampos被定義為long型,并以字節數為單位?!皡⒄瘴恢谩本哂腥缦潞x:

?

cur=1相對于當前讀指針所指定的位置。

?

beg=0相對于流的開始位置。

?

end=2相對于流的結尾處?!纠烤帉懸粋€程序,在文件City.dat中輸入幾個城市的名稱和區號,并根據用戶輸入的區號查找對應的城市。解

溫馨提示

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

評論

0/150

提交評論