附錄 C
透過示例
本C++ 程式設計書籍的附錄將嘗試為使用者提供對C++ 程式語言的補充實踐理解。它將是一個依賴於C++ 程式設計書籍中已經介紹的課程和理論內容的聚合,因此為了始終如一地列出主書中使用的所有可編譯示例程式,本附錄將有助於以實踐的方式重新整理你的知識,保證效能並允許更容易地維護使用的程式碼和測試示例的派生。
這是一項開放的工作,如果你發現術語或概念有任何問題,你可以透過貢獻來幫助它,你的參與是必需的,也是受歡迎的! 你也可以自由地陳述對實際書籍內容、結構或其他概念事項的任何偏好、缺點或願景,請參閱此 Wikibook 的討論頁面以獲取參與的正確論壇。
| 此C++ 程式設計 Wikibook頁面正在建設中。 它可能不完整或包含錯誤。請參閱Talk:C++ 程式設計/內容以進行討論。 |
前言
透過示例學習 C++ 程式設計可以用作學習該語言的另一種方法,透過將實踐置於理論之上。在任何情況下,這都需要你具備更高的專業知識水平。你需要了解 C++ 檔案是如何組織的,擁有並知道如何操作編譯器,以及瞭解在程式碼中不可見的某些細微差別。請理解,你將能夠在某種程度上閱讀和用 C++ 程式設計,但要真正理解該語言,不僅需要實踐,還需要理論。如有疑問,請隨時參考主書。
在本書中,我們介紹了在哪裡獲取編譯器(參見編譯器部分),這將為你提供繼續所需的工具。如果你沒有、不想或不需要在你的機器上安裝編譯器,你可以使用一個可在http://ideone.com(或http://codepad.org,但你必須更改程式碼以不依賴互動式輸入)獲得的免費 WEB 編譯器。
第 1 章: C++ 一種多正規化語言
- 這是本書的初始章節,它試圖向讀者介紹 C++ 語言,談論語言的歷史及其演變,提供概述,試圖傳達人們應該瞭解該語言的原因。
- 要理解 C++,首先必須確定什麼是程式語言,它們如何相互關聯(低階/高階),不同的程式設計正規化,程序式程式設計和麵向物件程式設計(物件和類、封裝、繼承、多重繼承、多型)、泛型程式設計等。作為一種允許,不僅提供一些有用的背景,而且對於有其他語言經驗的讀者來說,能夠理解與其他密切相關的語言相比,C++ 的特殊之處(C(C++ 的起源)、Java、C#、(C++/CLI)和 D)。
- 在本章中,讀者被要求檢查第一個 C++ 原始碼,常見的Hello World,並提供資源以逐步瞭解它。
Hello World - 編寫、編譯和執行 C++ 程式
下面是一個簡單的 C++ 程式示例
// 'Hello World!' program
#include <iostream>
int main()
{
std::cout << "Hello World!" << std::endl;
return 0;
}
編寫程式時,會使用開發環境。你的開發環境可以是基本的文字編輯器,也可以是功能豐富的 C++ 整合開發環境 (IDE)。你不應該使用像 Microsoft Word 這樣的文字處理器,因為它會向文字新增格式化程式碼。
如果還沒有可用的編譯器,請參閱本書的在哪裡獲取編譯器部分。
開啟你的開發環境,輸入顯示的程式(或複製貼上),並將其另存為hello.cc。
現在使用 C++ 編譯器編譯它
COMMAND_PROMPT> g++ hello.cc -o hello
此示例使用 GCC,即 GNU 編譯器集合(http://gcc.gnu.org),但你可以使用任何其他編譯器,或使用 IDE 進行編譯。上述命令將生成一個名為hello或hello.exe的可執行檔案。呼叫可執行檔案以執行你的第一個 C++ 程式
Unix
COMMAND_PROMPT> ./hello Hello World! COMMAND_PROMPT>
Microsoft Windows
COMMAND_PROMPT> dear hello Hello World! COMMAND_PROMPT>
斜體文字由你鍵入,粗體文字由程式輸出。如果你使用IDE,它可能會根據語法自動為你著色程式碼。
故障排除
- g++
- 命令未找到
你沒有安裝 GNU C++ 編譯器。如果你有其他編譯器,請檢視其文件以獲取正確的編譯命令。
- 錯誤的編譯器命令
很多奇怪的錯誤,多次提及
undefined reference to `std::basic_ostream' [..]
通常以以下結尾
collect2: ld returned 1 exit status
要使用g++編譯你的 hello.cc,請使用
g++ hello.cc -o hello
對於gcc,請使用
gcc hello.cc -o hello -lstdc++
- hello
- 命令未找到
你沒有鍵入完整路徑,請嘗試
./hello
是否存在hello此目錄中的程式?當你鍵入時,你能看到它嗎?ls?如果不是,則你的編譯(g++ hello.cc -o hello)失敗或你已更改到錯誤的目錄。
如果你未指定-o hello, g++命名輸出檔案a.out(彙編程式輸出),出於歷史原因。在這種情況下,請鍵入
./a.out
以執行程式。
解釋你的第一個 C++ 程式
預處理指令
C++ 的一些特性是語言的一部分,而另一些特性是標準庫的一部分。標準庫是每個符合標準的 C++ 編譯器都提供的程式碼體。當 C++ 編譯器編譯你的程式時,通常也會將其與標準 C++ 庫連結。
當你使用庫中的特性時,C++ 要求你宣告將要使用的特性。程式中的第一行是一個預處理指令。在我們的示例中,它顯示為粗體和斜體
- IOStreams 的預處理指令
#include <iostream>
此行導致 C++ 宣告位於
iostream 標頭檔案,需要在程式中包含它。通常,編譯器會將名為iostream的標頭檔案的內容插入到程式中。它插入的位置取決於系統。此類檔案的位置可能在編譯器的文件中有所描述。標準 C++ 標頭檔案的列表在標準標頭檔案參考表中。該iostream標頭檔案包含用於輸入/輸出 (I/O) 的各種宣告。它使用稱為流的 I/O 機制的抽象。例如,有一個名為std::cout的輸出流物件,用於將文字輸出到標準輸出。通常,這會將文字顯示在計算機螢幕上。
預處理器是編譯器的一部分,它在實際編譯器看到程式碼之前對程式碼進行一些轉換。例如,在遇到#include <iostream>指令時,它會用iostream標頭檔案的內容替換該指令。
main函式
int main()
{
// ...
}
以上幾行表示一段 C++ 程式碼塊,名為main。這樣的命名程式碼塊在 C++ 中稱為函式。程式碼塊的內容稱為函式的主體。
單詞int以粗體顯示,因為它是一個關鍵字。C++ 關鍵字具有一些特殊含義,並且也是保留字,即不能用於除了其預期用途之外的任何其他用途。另一方面main不是關鍵字,您可以在許多關鍵字無法使用的地方使用它(儘管不建議這樣做,因為可能會導致混淆)。
每個(符合標準的)C++ 程式都必須定義一個名為main的函式。程式的執行從此處開始。正如我們稍後將看到的,main可能會呼叫其他函式,而這些函式又可能呼叫其他函式。編譯器會安排在程式開始執行時呼叫main函式。(雖然這通常是正確的,但並非總是如此。有一個例外是main並非總是在一開始就被執行,我們稍後會看到。)
現在讓我們看看main函式內部的程式碼。
列印 Hello World!
在main中,第一行使用std::cout物件列印字串(字元序列)Hello World!並在行尾新增換行符。
std::cout << "Hello World!\n";
這一行是C++ 語句。C++ 語句以分號 (;) 結尾。在語句<<中,稱為插入運算子,用於使用std::cout流輸出字串。C++ 字串用雙引號 (") 括起來。引號本身不是字串的一部分,因此不會被列印。序列\n在字串中用於指示當前行的結尾。雖然該序列由兩個字元表示,但它只佔用一個字元的記憶體空間。因此,序列\n稱為換行符。換行的實際過程取決於系統,但 C++ 標準庫會為您處理,您無需關心。
對上述程式的修改
以下是同一個程式,進行了少量修改
// This program just displays a string and exits
#include <iostream>
int main()
{
std::cout << "Hello World!";
std::cout << std::endl;
return 0;
}
註釋
開頭新增的行
// This program just displays a string and exits
是一個註釋,試圖解釋程式碼的作用。註釋對於任何非平凡的程式都是必不可少的,這樣閱讀程式碼的人才能理解它預期做什麼。註釋分隔符之間包含的內容沒有限制。編譯器只是忽略註釋中的所有內容。在我們的示例中,註釋以斜體顯示。C++ 支援兩種形式的註釋
- 單行註釋以//開頭,一直延伸到行尾。這些也可以用於語句的右側,以解釋該語句的作用。
- 多行註釋以/*序列開頭,以*/序列結尾。這些可用於跨越多行的註釋。這些也稱為 C 樣式註釋,因為這最初是 C 中唯一可用的註釋型別。例如:
/* This program displays a string and then it exits */
有時註釋也用於括起我們暫時希望編譯器忽略但打算以後使用的程式碼。這在除錯(查詢程式中的錯誤或錯誤的過程)中非常有用。如果程式沒有給出預期的結果,可以透過“註釋掉”程式碼來跟蹤哪個特定的語句存在錯誤。由於 C 樣式註釋可以在行尾之前停止,因此這些可以用於“註釋掉”程式中一行內的少量程式碼。
重新整理輸出流緩衝區
每當您寫入(即傳送任何輸出)到輸出流時,它不會立即被寫入。它首先儲存在記憶體中,實際上可能會在將來的任何時間寫入。此過程稱為緩衝,用於儲存此類臨時資料的記憶體區域稱為緩衝區。有時需要重新整理輸出流緩衝區以確保所有資料都已寫入。這是透過將插入運算子應用於輸出流和物件std::endl來實現的。這就是
std::cout << std::endl;
行所做的操作。在重新整理緩衝區之前,std::endl
還會寫入一個換行符(這解釋了它的名稱,end line)。因此,在上一行列印的字串中省略了換行符。
返回成功程式碼
在大多數作業系統中,每個程式都允許使用稱為退出狀態的值與呼叫方通訊,以表明它是否已成功完成執行。按照約定,退出狀態為 0 表示成功,任何其他值表示失敗。不同的退出狀態值可用於指示不同型別的失敗。在我們的簡單程式中,我們希望以狀態 0 退出。mainC++ 允許
return 0;
函式返回一個整數,該整數將作為程式的退出狀態傳遞給作業系統。語句main使main返回 0。由於int函式需要返回一個整數,因此使用關鍵字main開始函式定義。此語句是可選的,因為編譯器會自動生成程式碼以在控制流出函式而沒有return語句的情況下為main函式返回 0。這就是為什麼第一個程式無需任何 return 語句就能工作的原因。請注意,這只是一個特殊情況,僅適用於
函式。對於其他函式,如果宣告它們返回任何內容,則必須返回一個值。return常見程式設計錯誤 1 雖然main語句是可選的,但不應宣告為返回void
(宣告為void的函式是不返回任何內容的函式),就像在 Java 等其他語言中一樣。一些 C++ 編譯器可能不會對此發出抱怨,但這是錯誤的。這樣做可能相當於返回儲存在特定記憶體位置或暫存器中的任何隨機數,具體取決於平臺。此做法也可能對某些作業系統造成潛在損害,這些作業系統依靠返回程式碼來確定如何處理崩潰或其他異常退出。
空白和縮排
// This program just displays a string and exits, variation 1
#include <iostream>
int main() { std::cout<<"Hello World!"; std::cout<<std::endl; return 0; }
空格、製表符和換行符(換行符)通常稱為空白。除了預處理指令和 C++ 樣式註釋在換行符處結束的規則外,這些都被編譯器忽略,除非在引號內。因此,上述程式也可以寫成如下形式
但是,請注意,空格是必需的,用於分隔相鄰的單詞和數字。為了使程式更易讀,必須適當地使用空白。
// This program just displays a string and exits, variation 2
#include <iostream>
int main() {
std::cout << "Hello World!";
std::cout << std::endl;
return 0;
}
使用空白來提高程式碼可讀性的約定構成了縮排風格。例如,使用其他縮排風格,程式可以這樣編寫
// This program just displays a string and exits
#include <iostream>
int main()
{
std::cout << "Hello World!";
std::cout << std::endl;
return 0;
}
或者這樣
第 1 章:可編譯示例
Hello World - 顯示字串 - 顯示字串1 - 顯示字串2
資料和變數
變數
// This program adds two numbers and prints their sum.
#include <iostream>
int main()
{
int a;
int b;
int sum;
sum = a + b;
std::cout << "The sum of " << a << " and " << b << " is " << sum << "\n";
return 0;
}
// This program adds two numbers and prints their sum, variation 1
#include <iostream>
#include <ostream>
using namespace std;
int main()
{
int a = 123, b (456), sum = a + b;
cout << "The sum of " << a << " and " << b << " is " << sum << endl;
return 0;
}
將兩個數字相加並列印它們的和
初學者程式設計師需要理解如何編寫一個對三個整數進行排序的程式。如果您想將其應用於稍後要納入現實生活情境的程式,這將非常有用。我使用此程式碼來展示如何在工作中應用此程式碼。
例如,如果您正在統計人員,例如 (1) 某個地區的居民密度或 (2) 員工人數以獲取人口統計資料。例如,如果您在人口普查局工作,並且想要衡量有多少人從鄉村搬到城市,您可能需要對這些數字進行排序。如果您想知道申請某項工作的女性人數是否多於男性,您將需要對這些整數進行排序。有時,此類排序函式可以在過濾並以從最大整數降序到最小整數的檢視顯示的網站上看到。在使用者介面 (UI) 的背後,當用戶單擊網站上的提交按鈕時,會呼叫一個排序函式。
#include <iostream>
#include <cmath>
using namespace std;
void sortNums(int& input1, int& input2, int& input3);
int main()
{
int x, y, z; // create variables
// Get numbers using cout and cin
cout << "Please enter 3 numbers." << endl;
cin >> x;
cin >> y;
cin >> z;
// Sort numbers: x, y, and z
sortNums(x, y, z); // calls the function titled sortNums
cout << x << ", " << y << ", " << z << endl; // outputs the numbers
return 0;
}
void sortNums(int &myNumA, int &myNumB, int &myNumC) // sort numbers
{
int temp; // create temp variable
if (myNumA > myNumB)
{
temp = myNumA;
myNumA = myNumB;
myNumB = temp;
}
if (myNumB > myNumC)
{
temp = myNumB;
myNumB = myNumC;
myNumC = temp;
}
if (myNumA > myNumB)
{
temp = myNumA;
myNumA = myNumB;
myNumB = temp;
}
}
此示例獲取 3 個整數(來自使用者的輸入)並對其進行排序。本節的主要目的是展示如何在現實生活情境中使用簡單的程式碼。
第 3 章:面向物件程式設計
第 4 章:高階功能
// very simple C++ program using a class.
#include <iostream>
class myClass
{
public:
myClass(int);
private:
int i;
};
myClass::myClass(int x) : i(x) {}
int main()
{
myClass my_class(5);
// dynamic
myClass* my_class_ptr = new myClass(5);
delete my_class_ptr;
return 0;
}
I/O 流
// This program just displays a string and exits
#include <iostream>
int main()
{
std::cout << "Hello World!";
std::cout << std::endl;
return 0;
}
// This program just displays a string and exits, variation 1
#include <iostream>
int main() { std::cout<<"Hello World!"; std::cout<<std::endl; return 0; }
// This program just displays a string and exits, variation 2
#include <iostream>
int main() {
std::cout << "Hello World!";
std::cout << std::endl;
return 0;
}