C++ Primer Plus--分支語句和邏輯運算符(六)

C++提供了if和switch語句來進行決策,還有邏輯運算符和條件運算符。

6.1 if語句

使用if語句來統計語句中的空格總數,實現如下:

if.cpp

#include <iostream>
using namespace std;
int main()
{
	char ch;
	int spaces = 0;
	int total = 0;
	cin.get(ch);
	while (ch != '.')
	{
		if (ch == ' ')
			spaces++;
		total++;
		cin.get(ch);
	}
	cout <<  spaces << " spaces, " << total ;
	cout << " charachers total in sentence.\n";
	return 0;
}

結果:

The balloonist was an airhead
with lofty goals.
6 spaces, 46 charachers total in sentence.

只要當ch爲空格時,語句spaces++才被執行。因爲語句total位於if語句的外面,因此每輪循環中都被執行。

6.1.1 if else語句

if (test-condition)
	statement1
else
	statement2

如果測試條件爲true,則程序將執行statement1,跳過statement2;如果測試條件爲false,則程序將跳過statement1,執行statement2。

6.1.2 格式化if else語句

如果操作部分需要多條語句,需要使用大括號將它們括起來,組成一個語句塊。

if (ch == 'z')
{
	zorro++;
	cout << "Another zorro candidate\n";
}
else 
{
	dull++;
	cout << "Not a Zorro candidate\n";
}

6.1.3 if else if else結構

實際中,可能需要程序提供兩個以上的選擇:

if (ch == 'A')
	a_grade++;
else 
	if (ch == 'B')
		b_grade++;
	else 
		soso++;

可以寫成如下形式:

if (ch == 'A')
	a_grade++;
else if (ch == 'B')
	b_grade++;
else 
	soso++;

修改後的格式更爲清晰。

ifelseif.cpp

#include <iostream>
using namespace std;
const int Fave = 27;
int main()
{
	int n;
	cout << "Enter a number in the range 1-00 to find my favorite nmber: \n";
	do 
	{	cin >> n;
		if (n > Fave)
			cout <<  "Too high -- guess again:";
		else if (n < Fave)
			cout <<  "Too low -- guess agin: ";
		else
			cout << Fave << " is right!\n";
	}while (n != Fave);
	return 0;
}

結果:
Enter a number in the range 1-00 to find my favorite nmber:
22
Too low – guess agin: 44
Too high – guess again:27
27 is right!

錯誤防範:

表達式variable == value反轉寫成value == varibale。這樣,可以捕獲將相等運算符誤寫成賦值運算符的錯誤。

if (3 = var)

將一個變量賦給一個常量,編譯器將生成錯誤信息。

if (var = 3)

這樣,將3賦給一個變量,正確的語法,編譯不會報錯,於是會導致程序出錯。

6.2 邏輯表達式

C++提供了三種邏輯運算符,分別是:邏輯OR(||)、邏輯AND(&&)和邏輯NOT(!)。

6.2.1 邏輯OR運算符

如果表達式中的任意一個或全部都爲true,則得到的表達式爲true。

5 == 5 || 5 == 9 //true
3 <= 5 || 5 >= 3 //true
1 > 2 || 2 > 3 //False

||運算符的優先級比關係運算符低,因此不需要添加括號。

C++規定,||運算符是個順序點。即,先修改左側的值,再對右側的值進行判定。例如:

i++ < 6 || i == j

假設i越來的值爲10,則在對i和j進行比較時,i的值將爲11。另外,如果左側的表達式爲true,則C++將不會去判定右側的表達式,因爲只要一個表達式爲true,則整個邏輯表達式爲true。

6.2.2 邏輯AND運算符

僅當兩個表達式都爲true時,得到的表達式才爲true。

5 == 5 && 4 == 4//true
5 < 3 && 3 > 2 //false

&&運算符的優先級低於關係運算符,因此沒必要添加括號。和||運算符一樣,&&運算符也是順序點,因此將先判定左側,並且在右側判定之前產生所有的副作用。如果左側爲false,則整個邏輯表達式爲false,這種情況下,C++將不會再對右側進行判定。

6.2.3 用&&來設置取值範圍

&&運算符還允許建立一系列if else if else語句,其中每種選擇都對應一個特定的取值範圍。

if	(age > 17 && age < 35)
	index = 0;
else if (age >= 35 && age < 50)
	index = 1;
else if (age >= 50 && age < 65)
	index = 2;
else
	index = 3;

注意,下面語句:

if (17 < age < 35)

編譯器不會捕獲這種錯誤,因爲它仍然是合法的C++語法。<運算符是從左向右結合,因此表達式含義如下:

if ((17 < age) < 35)

但(17<age)的結果要麼爲1,要麼爲0。不管哪種情況,表達式的值17<age都要小於35,所以整個測試的結果總是true。

6.2.4 邏輯NOT運算符

!運算符將它後面的表達式的真值取反。!運算符的優先級高於所有的關係運算符和算術運算符。因此,要對表達式取反,必須使用括號將其括起來,如下:

!( x > 5);
!x > 5; // 該表達式總是爲false,!x爲1或0,總是小於5

!運算符對於返回true-false值或可以被解釋爲true-false值的函數是很有用的。比如:

!strcmp(s1,s2);

下面的程序來篩選可賦給int變量的數字輸入。

not.cpp

#include <iostream>
#include <climits>
using namespace std;
bool is_int(double);
int main()
{
	double num;
	cout << "Enter an integer value:";
	cin >> num;
	while (! is_int(num))
	{
		cout << "Out of range -- please try again:";
		cin >> num;
	}
	int val = int(num);
	cout << "You've entered the integer " << val << endl;
	return 0;
}

bool is_int(double x)
{
	if (x <= INT_MAX && x >= INT_MIN)
		return true;
	else 
		return false;
}

結果:

Enter an integer value:1000000000000000
Out of range -- please try again:-1000000000000
Out of range -- please try again:444
You've entered the integer 444

布爾函數is_int()使用了climits文件中定義的兩個符號常量INT_MIN和INT_MAX來確定int類型的範圍。

6.2.5 邏輯運算符細節

AND和OR運算符的優先級都低於關係運算符。

!運算符的優先級都高於所有關係運算符和算符運算符。

邏輯AND運算符的優先級高於邏輯OR運算符,因此:

age > 30 && age < 45 || weight > 300

被解釋爲:

(age > 30 && age < 45) || weight > 300

當然,還可以使用括號來將所希望的解釋告訴程序。例如:

(age > 30 || weight > 300) && donation > 1000

C++確保程序從左向右進行邏輯運算表達式,並在知道了答案立刻停止。

6.2.6 其他表示方式

使用標識符and、or和not來表示三種邏輯運算符。

| 運算符 | 另一種表示方式 |
|—|
| && | and |
| || | OR |
| ! | NOT |

6.3 字符函數庫cctype

C++繼承了一個與字符相關的、非常方便的函數軟件包,他可以簡化如確定字符是否爲大小寫字母、數字、標點符號等工作,這些函數的原型在頭文件cctype(老式的風格ctype.h)中定義。

下面使用AND和OR來測試字符ch是不是字母字符的代碼:

if (ch >= 'a' and ch <= 'z') || (ch >= 'A' && ch <= 'Z')

與使用isalpha()相比:

if (isalpha(ch))

isslpha()不僅更容易使用,而且更通用。

下面程序演示cctype庫函數。

cctypes.cpp

#include <iostream>
#include <cctype>
using namespace std;
int main()
{
	cout << "Enter text for analysis and type @ to terminate input:";
	char ch;
	int whitespace = 0;
	int digits = 0;
	int chars = 0;
	int punct = 0;
	int others = 0;
	cin.get(ch);
	while (ch != '@')
	{
		if (isalpha(ch))
			chars ++;
		else if (isspace(ch))
			whitespace++;
		else if (isdigit(ch))
			digits++;
		else if (ispunct(ch))
			punct++;
		else
			others++;
		cin.get(ch);
	}
	cout <<  chars << " letters, " 
	     <<  whitespace << " whitespace, "
	     << digits << " digits, "
	     << punct << " punctuations, "
	     << others << " others.\n";
	return 0;
}

結果:

Enter text for analysis and type @ to terminate input:
AdrenalVision Internationsl producer Adrienne Vismonger
announced production of their new 3-D film, a remake of
"My Dinner with Andre," scheduled for 2013.
@
123 letters, 23 whitespace, 5 digits, 6 punctuations, 0 others.

cctype中的字符函數:

| 函數名稱 | 返回值 |
|—|
| isalnum() | 如果參數是字母數字,即字母或數字,該函數返回true|
| isalpha() | 如果參數是字母,該函數返回true |
| iscntrl() | 如果參數是控制字符,該函數返回true |
| isdigit() | 如果參數是數字(0~9),該函數返回true |
| isgraph() | 如果參數是除空格之外的打印字符,該函數返回true |
| islower() | 如果參數是小寫字母,該函數返回true |
| isprint() | 如果參數打印字符(包括空格),該函數返回true |
| ispunct() | 如果參數是標點符號,該函數返回true |
| isspace() | 如果參數是標準空白字符,如空格、換行符、回車、製表符,該函數返回true |
| isupper() | 如果參數是大寫字母,該函數返回true |
| isxdigit() | 如果參數是十六進制,該函數返回true |
| tolower() | 如果參數是大寫字母,則返回小寫字母 |
| toupper() | 如果參數是小寫字母,則返回大寫字母 |

6.4 ?:運算符

C++常用?:運算符來代替if else語句,它C++中唯一的3個操作數的運算符。通用格式如下:

expression1 ? expression2 : expression3

如果expression1爲true,則整個表達式的值爲expression2;否則,整個表達式的值爲expression3。如下:

5 > 3 ? 10 : 12 //5>3爲true,所以該表達式的值爲19
3 == 0 ? 25 : 18 // 3==0爲false,所以表達式的值爲18

condit.cpp

#include <iostream>
int main()
{
	using namespace std;
	int a, b;
	cout << "Enter two integers: ";
	cin >> a >> b;
	cout << "The larger of " << a << " and " << b;
	int c = a > b ? a :b;
	cout << " is " <<  c << endl;
	return 0;
}

結果:

Enter two integers: 2 3
The larger of 2 and 3 is 3

將條件表達式嵌套在另一個條件表達式中,如下:

const char x[2][20] = {"Jason ", "at your serviece\n"};
const char * y = "Quillstone ";

for (int i = 0; i < 3; i++)
	cout << ((i < 2) ? !i ? x[i]:y : x[i]);

這是一種費解的方式,他按下面的順序打印3個字符串:

Jasn Qullstone at your service

從可讀性來說,條件運算符最適合簡單關係和簡單表達式的值。

6.5 switch語句

用戶從5個選項中選擇一個,雖然可以擴展if else if else來處理,但C++的switch語句能夠更容易地從大型列表中進行選擇。switch語句的通用格式:

switch (integer-expression)
{
	case label1: statement(s);
	case label2: statement(s);

	default: statement(s);
} 

switch.cpp

#include <iostream>
using namespace std;
void showmenu();
void report();
void comfort();
int main()
{
	showmenu();
	int choice;
	cin >> choice;
	while (choice != 5)
	{
		switch (choice)
		{
			case 1 : cout << "\a\n";
				break;
			case 2 : report();
				break;
			case 3 : cout << "The boss was in all day.\n";
				break;
			case 4 : comfort();
				break;
			default : cout << "That's not a choce.\n";
		}
		showmenu();
		cin >> choice;
	}
	cout << "Bye!\n";
	return 0;
}

void showmenu()
{
	cout << "Please enter 1,2,3,4,5:\n"
		"1) alarm	 2) report\n"
		"3) alibi	 4) comfort\n"
		"5) quit\n";
}

void report()
{
	cout << "It's been an excellent week for business.\n";
}

void comfort()
{
	cout << "Your employees think you are the fines CEO in the induesty.\n";
}

當用戶輸入5時,while循環結束。輸入1到4將執行switch列表中相應的操作,輸入6將執行默認語句。

同時,也可以使用字符(而不是整數)作爲菜單選項和switch標籤,則可以爲大寫標籤和小寫標籤提供相同的語句:

		char choice;
		switch (choice)
		{
			case 'a' :
			case 'A' : cout << "\a\n";
				break;
			case 'b' :
			case 'B' : report();
				break;
			case 'c' :
			case 'C' : cout << "The boss was in all day.\n";
				break;
			case 'd' :
			case 'D' : comfort();
				break;
			default : cout << "That's not a choce.\n";
		}

由於case 'a’後面沒有break語句,因此程序將執行下一行–case 'A’後面的語句。

6.5.1 將枚舉用作標籤

使用enum定義了一組相關常量,然後在switch語句中使用這些常量。通常,cin無法識別枚舉類型,因此該程序要求用戶選擇選項時輸入一個整數。將switch語句將int值和枚舉標籤進行對比時,將枚舉類型提升爲int。

enum.cpp

#include <iostream>
enum {red, orange, yellow, green, blue, violet, indigo};
using namespace std;
int main()
{
	cout << "Enter color code(0-6):";
	int code;
	cin >> code ;
	while (code >= red and code <= indigo)
	{
		switch(code)	
		{
			case red : cout << "Her lips were red.\n"; break;
			case orange : cout << "Her hair was orange.\n"; break;
			case yellow : cout << "Her sheos were yellow.\n"; break;
			case green : cout << "Her nails were green.\n"; break;
			default : cout << "Others.\n";
		}
		cout << "Enter color code (0-6):";
		cin >> code;
	}
	cout << "Bye!\n";
	return 0;
}

結果:

Enter color code(0-6):0
Her lips were red.
Enter color code (0-6):2
Her sheos were yellow.
Enter color code (0-6):6
Others.
Enter color code (0-6):7
Bye!

6.5.2 switch和if else

switch語句和if else語句都允許程序從選項中進行選擇。if else更通用,它可以處理取值範圍。而switch並不是爲處理範圍而設計的,switch語句中的每一個case標籤都必須時一個單獨的值。另外,這個值必須是整數(包括char),因此switch無法處理浮點測試。另外,case標籤值必須是常量。

6.6 break和continue

break和continue語句都是程序能過跳過部分代碼。可以在switch語句或任何循環中使用break語句,使程序跳到switch或循環後面的語句處執行。continue語句用於循環中,讓程序跳過循環體中餘下的代碼,並開始新一輪循環。如下圖:

jump.cpp

#include <iostream>
const int ArSize = 80;
int main()
{
	using namespace std;
	int letter = 0;
	char line[ArSize];
	cout << "Enter a line of text:\n";
	cin.get(line, ArSize);
	cout << "Complete line:\n " << line << endl;
	cout << "Line through first period:\n";
	for (int i = 0; line[i] != '\0'; i++)
	{
		cout << line[i];
		if (line[i] == '.')//遇到句號,結束循環
			break;
		if (line[i] == ' ') //只統計字母個數,空格跳過,則下面的語句將不會執行
			continue;
		letter++; //統計字母個數
		
	}
	cout << endl << letter << " letters.\n";
	return 0;
}

結果:

Enter a line of text:
Let's do lunch today. you can pay!
Complete line:
 Let's do lunch today. you can pay!
Line through first period:
Let's do lunch today.
17 letters.

程序說明

雖然continue語句導致該程序跳過循環體的剩餘部分,但不會跳過循環的更新表達式。在for循環中,continue語句使程序直接跳到更新表達式,然後跳到測試表達式。然而,對於while循環,continue將使程序直接跳到測試表達式,因此while循環中位於continue之後的更新表達式都被跳過。在某些情況下,這是一個問題。

6.7 讀取數字的循環

將一系列數字讀入數組中,並允許用戶在數組填滿之前結束輸入,利用如下代碼:

int n;
cin >> n;

如果用戶輸入一個單詞,而不是一個數字,發送這種類型匹配情況時,將發生4種情況:

  • n的值保持不變
  • 不匹配的輸入將留在輸入隊列種
  • cin對象中的一個錯誤標記被設置
  • 對cin方法的調用將返回false

假設編寫一個程序,來計算每天捕獲的魚的重量。這裏假設每天最多捕獲5條魚,因此一個包含5個元素的數組將足以存儲所以的數據,但也可能沒有捕獲這麼多。如果數組被填滿或輸入了非數字輸入,循環將結束。

cinfish.cpp

#include <iostream>
using namespace std;
const int Max = 5;
int main()
{
	double fish[Max];
	cout << "Please enter the weights of your fish.\n";
	cout << "You may enter up to " << Max << " fish < q to terminate>.\n";
	cout << "fish #1: ";
	int i = 0;
	while (i < Max and cin >> fish[i])
        {
		if (++i < Max)
			cout << "fish # " <<  i+1 << ": ";
	}
	double total = 0.0;
	for (int j= 0; j< i; j++)
		total += fish[j];
	if (i == 0)
		cout << "No fisht.\n";
	else 
		cout << total / i << " average weight of " << i << " fish.\n";
	return 0;
}

結果:

Please enter the weights of your fish.
You may enter up to 5 fish < q to terminate>.
fish #1: 10.2
fish # 2: 2.3
fish # 3: 4.5
fish # 4: q
5.66667 average weight of 3 fish.
[root@localhost ~]# ./a.out
Please enter the weights of your fish.
You may enter up to 5 fish < q to terminate>.
fish #1: q
No fisht.

上述程序中,cin>>fish[i]實際上是一個cin方法函數調用,該函數返回cin。如果cin位於測試條件中,則將被轉化爲bool類型。如果輸入成功,則轉換後爲true,否則爲false。

當用戶輸入的不是數字時,該程序將不再讀取輸入。下面再看一個例子,假設程序要求用戶提供5個高爾夫得分,以計算平均分。如果用戶輸入非數字,程序拒絕,並要求用戶繼續輸入數字。可以看到,可以使用cin輸入表達式來檢測輸入是不是數字。程序發現用戶輸入了錯誤內容時,應採取3個步驟:

  • 重置cin以接受新的輸入
  • 刪除錯誤輸入
  • 提示用戶重新輸入

cingolf.cpp

#include <iostream>
const int Max = 5;
using namespace std;
int main()
{
 	int golf[Max];
	cout << "Enter your golf scores.\n";
	cout << "You must enter " << Max << " rounds.";
	for (int i = 0; i < Max; i++)
	{
		cout << "Round# " << i+1 << " : " ;	
		while (!(cin >> golf[i]))
		{
			cin.clear();
			while(cin.get()!='\n')
				continue;
			cout << "Please enter a number: ";
		}
	}
	double total = 0.0;
	for (int i = 0; i< Max; i++)
		total += golf[i];
	cout << total/Max << " = average score " << Max << " rounds.\n";
	return 0;
}

結果:

Enter your golf scores.
You must enter 5 rounds.
Round# 1 : 88
Round# 2 : i
Please enter a number: k
Please enter a number: 4
Round# 3 : 5
Round# 4 : 9
Round# 5 : ?
Please enter a number: 44
30 = average score 5 rounds.

clear()方法重置輸入,如果省略這條語句,程序將拒絕繼續讀取輸入。程序中如下代碼的作用是:

while(cin.get()!='\n')
	continue;

讀取行尾之前的所有輸入,從而刪除這一行的錯誤輸入。

6.8 簡單文件輸入/輸出

C++使得將讀取鍵盤輸入和在屏幕上顯示輸出的技巧用於文件輸入/輸出(文件I/O)非常簡單。

6.81 文本I/O和文本文件

使用cin進行輸入時,程序將輸入視爲一系列的字節,其中每個字節都被解釋爲字符編碼。不管目標數據類型是什麼,輸入一開始都是字符數據–文本數據。然後,cin對象負責將文本轉換爲其他類型。

char ch;
cin >> ch;

輸入實例爲: 38.5 19.2

輸入行中的第一個字符被賦給ch。在這裏第一個字符是數字3,其字符編碼(二進制)被存儲在變量ch中。輸入和目標變量都是字符,因此不需要進行轉換。注意,這裏存儲的不是數值3,而是字符3的編碼。

int n;
cin >> n;

在這種情況下,cin將不斷讀取,直到遇到非數字符號。也就是說,它讀取3和8,這樣句點將成爲輸入隊列中的下一個字符。cin通過計算髮現,這兩個字符對應數字是38,因此將38的二進制編碼複製到變量n中。

接下來看double類型:

double x;
cin >> x;

在這種情況下,cin將不斷讀取,直到遇到第一個不屬於浮點數的字符。即,cin讀取3、8、句點和5,使得空格成爲輸入隊列中的下一個字符。cin通過計算髮現,這四個字符對應數字38.5,因此將38.5的二進制編碼複製到變量x中。

接下來看看char數組的情況:

char word[50];
cin >> word;

在這種情況下,cin將不斷讀取,直到遇到空白字符。即,它讀取3、8、句點和5,使得空格成爲輸入隊列中的下一個字符。然後,cin將這4個字符編碼存儲到輸入word中,並在末尾加上一個空字符,這裏需要進行任何轉換。

最後,看一下另一種使用char數組來存儲輸入的情況:

char word[50];
cin.getline(word,50);

在這種情況下,cin將不斷讀取,直到遇到換行符。所有字符都將被存儲到數組word中,並在末尾添加一個空字符。換行符被丟棄,輸入隊列中的下一個字符是下一行的第一個字符。這裏不進行任何轉換。

對於輸出,將執行相反的操作。即整數被轉換爲數字字符序列,浮點數被轉換爲數字字符和其他字符組成的字符序列。字符數據不需要做任何轉換。

這裏的要點是:輸入一開始都是文本。因此,控制檯輸入的文件版本是文本文件,即每個字節都存儲了一個字符編碼的文件。並非所有的文件都是文本文件,比如,數據塊和電子表格以數值格式(即二進制整數或浮點格式)存儲數值數據。

6.8.2 寫入的文本文件中

文件輸出:

  • 必須包含頭文件fstream;
  • 頭文件fstream定義了一個用於處理輸出的ofstream類;
  • 需要聲明一個或多個ofstream變量,並以自己喜歡的方式對其進行命名;
  • 必須指明命名空間std;
  • 需要將ofstream對象與文件關聯起來,爲此方法之一是使用open()方法;
  • 使用完文件後,應使用方法close()將其關閉;
  • 可結合使用ofstream和運算符<<來輸出各種類型的數據。

iostream頭文件提供了一個預先定義好的名爲cout的ostream對象,但您必須聲明自己的ofstream對象,爲其命名,並將其同文件關聯。聲明對象如下:

ofstream outFile;

關聯文件如下:

outFile.open("fish.txt");
char filename[50];
cin >> filename;
outFile.open(filename);

open()接受一個c-風格字符串作爲輸入,可以是字面字符串,也可以是存儲在數組中的字符串。

使用文件輸出的主要步驟如下:

  • 包含頭文件fstream;
  • 創建一個ofstream對象;
  • 將該ofstream對象同一個文件關聯起來;
  • 將像使用cout那樣使用該ofstream對象。(如:<<,endl和setf()都可用於ofstream對象)。

outfile.cpp

#include <iostream>
#include <fstream>
using namespace std;
int main()
{
	char automobile[50];
	int year;
	double a_price;
	double b_price;
	
	ofstream outFile;
	outFile.open("carinfo.txt");

	cout << "Enter the amke and model of automobile: ";
	cin.getline(automobile, 50);
	cout << "Enter the model year: ";
	cin >> year;
	cout << "Enter the original asing price: ";
	cin >> a_price;
	b_price = 0.913 * a_price;

	cout.precision(5);
	cout.setf(ios_base::showpoint);
	cout << "Make and model: " << automobile << endl;
	cout << "Year: " << year << endl;
	cout << "Was asing: $" << a_price << endl;
	cout << "Now asking: $" << b_price << endl;

	outFile.precision(5);
	outFile.setf(ios_base::showpoint);
	outFile << "Make and model: " << automobile << endl;
	outFile << "Year: " << year << endl;
	outFile << "Was asking: $" << a_price << endl;
	outFile << "Now asking: $" << b_price << endl;
	outFile.close();
	return 0;
}

結果:

在程序運行之前,並不存在carinfo.txt文件。在這種情況下,open()將新建一個名爲carinfo.txt的文件。如果在此程序運行前,該文件已存在。默認情況下,open()將首先截斷該文件,即將其長度截斷爲零—丟棄原有的內容,然後將新的輸入加入到該文件中。

6.8.3 讀取文本文件

文件輸入:

  • 必須包含頭文件fstream;
  • 頭文件fstream定義了一個用於處理輸入的ifstream類;
  • 需要聲明一個或多個ifstream變量,並以自己喜歡的方式對其進行命名;
  • 必須指明命名空間std;
  • 需要將ifstream對象與文件關聯起來,爲此方法之一是使用open()方法;
  • 使用完文件後,應使用方法close()將其關閉;
  • 可結合使用ifstream和運算符>>來輸出各種類型的數據;
  • 可以使用ifstream對象和get()方法來讀取一個字符,使用ifstream對象和getline()來讀取一行字符;
  • 可以結合使用ifstream和eof()、fail()等方法來判斷輸入是否成功;
  • ifstream對象本身被用作測試條件時,如果最後一個讀取操作成功,它將轉換爲true,否則爲false。

ifstream對象的聲明:

ifstream inFile;

關聯文件:

inFlie.open("bowling.txt");

如果試圖打開一個不存的文件用於輸入,這種錯誤將導致後面使用ifstream對象進行輸入時失敗。檢查文件是否被成功打開的方法:is_open()。

inFile.open("bowling.txt");
if (!inFile.is_open())
	exit(EXIT_FAILURE);

函數exit()的原型在頭文件cstdlib中定義的,在該頭文件中,還定義了一個用於同操作系統通信的參數數值EXIT_FAILURE。函數exit()終止程序。

方法is_open()是C++中比較新的內容。可以使用方法good()來代替。

sumafile.cpp

#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
const int SIZE = 60;
int main()
{
	char filename[SIZE];
	ifstream inFile;
	cout << "Enter name of data file: ";
	cin.getline(filename,SIZE);
	inFile.open(filename);
	if (!inFile.is_open())
	{
		cout << "Could not open the file " << filename << endl;
		cout << "Program terminating.\n";
		exit(EXIT_FAILURE);
	}
	double value;
	double sum = 0.0;
	int count = 0;
	
	inFile >> value;
	while (inFile.good())
	{
		++count ;
		sum += value;
		inFile >> value;
	}
	if (inFile.eof())
		cout << "End of file reached.\n";
	else if (inFile.fail())
		cout << "Input terminatd by data mismatch.\n";
	else 
		cout << "Input terminated for unknown reasion.\n";
	if (count == 0)
		cout << "No data processed.\n";
	else
	{
		cout << "Items read: " << count << endl;
		cout << "Sum: " << sum << endl;
		cout << "Average: " << sum/count << endl;
	}
	inFile.close();
	return 0;
}

結果:

文件循環讀取設計時,需要注意幾點。首先,程序讀取文件時不應超過EOF。如果最後一次讀取數據時遇到EOF,方法eof()返回true。其次,程序可能遇到類型不匹配,方法fail()返回true(如果遇到EOF,該方法也返回true)。最後,可能出現意外的問題,如文件損壞或硬件故障。如果最後一次讀取文件出現了這樣的問題,方法bad()將返回true。不要分佈檢查這些情況,一種更簡單的方式是使用good()方法,該方法在沒有發送任何錯誤時返回true。同時,可以使用其他方法來確定循環終止的原因,如下:

	if (inFile.eof())
		cout << "End of file reached.\n";
	else if (inFile.fail())
		cout << "Input terminatd by data mismatch.\n";
	else 
		cout << "Input terminated for unknown reasion.\n";

方法god()指出最後一次讀取輸入的操作成功與否。標準的做法:

	inFile >> value;
	while (inFile.good())
	{
		++count ;
		sum += value;
		inFile >> value;
	}

由於表達式inFile >> value的結果爲inFile,而在需要一個bool值的情況下,inFile的結果爲inFile().good(),即true或false。於是,兩條輸入語句用一條用作循環測試的語句代替。因此可以簡化上面標準做法,如下:

while(inFile >> value)
{
	sum += value;
	++count;
}

6.9 總結

if語句、if else語句和switch語句

邏輯運算符

文件輸出和輸入

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章