1. 程式人生 > >【學習筆記】《C++ Primer Plus》

【學習筆記】《C++ Primer Plus》

目錄

第一章 預備知識

第二章 開始學習C++

1、名稱空間

2、定義變數

3、賦值語句

第三章 處理資料

1、變數名

2、整形

3、浮點數

第四章 複合型別

1、字串

a) 概念

b) 字串輸入

2、String類簡介

a)相關函式

b)原始字串

3、指標

4、C++資料儲存

a)自動儲存

b)靜態儲存

c)動態儲存

5、記憶體空間

第五章 迴圈和關係表示式

1、延時迴圈

2、基於範圍的for迴圈

3、cin讀取之檔案尾EOF

第六章 分支語句和邏輯控制符

1、字元函式庫cctype

2、簡單檔案輸入輸出


想說的話:打算學好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的儲存方式如下圖所示:

float型別的儲存方式

double的儲存方式為:

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、記憶體空間

è¿éåå¾çæè¿°
C程式的記憶體空間

 

 

 

 

第五章 迴圈和關係表示式

 

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;
}

總結下:

  1. 引入標頭檔案fstream;
  2. 建立ifstream物件/ofstream物件,假設是object;
  3. object.open();
  4. object >>或者<<(讀寫檔案):就像cin一樣來操作
  5. object.close()。

 

 

第七章 函式——C++的程式設計模組