【學習筆記】《C++ Primer Plus》
目錄
想說的話:打算學好C++,計劃從C++ Primer Plus開始。在學習過程中遇到我不瞭解的或者感興趣的,會花大篇幅來做筆記;對於很熟悉的內容在書上過一遍後,不會記錄在本文中。這也算是對本科所學的一次系統的複習。
Stay hungry ,stay foolish.
第一章 預備知識
泛型程式設計:generic programming
第二章 開始學習C++
C語言的傳統是標頭檔案使用副檔名.h,C++則沒有副檔名。
1、名稱空間
以廠商為例,名稱空間指代不同的廠商,這樣將多個廠商的程式碼組合時不會互相混淆。
Micro::func(1);
Macro::func(1);
也可以用using編譯指令,using namespace Micro,使得Micro名稱空間中的所有名稱可用。名稱空間管理技術以後再表。
2、定義變數
C++的做法是儘可能在首次使用變數前宣告它。(為什麼要宣告變數?防止拼寫錯誤而使用了錯誤的變數。。)
3、賦值語句
- 等號表示式的值為左值,從右往左計算:b=a=1;即可以連續賦值。
- 逗號表示式的值為右值,從左往右計算:int i = 0; int n = (i += 2, i++); n結果為2。
第三章 處理資料
1、變數名
以兩個下劃線或下劃線和大寫字母開頭的名稱被保留給編譯器,以一個下劃線開頭的名稱也被保留,用作全域性識別符號。如_time_stop、_Dount雖然可以通過編譯但不建議。
2、整形
規定整形長度為:2B <= short <= 4B <= int <= long <= 8B <=long long
對於有符號整數,假設長為n位(bit),則其表示範圍為 [-2^(n-1),2^(n-1)-1]。指數減一是因為留一位給符號位,結果減一是因為最高位為n-2。如signed short 範圍為-2^15到2^15-1(-32768~32767) 。無符號數的表示範圍擴大一倍即可。
如何判斷溢位?逆向運算再比較:
int tadd_ok(int x,int y){ int sum=x+y; return (sum-x==y)&&(sum-y==x); }
cout<<hex cout<<oct分別輸出16進位制、8進位制整數。
3、浮點數
浮點數表示帶小數的數字,一部分表示值,另一部分用於對值進行放大和縮小。
float的儲存方式如下圖所示:
double的儲存方式為:
第四章 複合型別
1、字串
a) 概念
在C++中,單引號表示字元常量,如 ‘S’;雙引號表示字串常量,如 “S”。
字元常量:‘S’ 只是83的另一種寫法,本質是ASCII碼
字串常量:“S” 其實是由字元S和字元\0 組成的字串。實際上,“S”表示的是字串所在的記憶體地址。、
b) 字串輸入
cin使用空白(空格、製表符和換行符)來確定字串結束的位置,所以用cin輸入“aaa bbb”時,第一個字串接收aaa,第二個接收bbb。要解決這個問題可以用getline() 和 get() 。cin.get() 經常用來接收輸入流中未被接收的換行符。
int main(){
//每次讀取一行帶空格的字串
using namespace std;
const int size = 20;
char name[size];
char dessert1[size];
char dessert2[size];
cout << "enter name\n";
cin.getline(name, size);//通過換行符來確定行尾,儲存時用空字元替換換行符
cout << "enter dessert1\n";
cin.get(dessert1, size).get();//通過換行符確定行尾,保留換行符,所以要再呼叫get()取出換行符
cout << "enter dessert2\n";
cin.get(dessert2, size).get();
cout << "end";
return 0;
}
2、String類簡介
a)相關函式
參見 C語言字串函式探幽
b)原始字串
將原始字串(Raw)輸出,不用轉義符。如下:
cout<<R"(Jim "King" Tutt use "\n" instead of endl.) " << ' \n' ;
cout<<R"+* ("(Who wouldn‘ t?)" , she whispered.) +*" <<endl;
3、指標
一個指標的一生:
int main() {
/*1、宣告指標。指標值均為0xcccccccc。造了三個倉庫管理員,他們管理哪個倉庫未知*/
int *point_c,*point_cpp,*p,val;
/*2、定義|初始化指標。指標都有值了,但是他們指向的int變數均預設為-842150451。
倉庫管理員知道自己管理哪個倉庫了*/
point_c = (int *)malloc(sizeof(int *));
point_cpp = new int;
/*3、使用指標。指標指向的變數有一個明確的值了。管理員們開始搬貨進去*/
*point_c = 10;
*point_cpp = 11;
/*4、釋放記憶體。
指標指向的變數被清空,C指標指向的值為-572662307,C++指標也存在,但指向的值無法讀取
他們變成野指標了(迷途指標):告訴管理員,你不再管理任何倉庫了*/
free(point_c);
delete(point_cpp);
/*5、清空指標,指標值變為0
把管理員刪除掉了。人沒了。*/
point_c = NULL;
point_cpp = NULL;
return 0;
}
- delete 只能釋放new得來的地址,free同理。
- 不能釋放同一個記憶體塊兩次,但可以釋放空指標。
- 不釋放將導致記憶體洩漏。
4、C++資料儲存
a)自動儲存
自動變數(區域性變數)是在函式內部定義的常規變數,其作用域為包含它的程式碼塊。執行到這個函式時,相關變數入棧,函式結束時,變量出棧,編譯器自動釋放這些變數。
b)靜態儲存
第九章將詳解。要麼在函式外定義它,要麼用static。
c)動態儲存
有一個稱為堆的記憶體空間給程式設計師使用。可以在一個函式內分配記憶體,也可以在另一個函式裡釋放它。
5、記憶體空間
第五章 迴圈和關係表示式
1、延時迴圈
#include <ctime>
void my_delay(float secs) {
clock_t delay = secs * CLOCKS_PER_SEC;//乘以系統時間得到秒數
std::cout << "\a";//振鈴
clock_t start = clock();
while (clock() - start < delay)//流逝的時間小於指定時間,就迴圈消耗cpu
;
std::cout << "\a";//時間到
}
2、基於範圍的for迴圈
double prices[5] = {1.1, 1.2, 1.3, 1.4, 1.5};
for (double &x : prices)
x *= 0.8;
3、cin讀取之檔案尾EOF
int main() {
char ch;
int count=0;
cin.get(ch);
while (cin.fail()==false)//檢測到EOF後,cin把eofbit和failbit都設定為1,cin.fail()為true
{
cout << ch;
count++;
cin.get(ch);//除錯發現,鍵盤鍵入字元後回車,cin就從輸入流讀取,讀完了就需要再次鍵入
}
while (cin.get(ch)) { ; }//這樣也行
//注意在Unix使用Ctrl+D模擬EOF 而在Windows使用Ctrl+Z或回車
return 0;
}
第六章 分支語句和邏輯控制符
1、字元函式庫cctype
函式名稱 |
返回值 |
isalnum() |
如果引數是字母數字,即字母或者數字,函式返回true |
isalpha() |
如果引數是字母,函式返回true |
isblank() |
如果引數是水平製表符或空格,函式返回true |
iscntrl() |
如果引數是控制字元,函式返回true |
isdigit() |
如果引數是數字(0-9),函式返回true |
isgraph() |
如果引數是除空格之外的列印字元,函式返回true |
islower() |
如果引數是小寫字母,函式返回true |
isprint() |
如果引數是列印字元(包括空格),函式返回true |
ispunct() |
如果引數是標點符號,函式返回true |
isspace() |
如果引數是標準空白字元,如空格、換行符、水平或垂直製表符,函式返回true |
isupper() |
如果引數是大寫字母,函式返回true |
isxdigit() |
如果引數是十六進位制數字,即0-9、a-f、A-F,函式返回true |
tolower() |
如果引數是大寫字元,返回其小寫,否則返回該引數 |
toupper() |
如果引數是小寫字元,返回其大寫,否則返回該引數 |
2、簡單檔案的輸入輸出
一切皆檔案。
#include <iostream>
#include <cstdlib>
#include <fstream>
const int SIZE = 60;
int main() {
using namespace std;
ifstream in_file;
ofstream out_file;
out_file.open(R"(C:\Users\Trafalgar\Desktop\a.txt)");//檔案不存在則新建,存在則截斷(丟棄原內容)
double value = 3.2;
int cnt = 10;
while (cnt--)
{
out_file << value++<<" ";
}
out_file << "\nthis is a test\n";
out_file.close();
in_file.open(R"(C:\Users\Trafalgar\Desktop\a.txt)");
if (!in_file.is_open()) {
cout << "could not open file\n";
exit(EXIT_FAILURE);
}
double sum = 0.0;
in_file >> value;//讀
while (in_file.good()) {
sum += value;
in_file >> value;
}
if (in_file.eof()) {
cout << "EOF\n";
}
else if (in_file.fail()) {
cout << "由於資料不匹配無法讀取\n";
}
else cout << "未知錯誤\n";
cout << "sum=" << sum;
in_file.close();
return 0;
}
總結下:
- 引入標頭檔案fstream;
- 建立ifstream物件/ofstream物件,假設是object;
- object.open();
- object >>或者<<(讀寫檔案):就像cin一樣來操作;
- object.close()。
第七章 函式——C++的程式設計模組