程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C++啟蒙之控制結構

C++啟蒙之控制結構

編輯:關於C++

語句是按次序執行的:同一個函數中第一個語句首先執行,接著執行第二個……當然,少數的程序--包括我們需要編寫的解決書店問題的程序--可以只使用一個次序執行。作為代替,編程語言提供了多種控制結構,允許更加復雜的執行路徑。這一部分將簡單地介紹C++提供的一些控制結構。

練習7:

編譯一個包含錯誤的嵌套注釋的程序。

練習8:

指出下面哪些輸出語句是合法的:

std::cout << "/*";
std::cout << "*/";
std::cout << /* "*/" */;

在你作出判斷之後,編譯這三個語句測試自己的答案。糾正自己遇到的錯誤。

1、while語句

While語句用於迭代執行。我們可以使用while編寫一個程序來計算1到10之間數字的和:

#include <iostream>
int main()
{
int sum = 0, val = 1;
// 持續執行
while
until
val
is greater than 10
while (val <= 10) {
sum += val; // 賦值 sum + val 賦給sum
++val; // 增加 給val加1
}
std::cout << "Sum of 1 to 10 inclusive is "
<< sum << std::endl;
return 0;
}

該程序編譯和執行以後打印出:

Sum of 1 to 10 inclusive is 55

像前面的例子一樣,我們先包含了iostream頭文件並定義了一個main函數。在main函數中我們定義了兩個整型變量:sum保存數字的和,val表示從1到10的值。我們給sum賦了一個初始值0,val的開始值為1。

其中的重要部分是while語句。While的形式如下

while (condition) while_body_statement;

While周期性地測試condition(條件)並執行相關的語句,直到條件為假。

條件是一個表達式,我們可以計算它的值,這樣才能測試其結果。如果結果值非零,那麼條件為真;如果值為零那麼條件為假。

如果條件是真的(表達式計算出的值非零),那麼就執行while_body_statement。在執行while_body_statement之後,再次測試條件。如果條件仍然是真的,那麼就再次執行while_body_statement。While持續執行,要麼測試條件,要麼執行while_body_statement直到條件為假。

在這個程序中,while語句是:

// 持續執行
while
until
val
is greater than 10
while (val <= 10) {
sum += val; // 賦值 sum + val 賦給sum
++val; // 增加 給val加1
}

上面的While中的條件使用小於或等於操作符(<=操作符)來比較val的當前值與10的大小。只要val小於或等於10,我們就執行while的主體。在這種情況下,while的主體是一個包含兩個語句的代碼塊:

{
sum += val; // 賦值 sum + val 賦給sum
++val; // 增加 給va l加1
}

代碼塊是用波浪括號包含的語句序列。在C++中,代碼塊可以用於任何能夠使用語句的位置。代碼塊中的第一個語句使用了復合賦值操作符(+=操作符)。這個操作符把右邊的操作數加上左邊的操作數。它的效果與下面的賦值語句相同:

sum = sum + val; // 賦值 sum + val 賦給sum

因此,第一個語句把val的值與sum的當前值相加,並把結果存放到sum中。

下一個語句

++val; // 增加 給val加1

使用了前綴增量操作符(++操作符)。增量操作符給自己的操作數加1。++val與val = val + 1是相同的。

在執行while主體之後我們再次執行while中的條件。如果(現在已經增加了的)val值仍然小於或等於10,那麼就再次執行while的主體。循環繼續,測試條件和執行主體,直到val不再小於或等於10。

一旦val大於10,我們就跳出while循環並執行while後面的語句。在例子中,語句打印輸出信息,然後返回,終止main程序。

C++程序的縮排和格式化

C++程序的格式在很大程度上是自由的,這意味著波浪括號、縮排、注釋和新行通常對程序的含義是沒有影響的。例如,表示main開始的波浪括號可以與main在同一行,而我們把它放在了下一行,或放在任何我們喜歡的位置。唯一的要求是它必須是main參數列表反括號後面的第一個非空格、非注釋符號。

盡管我們對程序格式化有很大的自由度,但是我們的選擇會影響程序的可讀性。例如,我們可以把main函數寫在一個很長的行中。這種定義盡管是合法的,但是卻難以閱讀。

如何對C或C++程序進行正確的格式化一直存在爭論。我們認為並不是只存在一種正確的樣式。我們傾向於把定義函數邊界的波浪括號放在它們自己的行中。我們傾向於縮排輸入或輸出表達式,這樣操作符可以排列起來,就像我們編寫main函數中的輸出語句一樣。隨著我們的程序越來越復雜,其它一些縮排習慣會清晰起來的。

我們要記住,用其它的方式格式化程序也是可行的。當選擇某種格式樣式的時候,請考慮它對可讀性和理解力的影響。一旦你選擇了某種樣式,就一致性地使用它。

2、for語句

在我們的while循環中,我們使用變量var來控制循環中迭代的次數。每次經過while的時候,都測試val值,然後增加主體中的val值。

使用像val那樣的變量來控制循環是經常用到的,語言也提供了第二種控制結構,叫做for語句,它簡化了管理循環變量的代碼。我們將使用for循環來重新編寫一個計算1到10的和的程序:

#include <iostream>
int main()
{
int sum = 0;
// 計算1到10之間所有數字的和
for (int val = 1; val <= 10; ++val)
sum += val; //等同於sum = sum + val
std::cout << "Sum of 1 to 10 inclusive is "
<< sum << std::endl;
return 0;
}

我們在前面的for循環中定義了sum,並把它設置為零。變量val只在迭代內部使用,並且是作為語句自身的一部分定義的。

For語句

for (int val = 1; val <= 10; ++val)
sum += val; // 等同於 sum = sum + val

有兩個部分:for頭和for主體。頭控制主體執行的次數。頭本身包含三個部分:初始化語句、條件和表達式。在這種情況下,初始語句

int val = 1;定義了一個整型的叫做val的對象並把它的初始值設置為1。初始語句只在進入for的時候執行一次。條件val <= 10比較當前值與10的大小,每次循環的時候都會測試它的值。只要val小於或等於10,就執行for主體。執行主體之後才執行表達式。在這個for中,表達式使用了前綴增長操作符,就是給val的值加上1。在執行表達式之後,for繼續測試條件。如果val的新值仍然小於或等於10,那麼接著執行for循環主體,val的值繼續增長。執行過程一直持續,直到條件失敗為止。

在這個循環中,for主體執行了求和操作:

sum += val; // 等同於 sum = sum + val

上面的主體使用復合賦值操作符把當前的val值增加給sum,並把結果存回sum。

扼要地重述,這個for的全部執行流程是:

1.建立val並把它的初始值設為1。

2.測試val的值是否小於或等於10。

3.如果val小於或等於10就執行for主體,把val加上sum。如果val並非小於或等於10,那麼就終止循環,繼續執行循環後面的第一個語句。

4.增加val的值。

5.重復步驟2中的測試,只要條件為真就繼續它後面的步驟。

請注意:

當我們退出for循環的時候,就再也不能訪問變量val了。在這個循環終止之後不能使用val。但是,並非所有的編譯器都有這個強制條件。

回顧編譯過程

編譯器任務的一部分是檢查程序文本中的錯誤。編譯器不能檢測程序的含義是否正確,但是它可以檢測程序形式的錯誤。下面是編譯器可能檢測到的一些通常的錯誤。

1.語法錯誤。程序員犯了C++語法錯誤。下面的程序演示了通常的語法錯誤;下面行中的每個注釋都描述了錯誤信息:

// error: missing ')' in parameter list for main
int main ( {
// error: used colon, not a semicolon after endl
std::cout << "Read each file." << std::endl:
// error: missing quotes around string literal
std::cout << Update master. << std::endl;
// ok: no errors on this line
std::cout << "Write new master." <<std::endl;
// error: missing ';' on return statement
return 0
}

2.類型錯誤。C++中每個數據條目都有相關的類型。例如10是個整數。單詞"hello"是字符串文本。類型錯誤的例子有給希望接收整型參數的函數傳遞了字符串文本。

3.聲明錯誤。C++中使用的每個名字都必須在使用之前先定義。沒有定義名字通常導致錯誤消息。最常見的聲明錯誤是在訪問類庫中的名字的時候忘了使用std::,或者不注意拼錯了提示符的名稱:

#include <iostream>
int main()
{
int v1, v2;
std::cin >> v >> v2; // error: uses " v "not" v1"
// 不能定義,應該是 std::cout
cout << v1 + v2 << std::endl;
return 0;
}

錯誤消息包含一個行號和編譯器認為的錯誤的描述。按照錯誤報告的次序修改錯誤是很好的經驗。通常一個錯誤會有級聯效應並引起編譯器報告比實際情況多的錯誤。每次修補以後或者至少在修補了少量的明顯錯誤之後,重新編譯代碼也是很好的經驗。這個循環就是眾所周知的編譯-編譯-調試。

練習9:

下面的for循環實現什麼功能?Sum之後的值是多少?

int sum = 0;
for (int i = -100; i <= 100; ++i)
sum += i;

練習10:

編寫一個程序使用for循環統計50到100之間所有數字的和。然後重新使用while編寫一遍。

練習11:

編寫一個程序使用while循環打印從10到0的數字。然後用for重新編寫一次。

練習12:

比較你在前面兩個練習中編寫的循環。使用每種形式都有些什麼優缺點?

練習13:

編譯器對診斷信息的理解是不同的。編寫一些包含了上面討論的普通錯誤的程序。研究編譯器產生的消息,這樣就可以熟習自己遇到的消息,以適應更復雜的程序。

3、if語句

作為對1和10之間的數字求和的邏輯擴展,我們可以計算用戶提供的兩個數字之間所有值的和。我們可以在for循環中直接使用數字,把第一個數字作為下邊界,第二個作為上邊界。但是,如果用戶提供的第一個數字較大,這個策略就失敗了:我們的程序會立即退出for循環。作為代替,我們應該調整范圍,使較大的數字作為上邊界,較小的數字作為下邊界。為了實現這個功能,我們需要辨別哪個數字比較大的途徑。

與多數語言一樣,C++語言也提供了if語句支持條件執行。我們可以使用if語句修改過的求和程序:

#include <iostream>
int main()
{
std::cout << "Enter two numbers:" << std::endl;
int v1, v2;
std::cin >> v1 >> v2; // 讀取輸入
// 把較小的數字作為下邊界,較大的數字作為上邊界
int lower, upper;
if (v1 <= v2) {
lower = v1;
upper = v2;
} else {
lower = v2;
upper = v1;
}
int sum = 0;
// 求下邊界與上邊界之間的數字的和
for (int val = lower; val <= upper; ++val)
sum += val; // sum = sum + val
std::cout << "Sum of " << lower
<< " to " << upper
<< " inclusive is "
<< sum << std::endl;
return 0;
}

如果我們編譯並執行這個程序,並輸入數組7和3,這個程序的輸出信息是:

Sum of 3 to 7 inclusive is 25

這個程序中的大多數代碼與前面例子中的相同。該程序先提示用戶並定義了四個整型變量。接著它從標准的輸入中讀取信息到v1和v2。唯一的新代碼是if語句

// 把較小的數字作為下邊界,較大的數字作為上邊界
int lower, upper;
if (v1 <= v2) {
lower = v1;
upper = v2;
} else {
lower = v2;
upper = v1;
}

這段代碼的效果就是適當地設置upper和lower。其中的if條件測試v1是否小於或等於v2。如果是這樣的,我們就立即執行條件後面的代碼塊。這個代碼塊包含兩個語句,每個語句執行一次賦值操作。第一個語句把v1賦給lower,把v2賦給upper。

如果該條件為假--也就是說v1大於v2--那麼我們就執行else後面的語句。同樣,這個語句也是包含兩個賦值操作的代碼塊。我們把v2賦給lower,把v1賦給upper。

4、讀取未知數量的輸入信息

我們進一步對這個程序進行修改,允許用戶指定一組數字來求和。在這種情況下,我們不知道加上多少個數字。作為代替,我們希望保持讀取數字狀態,直到程序達到輸入信息的末尾。當輸入結束以後,程序給標准輸出寫入它們的和:

練習14:

如果輸入的數字是相等的,這個程序會怎麼辦?

練習15:

編譯和運行這一部分的程序,輸入兩個相等的值。把其輸出值與你預計的值進行對比。解釋兩者之間的不一致。

練習16:

編寫一個程序打印出用戶提供的兩個輸入信息中較大的一個。

練習17:

編寫一個程序讓用戶輸入一系列的數字。打印出一個消息,說明這些數字中有多少個負數。

#include <iostream>
int main()
{
int sum = 0, value;
// 讀取直到文件尾,計算讀取的值
while (std::cin >> value)
sum += value; // 等同於 sum = sum + value
std::cout << "Sum is: " << sum << std::endl;
return 0;
}

如果我們提供給這個程序的輸入信息是:3 4 5 6

那麼輸入結果將會是:

Sum is: 18

像通常一樣,我們先包含了必要的頭文件。Main函數中的第一行定義了兩個變量,分別是sum和value。我們將使用value來保存我們讀取的每個數字,這是在while條件內部實現的:

while (std::cin >> value)

此處發生的操作就是對條件的計算,輸入操作

std::cin >> value

被執行,它的效果是從標准的輸入中讀取下一個數字,把讀取的內容保存到value中。這個輸入操作符返回左邊的操作數。條件測試了這個結果,也就是測試了std::cin。

當我們把istream作為條件的時候,其效果是測試流的狀態。如果流是有效的--也就是說,仍然能夠讀取另外一個輸入--那麼測試是成功的。當我們輸入文件結尾標識或遇到無效的輸入(例如讀取的值不是整數)的時候,istream就變成無效的。Istream處於無效狀態將導致條件失敗。

測試將一直成功並執行while主體,直到我們的確遇到文件尾標識(或其它的輸入錯誤)。它的主體是一個語句,使用了復合賦值操作符。這個操作符把右邊的操作數加到左邊的操作數上。

在鍵盤上輸入文件尾標識

不同的操作系統使用的文件尾標識值不同。在Windows系統上我們通過按control-z--同時按下"ctrl"和"z"來輸入文件尾標識。在Unix系統中(包括Mac OS-X計算機),通常是control-d。

一旦測試失敗了,while就終止了,我們將跳出循環並執行while後面的語句。這個語句打印出sum和endl(它打印出新行並刷新與cout關聯的緩沖器)。最後,我們執行了return(返回),它通常返回0表明成功了。

練習18:

編寫一個程序,提示用戶輸入兩個數字,在標准的輸出中寫入兩個數字之間的所有數字。

練習19:

如果上面的練習中給出的數字是1000和2000會發生什麼情況?修改前面的程序,使它不要在每一行輸出10個以上的數字。

練習20:

編寫一個程序來計算用戶給定的范圍之間的數字的和,略過設置上下邊界的if測試。預計一下如果輸入信息是7和3會發生什麼情況。現在運行程序,並輸入7和3,看看結果是否跟你的預計相同。如果不同,重新研究一個對for和while循環的討論內容,直到理解發生的情況。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved