?? 02章 控制結構.txt
字號:
Print "No grades were entered"
圖2.8 用標記符控制重復解決全班平均成績問題的偽代碼算法
軟件工程視點2.6
偽代碼算法的細節足以將偽代碼變為C++代碼時,程序員即可停止自上而下逐步完善的過程,然后就可
方便地實現C++程序。
圖2.9顯示了C++程序和示例執行結果。盡管只輸入整數成績,但結果仍然可能產生帶小數點
的平均成績,即實數。int類型無法表示實數,程序中引入float數據類型處理帶小數點的數(也稱
為浮點數,floatingpoint number),并引入特殊的強制類型轉換運算符(cast operator)處理平均值計
算。這些特性將在程序之后詳細介紹。
1 // Fig. 2.9: fig02_09.cpp
2 // Class average program with sentinel-controlled repetition.
3 #include <iostream.h>
4 #include <iomanip.h>
5
6 int main()
7 {
8 int total, // sum of grades
9 gradeCounter, // number of grades entered
10 grade; // one grade
11 float average; // number with decimal point for average
12
13 // initialization phase
14 total = 0;
15 gradeCounter = 0;
16
17 // processing phase
18 cout << "Enter grade, -1 to end: ";
19 cin >> grade;
2O
21 while ( grade !=-1 ) {
22 total = total + grade;
23 gradeCounter = gradeCounter + 1;
24 cout << "Enter grade, -1 to end: ";
25 cin >> grade;
26 }
27
28 // termination phase
29 if ( gradeCounter != 0 } {
30 average - static_cast< float >( total ) / gradeCounter;
31 cout << "Class average is "<< setprecision{ 2 )
32 << setiosflags( ios::fixed | ios::showpoint )
33 << average << endl;
34 }
35 else
36 cout << "NO grades were entered" << endl;
37
38 return 0; // indicate program ended successfully
39 }
輸出結果:
Enter grade, -1 to end: 75
Enter grade, -1 to end: 94
Enter grade, -1 to end: 97
Enter grade,-1 to end: 88
Enter grade, -1 to end: 70
Enter grade, -1 to end: 64
Enter grade, -1 to end: 83
Enter grade, -1 to end: 89
Enter grade, -1 to end: -1
Class average is 82.50
圖2.9 用標記符控制重復解決全班平均成績問題的C++程序和示例執行結果
注意圖2.9中while循環中的復合語句。如果沒有花括號,則循環體中的最后三條語句會放到循環以外,使計算機錯誤地理解如下代碼:
while { grade ! = -1 )
total - total + grade;
gradeCounter = gradeCounter + 1;
cout << "Enter grade, -1 to end:";
cin >> grade;
如果用戶輸入的第一個成績不是-l,則會造成無限循環。
注意下列語句:
cin >> grade;
前面用一個輸出語句提示用戶輸入。
編程技巧2.10
提示用戶進行每個鍵盤輸入。提示應表示輸入形式和任何特殊輸入值(如用戶終止循環時輸入的標記值)。
編程技巧2.11
在標記控制循環中,提示請求輸入數據項目時應顯式指定標記值是什么值。
平均值并不一定總是整數值,而常常是包含小數的值,如7.2或-93.5。這些值稱為浮點數,用數據類型float表示。變量average聲明為數據類型float,以獲得計算機結果中的小數。但total/gradeCounter的計算結果是整數,因為total和gradeCounter都是整數變量。兩個整數相除是整除(integer division),小數部分丟失(即截尾,truncated)。由于先要進行計算,因此小數部分在將結果賦給average之前已經丟失。要用整數值進行浮點數計算,就要先生成用于計算的臨時浮點數值。
C++提供了一元強制類型轉換運算符(unary cast operator)。下列語句:
average = static cast< float >(total) / gradeCounter;
包括一元強制類型轉換運算符static_cast<float>(),生成用于計算的臨時浮點數值(total)。這樣使用強制類型轉換運算符稱為顯式類型轉換(explicit conversion)。total中存放的值還是整數,而計算時則用浮點數值(total的臨時float版本)除以整數gradcCounter。
c++編譯器只能對操作數的數據類型一致的表達式求值。要保證操作數的數據類型一致,編譯器對所選擇的操作數進行提升(promotion)操作(也稱為隱式類型轉換,implicit conversion)。例如,在包含數據類型float和int的表達式中,int操作數提升為float。本例中,gradeCounter提升為float之后進行計算,將浮點數除法得到的結果賦給average。本章稍后將介紹所有標準數據類型及其提升順序。任何數據類型都可用強制類型轉換運算符,static_cast運算符由關鍵字statlc cast加尖括號(<>)中的數據類型名組成。強制類型轉換運算符是個一元運算符(unary perator),即只有一個操作數的運算符。第1章曾介紹過二元算術運算符。C++也支持一元正(+)、負(-)運算符,程序員可以編寫-7、+5之類的表達式。強制類型轉換運算符從右向左結合,其優先級高于正(+)、負(-)運算符等其他一元運算符,該優先級高于運算符*、/和%,但低于括號的優先級。優先級表中用static_cast<type>()表示強制類型轉換運算符。
圖2.9中格式化功能將在第11章詳細介紹,這里先做一簡要介紹。下列輸出語句中調用
setpreclslon(2):
cout<<"Class average is" << setprecision(2)
<< Setiosflaqs(iOS::fixed |iOS::showpoint)
<<averaqe<<endl;
表示float變量average打印小數點右邊的位數為兩位精度(precision),例如92.37,這稱為參數化流操縱算子(parameterized stream manipulator)。使用這些調用的程序要包含下列預處理指令:
#include<iomanip.h>
注意endl是非參數化流操縱算子(nonparameterized stream manipulator),不需要iomanip.h頭文件。如果不指定精度,則浮點數值通常輸出六位精度(即默認精度,default precision),但稍后也會介紹一個例外。
上述語句中的流操縱算子setiosflags(ios::fixed | ios::showpoInt)設置兩個輸出格式選項ios::fixed和ios::showpoint。垂直條(1)分隔setiosflags調用中的多個選項(垂直條將在第16章詳細介紹)。選項ios::fixed使浮點數值以浮點格式(而不是科學計數法,見第ll章)輸出。即使數值為整數,ios::showpoInt選項也會強制打印小數點和尾部O,如88.OO。如果不用ios::showpoint選項,則C++將該整數顯示為88,不打印小數點和尾部o。程序中使用上述格式時,將打印的值取整,表示小數點位數,但內存中的值保持不變。例如,數值87.945和67.543分別輸出為87.95和67.54。
常見編程錯誤2.10
如萊在使用浮點敷時認為其精確地表示了敷值.則全得到不正確的蛄柬。浮點敷雇大多數計算機上都采用近似表示。
編程技巧2.12
不要比較浮點數值的相等和不等性,而要測試差值絕對值是否小于指定的值。
盡管浮點數算不總是100%精確,但其用途很廣。例如,我們說正常體溫98.6(華氏溫度)時,并不需要精確地表示,如果溫度計上顯示98.6度.實際上可能是98.5999473210643度。這里顯示98.6對大多數應用已經足夠了。
另一種得到浮點數的方法是通過除法。10除以3得到3.333333……,是無限循環小敷。計算機只分配固定空間保存這種值,因此只能保存浮點值的近似值。
2.10 構造算法與自上而下逐步完善:實例研究3(嵌套控制結構)
下面介紹另一個問題。這里還是用偽代碼和自上而下逐步完善的方法構造算法,然后編寫相應的C++程序。我們介紹過按順序堆疊的控制結構,就像小孩堆積木一樣。這里顯示C++中控制結構的另一種方法,稱為嵌套控制結構。
考慮下列問題:
學校開了一門課,讓學生參加房地產經紀人證書考試。去年,幾個學生讀完這門課并參加了證 書考試。學校想知道學生考試情況,請編寫一個程序來總結這個結果。已經得到了10個學生 的名單,每個姓名后面寫1時表示考試通過,寫2時表示沒有通過。
程序應分析考試結果,如下所示:
1.輸入每個考試成績(即l或2),每次程序請求另一個考試成績時,在屏幕上顯示消息“Enter result"。
2.計算每種類型的考試成績數。
3.顯示總成績,表示及格人數和不及格人數。
4.如果超過8個學生及格,則打印消息“Raise tuition”。
認真分析上述問題后,我們做出下列結論:
1.程序要處理10個考試成績,用計數器控制循環。
2.每個考試成績為數字l或2,每次程序讀取考試成績時,程序要確定成績是否為數字1或2。
我們的算法中測試1,如果不是l,則我們假設其為2(本章末尾的練習會考慮這個假設的結果)。
3,使用兩個計數器,分別計算及格人數和不及格人數。
4.程序處理所有結果之后,要確定是否有超過8個學生及格。
下面進行自上而下逐步完善的過程。首先是上層的偽代碼表示:
Analyze exam results and decide if tuition should be raised
我們再次強調,頂層是程序的完整表達,但通常要先進行幾次完善之后才能將偽代碼自然演變成C++程序。我們的第一步完善為:
Initialize variables
lnput the ten quiz qrades and COU~t passes and failures
Print a sugary Of the cxam results and decide if tuition should be raised
這里雖然有整個程序的完整表達式,但還需要進一步完善。我們要提供特定變量。要用兩個計數器分別計算,用一個計數器控制循環過程,用一個變量保存用戶輸入。偽代碼語句:
Initialize variables
可以細分如下:
Initialize passes to zero
lnitialize failules to zero
Inltiallze student counter to One
注意.這里只初始化計數器和總和。偽代碼語句:
Input the ten quiz grades and count Passes and faiLures
要求循環輸入每個考試成績。我們事先知道共有10個成績,因此可以用計數器控制循環。在循環中(即嵌套在循環中),用一個雙項選擇結構確定考試成績為數字1或2,并遞增相應的計數器。上述偽代碼語句細化如下:
while student counter is less than or equal to ten
Input the next exam result
if the student passed
Add one to Passes
else
Add One to failures
Add one to student counter
注意這里用空行分開if/else控制結構,以提高程序可讀性。偽代碼語句:
Print a sugary Of the exam results and declde if tuition should be raised
可以細化如下:
Print the number of passes
Print the number of filuies
if more than eight students Passed
Priht "Raise tuition"
圖2.10顯示了完整的第2步完善結果。注意這里用空行分開while結構,以提高程序可讀性。
Initlalize passes to zero
Init±a1ize failures to zero
lnitlallze student counter to one
while student counter is less than or equal to ten
Input the next exam result
if the student Passed
Add one to passes
else
Add one to failures
Add one to student counter
Priht the number of passes
Prirt the number of filures
if more than eight students passed
Print”Raise tuition'’
圖2.10檢查考試成績的偽代碼
這個偽代碼語句已經足以轉換為C++程序。圖2.11顯示了C++程序及示例的執行結果。注意,
我們利用C++的一個特性,可以在聲明中進行變量初始化。循環程序可能在每次循環開頭要求初始
化,這種初始化通常在賦值語句中進行。
1 // Fig. 2.11: fig02_ll.cpp
3 #include <iostream.h>
4
5 int main()
6 {
// initialize variables in declarations
int passes = 0, // number of passes
Passes = v; // number or passes
failures = 0, // number of failures
studentCounter = 1, // student counter
result; // oue exam result
// process 10 students; counter-controlled loop
while ( studentCounter <= 10 ) {
cout << "Enter result (1=pass,2=fail): ";
cin >> result;
if { result == 1 } // if/else nested in while
passes = passes + 1;
else
failures = failures + 1;
studentcounter = studentCounter + 1;
)
// termination phase
cout << "Failed" << failures << endl;
if ( passes > 8 )
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -