下面將全班平均成績問題通常化,考慮以下問題:ios
開發一個計算全班平均成績的程序,在每次程序運行時處理任意個成績數。c++
在第一個全班平均成績例子中,成績個數(10)是事先預置的。而本例中,則不知道要輸入多少個成績,程序要處理任意個成績數。程序怎麼肯定什麼時候中止輸入成績呢?什麼時候計算和打印全班平均成績呢?程序員
一種辦法是用一個特殊值做爲標記值(sentinelvalue),也稱信號值(signalvalue)、啞值(dummy value)或標誌值(flag value),表示數據輸入結束(「end of data entry」)用戶輸入成績,直到輸入全部合法成績。而後用戶輸入一個標記值,表示最後一個成績已經輸入。標記控制重複(sentinel-controlled repetition)也稱爲不肯定重複(indefinite repetition),由於執行循環以前沒法事先知道重複次數。算法
顯然,標記值不能與可接受的輸入值混淆起來。因爲考試成績一般是非負整數,所以能夠用-1做標記值。這樣,全班平均成績程序能夠處理9五、9六、7五、7四、89和-l之類的輸人流。程序計算並打印成績9五、9六、7五、74和89的全班平均成績(不計入-1,由於它是標記值)。編程
將選擇的標記值與可接受的輸入值混淆時會形成邏輯錯誤。ide
咱們用自上而下逐步完善(top-down,stepwise工具
refinement)的方法開發計算全班平均成績的程序,這是開發結構化程序的重要方法。咱們首先生成上層僞代碼表示:測試
Determine the class avcraqe for the quiz
上層僞代碼只是一個語句,表示程序的整體功能。這樣.上層等因而程序的完整表達式。但上層一般沒法提供編寫C++程序所需的足夠細節。所以要開始完善過程。咱們將上層僞代碼分解爲一系列的小任務,按其須要完成的順序列出。這個結果就是下列第一步完善(first,refinement):ui
Initialize variables Input,sum,and count the quiz grades Calculate and print the class average
這裏只用了順序結構,全部步驟按順序逐步執行。this
上層僞代碼及每一步完善都是算法的完整定義,只是詳細程度不一樣而已。
許多程序能夠在邏輯上分爲三個階段:初初化階段將程序變量初始化,處理階段輸入數據值和相應調整程序變量,結束階段計算和打印最後結果。
上述「軟件工程視點」一般是自上而下過程第一步完善的所有工做。要進行下一步完善(即第二步完善,second
refinement),咱們要指定特定變量,要取得數字的動態和以及計算機處理的數值個數,用一個變量接收每一個輸入的成績值,一個變量保存計算平均值。下列僞代碼語句:
Initialize variables
能夠細化成:
Initialize total to zero Initialize counter to zero
注意,只有total和counter變量要先初始化再使用,average和grade變量(分別計算平均值和用戶輸入)不須要初始化.由於它們的值會在計算或輸入時重定義。
下列僞代碼語句:
Input, sum, and count the quiz grades
須要用重複結構(即循環)連續輸入每一個成績。因爲咱們事先不知道要處理多少個成績,所以使用標記控制重複。用戶一次一項地輸入合法成績。輸入最後一個合法成績後,用戶輸人標記值。程序在每一個成績輸入以後測試其是否爲標記值.若是用戶輸入標記值,則順序循環終止。上述僞代碼語句的第二步完善以下:
Input the first grade (possibly the sentinel) While the user has not as yet entered the sentinel Add this grade into the running total Add one to the grade counter Input the next grade (possibly the sentinel)
注意,在這個僞代碼中,咱們沒有在while結構體中使用花括號,只是在while下面將這些語句縮排表示它們屬於while。僞代碼只是非正式的程序開發輔助工具。
下列僞代碼語句能夠完善以下:
If the counter is not equal to zero Set the average to the total divided by the counter Print the average else Print "No grades were entered"
注意咱們這裏要測試除數爲0的可能性,這是個致命邏輯錯誤,若是沒有發現,則會使程序失敗(一般稱爲爆炸或崩潰)。圖2.8顯示了全班平均成績問題第二步完善的完整僞代碼語句。
除數爲0是個致命邏輯錯誤。
進行除法時,要測試除數爲0的可能性,並在程序中進行相應處理(如打印一個錯誤消息).而不是讓致命邏輯錯誤發生。
圖2.6和圖2.8的僞代碼中增長了一些空行,使僞代碼更易讀。空行將程序分紅不一樣階段。
圖2.8所示的僞代碼算法解決更通常的全班平均成績問題,這個算法只進行了第二步完善,還須要進一步完善。
Initialize total to zero Initialize counter to zero Input the first grade (possibly the sentinel) While the user has not as yet entered the sentinel Add this grade into the running total Add one to the grade counter Input the next grade (possibly the sentinel) if the counter is not rqual to zero Set the average to the total divided by the counter Print the average else Print "No grades were entered"
圖2.8 用標記符控制重複解決全班平均成績問題的僞代碼算法
僞代碼算法的細節足以將僞代碼變爲C++代碼時,程序員便可中止自上而下逐步完善的過程,而後就可方便地實現C++程序。
圖2.9顯示了C++程序和示例執行結果。儘管只輸入整數成績,但結果仍然可能產生帶小數點的平均成績,即實數。int類型沒法表示實數,程序中引入float數據類型處理帶小數點的數(也稱爲浮點數,floatingpoint number),並引入特殊的強制類型轉換運算符(cast operator)處理平均值計算。這些特性將在程序以後詳細介紹。
// Fig. 2.9: fig02_09.cpp // Class average program with sentinel-controlled repetition. #include <iostream.h>
#include <iomanip.h> int main() { int total, // sum of grades gradeCounter, // number of grades entered grade; // one grade float average; // number with decimal point for average // initialization phase total = 0; gradeCounter = 0; // processing phase cout << "Enter grade, -1 to end: "; cin >> grade; while ( grade !=-1 ) { total = total + grade; gradeCounter = gradeCounter + 1; cout << "Enter grade, -1 to end: "; cin >> grade; } // termination phase if ( gradeCounter != 0 } { average - static_cast< float >( total ) / gradeCounter; cout << "Class average is "<< setprecision{ 2 ) << setiosflags( ios::fixed | ios::showpoint ) << average << endl; } else cout << "NO grades were entered" << endl; return 0; // indicate program ended successfully }
輸出結果:
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;
前面用一個輸出語句提示用戶輸入。
提示用戶進行每一個鍵盤輸入。提示應表示輸入形式和任何特殊輸入值(如用戶終止循環時輸入的標記值)。
在標記控制循環中,提示請求輸入數據項目時應顯式指定標記值是什麼值。
平均值並不必定老是整數值,而經常是包含小數的值,如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++也支持一元正(+)、負(-)運算符,程序員能夠編寫-七、+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。
如萊在使用浮點敷時認爲其精確地表示了敷值.則全獲得不正確的蛄柬。浮點敷僱大多數計算機上都採用近似表示。
不要比較浮點數值的相等和不等性,而要測試差值絕對值是否小於指定的值。
儘管浮點數算不老是100%精確,但其用途很廣。例如,咱們說正常體溫98.6(華氏溫度)時,並不須要精確地表示,若是溫度計上顯示98.6度.實際上多是98.5999473210643度。這裏顯示98.6對大多數應用已經足夠了。
另外一種獲得浮點數的方法是經過除法。10除以3獲得3.333333……,是無限循環小敷。計算機只分配固定空間保存這種值,所以只能保存浮點值的近似值。
2016考研複試技巧http://www.kyjxy.com/fushi/zhinan/
考研專碩備考資料http://www.kyjxy.com/zhuanshuo/
考研院校政策http://www.kyjxy.com/yuanxiao/zhengce/