《好學的C 第2版》 第8章 檔案 電子儲存

2022-09-11 18:30:09 字數 3412 閱讀 3718

主記憶體(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...