補充教材

28
補補補補 補補補補

description

補充教材. 串流輸入輸出的錯誤狀態. 簡介. 標準串流輸入輸出與檔案串流輸入輸出物件皆包含成員變數用來紀錄串流輸入輸出的狀態。 這些變數稱作「狀態位元」( State bit )。 eofbit : true 代表遇到 EOF 字元。 failbit : true 代表輸入格式不正確。 badbit : true 代表輸入或輸出失敗。 任何不可回覆的錯誤產生,例如資料遺失。 goodbit :輸入輸入一切正常(換言之,以上的變數都沒有被設為 true ), goodbit 才會被設成 true 。 注意事項: - PowerPoint PPT Presentation

Transcript of 補充教材

補充教材補充教材

串流輸入輸出的錯誤狀態串流輸入輸出的錯誤狀態

簡介簡介標準串流輸入輸出與檔案串流輸入輸出物件

皆包含成員變數用來紀錄串流輸入輸出的狀態。◦ 這些變數稱作「狀態位元」( State bit )。

eofbit : true 代表遇到 EOF 字元。 failbit : true 代表輸入格式不正確。 badbit : true 代表輸入或輸出失敗。

任何不可回覆的錯誤產生,例如資料遺失。 goodbit :輸入輸入一切正常(換言之,以上的變數都沒

有被設為 true ), goodbit 才會被設成 true 。注意事項:

◦ 一旦 eofbit 、 failbit 或 badbit 被設為 true ,則該串流物件的輸入輸出將因此而失效。

成員函式成員函式 eof()eof() 、、 fail()fail() 、、 bad()bad() 與與good()good()呼叫串流物件的 eof() 、 fail() 、 bad()與 good() 等成員函式即可回傳各狀態位元的值◦回傳 true 或 false 。

注意事項注意事項注意事項:

◦一旦 eofbit 、 failbit 或 badbit 被設為true ,則該串流物件的輸入輸出皆會因此失效。

◦之後再以同樣的串流物件進行輸入輸出將會得到不正常的結果。 問題:如何清除串流物件的異常狀態呢?

成員函式成員函式 clear()clear()功能:接受一個引數,將特定的狀態位元予以

清除。◦ 例如:

cin.clear( ios::failbit );如不給引數,則預設會將所有的狀態位元予以

清除(設為 false ),並將 goodbit 設為true 。◦ 範例

cin.clear();

檢查串流輸入輸出是否正確檢查串流輸入輸出是否正確

簡介簡介利用狀態位元我們可以用來檢查使用者輸入

的格式是否正確。◦ 當利用串流物件輸入時,檢查物件的狀態位元;

一旦輸入失敗,即捨棄所有的串流輸入,並將狀態回復。

成員函式成員函式 ignore()ignore()串流輸入物件中提供成員函式 ignore ()

,其功能為:◦ 讀取串流輸入並將字元捨棄。◦ 提供一個正整數與分界字元為引數,代表捨棄的

字元數目或終止的字元。 預設的字元個數為 1 預設的分界字元為 EOF (’ \0’)

使用範例使用範例 #include <iostream> #include <limits>

using namespace std;

void main() { int x; cin >> x; if (cin.fail()) {

cin.clear();cin.ignore(numeric_limits<streamsize>::max(), '\n');

cout << "Error!" << endl; } else cout << "x = " << x << endl; }

執行結果執行結果輸入正確 輸入錯誤

使用範例二使用範例二 #include <iostream> #include <limits>

using namespace std;

void main() { int x; cin >> x; while (cin.fail()) {

cin.clear();cin.ignore(numeric_limits<streamsize>::max(), '\n');

cout << "Error!" << endl;cin >> x;

} cout << "x = " << x << endl; }

注意事項注意事項串流擷取運算子( >> )僅會讀取至空白字

元為止,即便狀態位元出現異常,串流輸入緩衝區中仍會遺留之前未讀入的字元。◦ 可用成員函式 ignore() 捨棄這些字元。◦ 或在狀態回復之後繼續讀取。◦ 如要讀入整行文字,或讀取固定個數的字元,可

用 cin 物件中的 get() 或 getline() 函式。 get() 與 getline() 的差別在於: get() 不會把換行符號放

進去緩衝區,但 getline() 則會。

檔案串流輸入輸出檔案串流輸入輸出

IntroductionIntroduction

開啟檔案開啟檔案類別 fstream 所建立的物件可以同時做為讀

取或寫入的檔案物件:file.open("test.txt", ios::out | ios::in);◦當模式既為 ios::out 又為 ios::in 時,請注

意該檔案如果不存在,並不會自動建立該檔案,反而會得到開檔失敗的情況。

◦使用該模式前,請先確認檔案是否存在,如不存在,請自行建立。

成員函式成員函式 seekg()seekg() 與與 seekp()seekp()seekg() 是在讀取檔案時,用來移動檔案指

標◦ 「 g 」代表 get

seekp() 是在寫入檔案時,用來移動檔案指標◦ 「 p 」代表 put

在「 ios::in | ios::out 」模式之下,兩者皆可使用,並請注意,不論檔案的讀取皆會同時移動到檔案指標的位置。

範例實作(範例實作( Part 1Part 1 )) #include <iostream> #include <fstream> #include <iomanip> using namespace std; void main() { fstream file("test.txt", ios::in); if (!file) {

file.clear();file.open("test.txt", ios::out);

} file.close(); file.open("test.txt", ios::out | ios::in); if (!file) {

cout << "file could not open!" << endl;return;

}…

範例實作(範例實作( Part 2Part 2 )) do { int option;

string id;int data;cout << "1) Insert 2) Output 3) Quit: ";cin >> option;if (option == 3) break;if (option == 1) { string in_ID; int in_data; cin >> in_ID; cin >> in_data; file.clear(); file.seekg(0); while (file >> id >> data) { if (id == in_ID) { // 找到重複的 ID file.seekp(-16, ios::cur);

break; } } if (file.eof()) // 遇到 EOF ,表示資料要寫到最後 file.clear(); // 再做一次 clear() 。 Why? file << setw(10) << in_ID << setw(5) << in_data << endl;}

從頭搜尋檔案。為什麼要先呼叫 clear() ?因為如果 eofbit 被設成 true ,檔案讀取會失效,所以要先清掉該位元。 file.seekg(0);一行用來將檔案指標定位到檔案開頭

用 >> 作格式化輸入可免去型態轉換的問題,但要注意 >>僅讀取至空白字元。

試說明「 file.seekp(-16, ios::cur); 」的意義。__________________________________________________

範例實作(範例實作( Part 3Part 3 )) … else if (option == 2) // 印出所有資料 { file.clear(); file.seekg(0); while (file >> id >> data) {

cout << setw(10) << id << setw(5) << data << endl; } } } while (1); file.close();}

CC 語言標準輸入輸出語言標準輸入輸出

printf()printf() 與與 scanf()scanf()呼叫 printf() 與 scanf() 可分別用來作

螢幕輸出與鍵盤輸入。◦使用前必須引入標頭檔如下:

#include <stdio.h> //C或#include <cstdio> //C++

螢幕輸出;使用螢幕輸出;使用 printf()printf() #include <stdio.h>

void main() { int x = 2; char *name = “Mary”; double g1 = 3.4; float g2 = 1.7; printf(“%s has %d classes. Her grades are %0.2e and %0.2f.\n”, name, x, g1, g2); }

相較於 cout 與 << ,使用 printf() 的差異在於,程式設計師必須要根據變數來指定格式字串;例如

整數的格式字串為 %d字串的格式字串為 %s浮點數的格式字串為 %f雙精準浮點數要用 %e

Function printf() FormatFunction printf() FormatFormat Description

%c 字元%d 十進位整數%i 十進位整數%e 浮點數, e 指數型式%E 浮點數, E指數型式%f 小數點位數 6 位之浮點數%g 印出 %f 與 %e較短者%G 印出 %f 與 %E較短者%o 無號八進位整數

Function printf() FormatFunction printf() FormatFormat Description

%% 印出百分比符號%p 以十六進位印出指標位址%s 印出字串%u 無號十進位數字%x 無號十六進位整數,以 0-f 表示%X 無號十六進位整數,以 0-F 表示%l long ,加在 d,o,u,x,X 之前

Function printf() FormatFunction printf() FormatModifier Description

- 向左齊對,如 %-4f

+ 將數值的正負符號顯示出來,如 %+f

填補空白 數值為正數時留一空白,為負時顯示負號,如 %7.2f

0 將固定欄位長度的數值前補 0 ,與 -同用時無效,如 %09f

+ 將數值的正負符號顯示出來,如 %+f

鍵盤輸入;使用鍵盤輸入;使用 scanf()scanf()

#include <stdio.h>

void main() { int age; char name[100]; float salary; printf(“Input name: ”); scanf(“%s”, name); printf(“Input age: ”); scanf(“%d”, &age); printf(“Input salary: ”); scanf(“%f”, &salary); printf(“%s is %d years old. His/her salary is %0.2f.\n”, name, age, salary); }

鍵盤輸入;使用鍵盤輸入;使用 scanf()scanf()

#include <stdio.h>

void main() { int age; char name[100]; float salary; printf(“Input name, age and salary: ”); scanf(“%s%d%f”, name, &age, &salary); printf(“%s is %d years old. His/her salary is %0.2f.\n”, name, age, salary); }