主記憶體(ram,隨機訪問記憶體)當計算機關閉時其資料就丟失。
對於cin和cout支援的函式呼叫和操作,c++提供的檔案流也同樣支援。前者需要#include ,後者需要#include 。流(stream)在寫資料時是目的地,讀資料時就是源頭。
開啟badgirl.txt檔案:
ofstream fout("badgirl.txt"); //以獨佔方式開啟該檔案,預設檔案在當前目錄(執行程式的那個目錄),也可給出完整路徑(加上驅動器碟符也可以,這就是絕對路徑,例如"c:\\badgirl.txt"就是c:\badgirl.txt檔案的絕對路徑)。還有ifstream、fstream
fout << "you bad but ***y girl!" << endl;
fout << "and you need bad boy!"
fout.close();
fout物件提供了一條通向磁碟檔案的道路。用物件導向的術語說,fout封裝了那個檔案並使之具備了接收輸出資料的能力。另外,雖然程式成功退出是、時c++會自動關閉仍處於開啟狀態的檔案,但是檔案不用時最好及時關閉,使程式放棄對該檔案的擁有權,讓其他程序可以去訪問它。 //it:乙個程序開啟了某檔案,其他程序是否可讀可寫該檔案?試圖開啟該檔案是否會出錯?
char filename[max_path+1];
預定義常數max_path:系統所能支援的檔名(包括其路徑在內)的最大長度。
若檔案開啟操作不成功,fout就會是null,可用於判斷。非法路徑或者像以寫的方式開啟唯讀檔案都會返回null.
if(!fout)
ifstream fin;//檔案以文字和輸入方式開啟。
fin.getline(input_line, col_width+1);//讀出一行
if(fin.eof()); //到達檔案末尾,fin.eof()就是true了
庫函式atoi可以將字串轉為整數,這可以用來處理使用者輸入。
以上都是文字流,操作與控制台io大同小異。寫入檔案的每乙個位元組都是可列印字元的ascii編碼。
二進位制檔案:讀寫這類檔案時使用的都是資料的實際數值,無需進行ascii轉換(it:數字0就是寫入數字0,而不是0的ascii碼值)。
####文字模式裡,換行符在寫時會被轉換為\n\r(回車加換行wins)或\n(unix)或\r(mac)。而二進位制模式裡無需也不能進行此種轉換。####注:回車原意是游標回到當前行的開頭,換行原意是游標移動到下一行。所以不要嘲諷wins,含義上是完整的,雖然多乙個字元。不過導致的問題就是跨系統的檔案格式問題,產生了dos2unix這種命令。
建立檔案流物件時,可將它設定為文字模式(預設)或二進位制模式。前者應該使用<<、>>及getline,後者只應該使用read和write成員函式(是直接的讀寫操作)。
範例:(記錄指的是在檔案裡不斷重複出現的資料格式。由於資料有規律排列,通過記錄號獲取資料會很容易,而用結構或類來儲存它們是很自然的(後續討論)。)
#include
#include
using namespace std;
int get_int(int default_value);
int main(){
char filename[max_path+1];
int n = 0;
char name[20];
int age = 0;
int recsize = sizeof(name) + sizeof(int);//計算記錄的長度
//開啟檔案
cout << "enter file name: ";
cin.getline(filename,max_path);
fstream fbinout(filename, ios::binary | ios::out); //ios::out是要對檔案進行寫操作,注意會覆蓋現有檔案內容,也用於開啟新檔案
if(!fbinout){
cout << "could not open " << filename return -1;
//獲取要記錄的資料
cout << "enter record number: ";
n = get_int(0); //獲取記錄號
cout << "enter name: "
cin.getline(name, sizeof(name)); //獲取名字
cout << "enter age: ";
age = get_int(0); //獲取年齡
//寫入資料
fbinout.seekp(n * recsize); //根據記錄號偏移到該記錄應在的位置,否則會覆蓋0號記錄(it:游標或者指標預設的在最開始即0號記錄處)
fbinout.write(name, sizeof(name));
fbinout.write((char*)(&age),sizeof(int));
fbinout.close();
system("pause");
return 0;
#define col_width 80 //80是典型行寬 //it:預編譯從定義處開始生效
int get_int(int default_value){
char s[col_width+1];
cin.getline(s, col_width+1);
if (strlen(s) == 0)
return default_value;
return atoi(s);
讀取資料類似,不同之處只在於:
fstream fbinin(filename, ios::binary | ios::in); //ios::in模式檔案不存在會出錯
fbinin.seekp(n*recsize);
fbinin.read(name, sizeof(name));
fbinin.read((char*)(&age), sizeof(int));
fbinin.close();
以下fbin將既支援讀又支援寫:
fstream fbin(filename, ios::binary | ios::out | ios::in);
小結撿漏:
#include 會將c++標準庫提供的檔案流支援功能啟用(把必要的函式原型和宣告引入程式)
//it:通過檔案指標可實現隨機訪問模式(讀寫(包括覆蓋)檔案任意部分而不影響其他資料)。如果檔案指標被移動到了超出檔案當前長度的位置,檔案會自動擴充套件以滿足長度需要。
seekp成員函式用於移動檔案指標,其入參是從檔案頭開始的偏移量(以位元組計算)。
read和write:入參相同,都是資料位址(char*型別)和需要複製的位元組數。//it:寫入int要取其位址轉為char*型別,但複製位元組數仍是int所占用位元組數(建議用sizeof獲取)。
fbin.write((char*)(&x), sizeof(x));
C 程式設計 第2版 課後習題答案 第8章
1.使用結構體變數來表示學生資料 姓名 學號和3門課程的成績。從鍵盤輸入個學生的資料,要求列印出每個學生的姓名和3門課程的平均成績,此外要求按學生的平均成績降序輸出,按學生姓名搜尋。view code 1 include 2 include 3 using namespace std 4struct...
《好學的C 第2版》 第9章 一些高階程式設計技術
轉向c 0x和oop之前,需要掌握其他一些技巧。c 命令列引數 main函式須這樣定義 int main int argc,char ar argc計數包括程式名,所以至少是1 ar 0 就是程式名。這兩個引數可以任意使用,但是是唯讀的,可以隨意顯示或複製它們。程式中可以通過argc判斷輸入引數是否...
C 程式設計 第2版 課後習題答案 第4章
c 程式設計 第2版 課後習題答案 第4章 控制結構 view code 1 設計乙個程式,輸入實型變數x和y,若x y,則輸出 x y 若x2 include 3 include 4 void main 514 15 include 16 include 17 include 18 void ma...