c++primer notebook

一、基礎

1. 循環讀入數據

讀取數量不定的輸入數據

void test01() {
	int value = 0;
	while (cin >> value)
	{
// 當遇到文件結束符或遇到一個無效輸入(比如讀到的值不是一個整數),istream對象狀態變爲無效,條件爲假
        cout << value << endl;
	}
}
2. 重定向

使用文件重定向連接標註你輸入和標準輸出

command < filename1 > filename2

Project4.exe < infile.txt > outfile.txt
  • 用double 而不是float
  • 無符號數的減法結果必須要確保爲正,尤其小心死循環
  • \123 八進制字符 \x1234 十六進制字符
  • 列表初始化: int value{0}; 優點:用列表初始化如果初始值存在丟失信息的風險,編譯器會報錯
3. extern:聲明

extern作用: 聲明一個變量而非定義,用於分文件編譯。

變量的定義只能出現在一個文件中,聲明可以出現在多個文件中

extern int j; //聲明i而非定義
int j; // 聲明並定義j
extern int j = 10; //定義
4. constexpr:常量

常量表達式:值不改變並且在編譯的時候就可以得到結果

constexpr作用:將變量聲明爲該類型以便有編譯器來驗證變量是否爲常量表達式。聲明爲constexpr的變量一定是個常量,而且必須用常量表達式初始化,否則會報錯

const int a =10; //Yes ,是常量表達式
const int a = getsize();//No,不是常量表達式

constexpr int a = 10; //a爲常量
constexpr int a = getsize();//只有當getsize是個constexpr函數(在編譯時就可以得到結果)時,纔不報錯

//如果constexpr聲明中如果定義了指針,限定符只對指針有效
const int *p = nullptr;
constexpr int *q = nullptr; //
5. typedef :類型別名
typedef double wages; //wages是double的同義詞
wages hourly, weekly;

typedef wages base, *p; // base是double的同義詞,p是double*的同義詞

using SI = Sales_item; // SI是Sales_item的同義詞----新方法:別名聲明
SI item;
6. auto : 類型說明符

auto : 編譯器通過初始值分析表達式所屬的類型

auto item = val1 + val2; // 自動根據val1和val2推斷item類型
auto i=0, *p = &i; // 正確,i和*p是同一個類型
auto sz=0, pi = 3.14; //錯誤,auto在一條語句中聲明多個變量時,要求類型一致
7. decltype : 類型說明符

decltype : 編譯器分析表達式並得到其類型,但不實際計算表達式的值

decltype(f()) sum = x;  //sum的類型由f返回類型決定,但不調用函數
decltype(s.size()) index = 0;
8. 指針的引用
int i = 42;
//int *&r = &i; 報錯,不能定義指向引用的指針

int *p;
int *&r = p;
p = &i;
cout << *r; //令i=0
9. 多文件常量共享

const聲明和定義中都加入extern

// 文件1
extern const int bufsize = 10;
// 文件2
extern const int bufsize;
10. 常量引用
int i = 42;
const int &r1 = i; //Yes,但是不可以通過r1修改i的值
const int &r2 = 42; //Yes 常量引用可綁定非常量對象、字面值和表達式
11. 常量指針和指針常量
//指針常量,值是常量
const double p = 3.14;
double *p1 = &p; //No
const double *p2 = &p; //Yes,但不能通過p2改p

//常量指針,地址是常量
int a = 0;
int const *p3 = &a;
12. for (declaration: expression) statement
for(declaration : expression) statement
for(元素:序列) 操作 //遍歷每個元素,並對序列中的每個值執行操作
string c{"hello"};
for(auto &i:c){cout << i;}
13. 迭代器類型
vector<int>::iterator it1;       // it1可讀寫vector元素
vector<int>::consti_iterator it2;// it2只能讀vector元素
auto it3 = v.cbegin();  //it3類型爲vector<int>::consti_iterator,只讀操作最好用常量類型

for(auto it = text.cbegin();it != text.cend() && !it->empty();++it}{
    cout << *it << endl;
}
14. 複雜數組聲明
int a[10];
int * p1[10];         // 存放10個指針的數組
int (*p2)[10];        // p是指針,指向存放10個int的數組
int(&r)[10] = a;      // r是引用,引用含有10個int的數組
int *(&arr)[10] = p1; //arr是引用,引用一個數組,該數組是存放10個指針的數組。
15. 數組索引類型

數組下標類型size_t,無符號類型,足夠大,可以表示內存中任意對象的大小

int scores[10] = {};
for (auto i: scores){
	cout << typeid(i).name()<< " " <<i << endl;
}
16. 標準庫函數 begin, end

需要包含頭文件 #include

int arr[] = {0,1,2,3,4,5,6};
int *beg = begin(arr);
int *last = end(arr); // 指向尾元素的下一個位置
cout << *beg; 
cout << *(last-1);
17. 指針下標的表示
int a[] = {1,2,3,4,5,6};
int *p=a+1;
cout << p[0];
18. 標準庫函數string

儘量還是使用string對象,而不是標準庫函數,因爲常常會出現越界的情況

char a[] = "hello";
char b[] = "areyouok";
strlen(a);    // 返回字符串的長度
strcmp(a,b);  // 比較兩個字符換是否相等a>b返回正
strcat(a, b); // 拼接字符串,返回a
strcpy(a, b); // 將b拷貝給a,返回a	
// 混用數組字符串和string對象
string a("areyouok");
const char *str = a.c_str();
char b[] = { 1,2,3,4,5 };
vector<char> vec(begin(b), end(b));
19. 多維數組
int a[3][4] = {
	{1,2,3,4},
	{2,3,4,5},
	{3,4,5,6}
};

int (&b)[4] = a[1];   // b 爲四元數組的引用
int(*c)[4] = &a[1];   // c 爲指向四元數組的指針
int(*d)[4] = a;       // d 爲指向四元數組的指針

// 用for循環處理多維數組,必須用到引用類型,否則無法通過編譯
for (auto &row :a){
	for (auto &col : row){
		cout << col << " ";
	}
	cout << endl;
}

for (auto &row:a){
	for(auto col:row)
		cout << col << " ";
	cout << endl;
}

// 指針和多維數組
for (auto p=a;p!=a+3;p++){   // p是指向四個元素的數組,
	for (auto q = begin(*p);q!=end(*p);q++){  // q是指向
		cout << *q;
	}
	cout << endl;
}	
20. 運算符
  • 遞增遞減運算符

    優先使用++a,而不是a++型

*p++; // *(p++) 將p值+1後,返回p指向的初始值
cout << *it++ << endl;
  • 成員訪問運算符

    string s = "hello", *p = &s;
    auto n = s.size();
    n = (*p).size();
    n = p->size();
    
  • 條件運算符

    注意: 當其他表達式子裏有條件運算符出現時,通常需要加上括號

    int  grade = 75;
    string finalgrade = (grade > 90) ? "great": ((grade > 60)?"good" : "bad");	
    
  • sizeof運算符

    int a;
    sizeof(int);
    sizeof a;
    
21. 異常處理
throw runtime_error("Data must be equal");
try{
    //
}catch(runtime_error err){
    cout << err.what();
}

二、函數

1. 局部靜態對象

有些時候,有必要令局部變量的聲明週期貫穿函數調用之後的時間,可以將局部變量定義成static類

size_t count_calls() {
	static size_t count=0;
	return ++count;
}

int main(int argc, char ** argv) {
	for (size_t i = 0; i < 10; i++)	{
		cout << count_calls() << endl;
	}
}
2. 指針形參傳遞
void reset(int *p) { // 當調用函數時,形參p指針拷貝了原來的指針的地址,是兩個不同的指針
	*p = 10;          // 修改形參p指向的值,會修改原來指針的值
	p = nullptr;     // 修改形參p的指向,不會對原來的指針造成影響
}

int main(int argc, char ** argv) {
	int i = 42;
	reset(&i);
	cout << "i=" << i << endl;
	system("pause");
	return 0;
}
3. 引用形參傳遞

值傳遞和引用傳遞都可以作爲函數的形參。

當某種類型不支持拷貝操作時,比如IO,函數只能通過引用形參訪問該類型對象。

當函數無須修改引用形參的值時,最好用常量引用。

bool isShorter(const string &s1, const string &s2){
	return s1.size()+s2.size();
}

函數如何返回多個信息?

方法一:定義一個新的數據類型,讓它包含多個成員

方法二:給函數傳入額外的引用實參,令其保存需要的信息

4. const形參和實參
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章