C++ Primer第三章!
#include "stdafx.h"
#include<iostream>
#include<vector> //vector可以容納著其他對(duì)象客税,簡(jiǎn)稱容器况褪。
#include<string> //string表示可變長(zhǎng)的字符序列。
#include<algorithm> //泛型算法更耻!
using namespace std;
int main()
{
//定義和初始化string
string s1;
string s2 = s1; //拷貝初始化
string s3 = "hello world"; //c風(fēng)格字符串
string s4(10, 'a'); //構(gòu)造函數(shù)测垛!
string s5(s1); //直接初始化
//string包含的方法
cout << s3 << endl;
cin >> s2>> s1; //string自動(dòng)忽略開(kāi)頭空白(空格符、換行酥夭、制表)赐纱,直到遇見(jiàn)下一處空白
getline(cin, s1); //遇見(jiàn)換行符就結(jié)束操作,觸發(fā)返回的換行符實(shí)際被丟棄
//s.empty(); s為空則返回true熬北,否則返回false
//s.size(); 返回s中字符的個(gè)數(shù)疙描,string::size_type為無(wú)符號(hào)類(lèi)型,足夠放下任何string對(duì)象的大小讶隐。
//s[n]; 返回第N個(gè)字符的引用
//s1+s2; s1和s2連接起胰,也可以將字面值與string相加,但必須確保兩側(cè)至少有一個(gè)string對(duì)象巫延。(在c++中效五,字面值字符串為字符指針,而與string不同類(lèi)型)
//s1=s2;
//s1 == s2; 長(zhǎng)度和字符相等則相等炉峰!
//s1!=s2;
//<,<=,>,>=; 1畏妖、長(zhǎng)度,2疼阔、第一對(duì)相異字符戒劫。
//cctype頭文件半夷,針對(duì)字符操作!
//isalnum(c) 當(dāng)c是字母或數(shù)字為真迅细。
//isalpha(c) 字母
//iscntrl(c) 控制字符
//isdigit(c) 數(shù)字
//isgraph(c) 不是空格但可打印
//islower(c) 小寫(xiě)字母
//isprint(c) 可打影诿埂(空格和可視形式)
//ispunct(c) 標(biāo)點(diǎn)符號(hào)(不是控制台囱、數(shù)字梭伐、字母医窿、可打印空白)
//isspace(c) 空白(空格,制表符统阿、回車(chē)符彩倚、換行符、進(jìn)紙符)
//isupper(c) 大寫(xiě)字母
//isxdigit(c) 十六進(jìn)制數(shù)字
//tolower(c) 大寫(xiě)轉(zhuǎn)小寫(xiě)
//toupper(c) 小寫(xiě)轉(zhuǎn)大寫(xiě)
//范圍for
for (auto &c : s3) //c是一個(gè)引用砂吞,將s3字符串全部改為大寫(xiě)字符串署恍。
c=toupper(c);
cout << s3 << endl;
//string可以使用下標(biāo)運(yùn)算符,建議設(shè)置string下標(biāo)的類(lèi)型為string:size_type(能確保下標(biāo)不會(huì)小于0)蜻直,而下標(biāo)值要小于size().
const string hexdigits = "0123456789ABCDEF";
cout << "Enter a series of numbers between 0 and 15:";
string result;
string::size_type n;
cin >> n;
result = hexdigits[n]; // 建議對(duì)下標(biāo)進(jìn)行檢查盯质,必須確保下標(biāo)合法。
cout << result << endl;
//標(biāo)準(zhǔn)庫(kù)類(lèi)型vector概而,容器
vector<int> ivec;
vector<string> svec1;
vector<string> svec2(svec1);
vector<string> svec3 = svec1;
vector<string> svec4(10, "love");
vector<string> svec5 = { "hello","world","!" };
vector<string> svec6{ "hello","world","!" }; //提供初始元素值的列表呼巷,只能使用花括號(hào),列表初始化赎瑰。
//向vector對(duì)象中添加元素
svec6.push_back(" hello c++!");
//其他vector操作
//v.empty(); 如果v中不含任何元素王悍,則返回真。
//v.size(); 返回v中元素個(gè)數(shù)餐曼,類(lèi)型為vector<內(nèi)置類(lèi)型>::size_type压储。
//v.push_back(t); 尾端插入元素
//v[n]; 下標(biāo)運(yùn)算符,對(duì)v中第N個(gè)位置上元素的引用源譬,而試圖訪問(wèn)不存在元素將發(fā)生溢出錯(cuò)誤集惋。另外,不能使用下標(biāo)添加元素踩娘。
//v1=v2; 拷貝
//v1={...} 列表初始化
//v1 == v2; 元素?cái)?shù)量刮刑,對(duì)應(yīng)位置元素值
//v1!=v2;
//<,<=,>,>=;
//迭代器,所有標(biāo)準(zhǔn)庫(kù)容器都可以使用迭代器养渴,但是只有少數(shù)才同時(shí)支持下標(biāo)運(yùn)算符雷绢。
auto b = svec6.begin(), e = svec6.end(); //end返回尾后迭代器,如果容器為空理卑,則都為尾后迭代器翘紊。
//迭代器運(yùn)算符
//*iter 解引用迭代器,并返回迭代器所指元素的引用
//iter->mem 解引用并返回該元素的mem成員藐唠,等價(jià)于(*iter).mem
//++iter 令迭代器iter指向下一元素
//--iter
//iter1==iter2 兩個(gè)迭代器是否指向相同元素霞溪?
//iter1!=iter2
string siter("hello world");//string也有迭代器操作孵滞!
if (siter.begin() != siter.end())
{
auto it = siter.begin();
*it = toupper(*it);
}
cout << siter << endl;
for (auto it = siter.begin(); it != siter.end() && !isspace(*it); ++it)
*it = toupper(*it);
cout << siter << endl;
//迭代器類(lèi)型
vector<int>::const_iterator it1; //迭代器分為iterator和const_iterator,const類(lèi)型只能讀元素鸯匹,不能寫(xiě)元素。
vector<int>::iterator it2;
//如果對(duì)象只讀而不寫(xiě)則應(yīng)該定義為const_iterator類(lèi)型
auto it_iterator = svec6.cbegin();
//迭代器運(yùn)算
//iter+n 加上數(shù)值還是迭代器
//iter-n;
//iter += n;
//iter-=n;
//iter1-iter2; 返回類(lèi)型為difference_type泄伪,帶符號(hào)整型殴蓬。
//>,>=,<,<=;
//二分法搜索
vector<int> text_num{ 3,1,2,4,5,6,9,8,7 };
int find_num = 9;
sort(text_num.begin(), text_num.end());
auto beg = text_num.cbegin();
auto end = text_num.cend();
auto mid = text_num.cbegin() + (end - beg) / 2;
while(mid != end)
{
if (*mid == find_num)
{
cout << "Find numbers!" << endl; // 二分法搜索,如果找到數(shù)值就輸出find numbers蟋滴!
break;
}
if (find_num < *mid)
{
end = mid;
}
else
{
beg = mid + 1;
}
mid = beg + (end - beg) / 2;
}
//數(shù)組染厅,是一種類(lèi)似于標(biāo)準(zhǔn)庫(kù)類(lèi)型vector,數(shù)組大小固定津函!
int arr1[10]; //含有10個(gè)整數(shù)的數(shù)組
int *parr1[10]; //含有10個(gè)整型指針的數(shù)組肖粮。int (*p)[10]指向含有10個(gè)整數(shù)數(shù)組的指針!主要應(yīng)用于指向二維數(shù)組尔苦!
int arr2[] = { 1,2,3 };
int arr3[5] = { 1,2,3 };
char a1[] = { 'c','c' };
char a2[] = "cc";
//char a3[2]="cc"; 沒(méi)有足夠的空間放下'\0'
//int arr4 = arr2; 不能用一個(gè)數(shù)組初始化令一個(gè)數(shù)組涩馆。數(shù)組會(huì)自動(dòng)轉(zhuǎn)為首元素指針!
//arr1=arr2; 不能把一個(gè)數(shù)組直接賦值給另一個(gè)數(shù)組
int (*parr2)[10]= &arr1; //parr2指向一個(gè)包含10個(gè)整數(shù)的數(shù)組允坚。
int (&parr3)[10] = arr1; //parr3引用一個(gè)含有10個(gè)整數(shù)的數(shù)組魂那。
int *(&parr4)[10] = parr1; //parr4是數(shù)組的引用,該數(shù)組包含10個(gè)指針
//默認(rèn)情況稠项,類(lèi)型修飾符從右至左依次綁定(而括號(hào)則改為由內(nèi)向外)涯雅,數(shù)組必須指定類(lèi)型,不允許用auto推斷類(lèi)型展运!
constexpr unsigned sz = 10;
string strs[sz]; //sz必須為常量表達(dá)式活逆!
for (auto i : arr2)
{
cout << i << " "; //arr2數(shù)組也支持下標(biāo)運(yùn)算符,下標(biāo)運(yùn)算符類(lèi)型為size_t拗胜,無(wú)符號(hào)類(lèi)型蔗候。建議檢查下標(biāo)的值,避免緩沖區(qū)溢出錯(cuò)誤挤土。
}
cout << endl;
//指針和數(shù)組關(guān)系密切琴庵,在c++中,編譯時(shí)會(huì)將數(shù)組轉(zhuǎn)換成指針仰美。
string nums[] = { "one","two","three" };
string *p1_nums = &nums[0];
string *p2_nums = nums; //p1等價(jià)于p2
//數(shù)組有迷殿,標(biāo)準(zhǔn)庫(kù)函數(shù)begin和end。類(lèi)似于容器的迭代器操作咖杂!
int ia[] = { 0,1,2,3,4,5,6,7,8,9 };
int *beg_ia = begin(ia);
int *end_ia = std::end(ia); //由于前文定義了迭代器變量end庆寺,因此此處只有使用作用域符!(避免使用c++內(nèi)置聲明符)
//指針也是迭代器诉字,指針相減返回類(lèi)型ptrdiff_t懦尝,帶符號(hào)類(lèi)型知纷,定義在頭文件cstddef中。
//c++支持c風(fēng)格字符串陵霉,也定義了c_str等轉(zhuǎn)換函數(shù)琅轧,但是最好不要用c風(fēng)格字符串!
//使用指針和數(shù)組容易出錯(cuò)踊挠,推薦使用vector和迭代器乍桂,還有string!
//多維數(shù)組效床,是數(shù)組的數(shù)組睹酌!
int ia_multi1[3][4]; //大小為3的數(shù)組,每個(gè)元素是含有4個(gè)整數(shù)的數(shù)組剩檀。
int ia_mulit2[3][4] = { 0 }; //將所有元素初始化為0
int ia_mulit3[3][4] = { {1,2,3,4},{5,6,7,8} };
int ia_mulit4[3][4] = { 1,2,3,4,5,6,7,8 };
int(&row)[4] = ia_multi1[1]; //把row綁定到ia的第二個(gè)4元素?cái)?shù)組上
decltype(ia_multi1) ia_mulit5; //decltype返回類(lèi)型是多維數(shù)組憋沿,而不是指針!auto推斷為指針沪猴,所以數(shù)組嵌套for外層必須為引用辐啄!
//范圍for處理多維數(shù)組,也可以用for嵌套
for (const auto &row : ia_mulit3) //除了最內(nèi)層循環(huán)字币,其他所有循環(huán)的控制變量都應(yīng)該是引用则披!如果非引用auto &row=ia_mulit3,則auto將自動(dòng)推斷為指針!
{
for (auto col : row)
cout << col << "-";
cout << endl;
}
//指針和多維數(shù)組
int(*p_mulit2)[4] = ia_mulit3; //*p_mulit2為指針洗出,指向含有4個(gè)整數(shù)的數(shù)組
int *ip[4]; //4個(gè)指向整型對(duì)象的數(shù)組士复!
using int_arry = int[4]; //類(lèi)型別名
int_arry *ia_mulit6 = ia_mulit3; //等價(jià)于*p_mulit2
//for循環(huán),使用auto翩活,可以不用在數(shù)組前面加指針類(lèi)型聲明阱洪!
for (auto p = ia_mulit2; p != ia_mulit2 + 3; ++p)
{
for (auto q = *p; q != *p + 4; ++q)
{
cout << *q << " ";
}
cout << endl;
}
//使用begin和end函數(shù),更加簡(jiǎn)潔易懂
for (auto p = begin(ia_mulit2); p != std::end(ia_mulit2); ++p)
{
for (auto q = begin(*p); q != std::end(*p); ++q)
{
cout << *q << "+";
}
cout << endl;
}
cin.ignore();
return 0;
}
//1菠镇、使用拷貝初始化時(shí)冗荸,只能提供一個(gè)初始值;2利耍、如果類(lèi)提供了類(lèi)內(nèi)初始值蚌本,則只能用拷貝初始化或者列表初始化(直接和拷貝);3隘梨、如果容器提供初始元素值的列表程癌,則只能用列表初始化。
//1轴猎、不能在范圍for循環(huán)中向vector對(duì)象添加元素嵌莉,另一個(gè)限制是任何可能改變vector對(duì)象容量的操作,如push_back捻脖,都會(huì)使vector對(duì)象的迭代器失效锐峭。
//第三章主要介紹vector中鼠,string,數(shù)組沿癞,順帶提到了C++對(duì)于C的支持(C風(fēng)格字符串援雇,及相互轉(zhuǎn)換方法)。在介紹vector和string時(shí)引出了迭代器的概念椎扬,講解了其基本用法熊杨。在介紹數(shù)組時(shí)引出了指針的概念和用法,同時(shí)穿插講解了auto盗舰、decltype、范圍for等等桂躏!作者重點(diǎn)提到钻趋,推薦使用vector、string剂习、迭代器,避免繁瑣和錯(cuò)誤蛮位!