《C++Primer》讀書筆記(五)語句

簡單語句

(1)空語句
- 一種常見情況:當循環的全部工作在條件部分就可以完成時,會用到空語句

// 我們想要讀取輸入流的內容,直至遇到一個特定值,除此之外什麼事情都不做
while(cin>>s&&s!=sought)
    ;

不要漏寫分號,也不要在語句未結束時寫分號

(2)符合語句(塊)

塊不以分號作爲結束

語句作用域

  • 在if、switch、while和for語句,在控制結構中聲明的變量,只有在相應語句的內部可見,語句結束,則變量也超出其作用範圍

條件語句

if語句

  • if else語句的形式是
if(condition)
    ststement
else
    statement2
  • 使用if else語句
const vector<string> scores={"F","D","C","B","A","A++"};
string lettergrade;
if (grade<60)
    lettergrade=scores[0];
else
    lettergrade=scores[(grade-50)/10];
  • 嵌套if語句
// 加入的片段
if(grade % 10 > 7)
    lettergrade += '+';
else if (grade % 10 < 3)
    lettergrade += '-';
if(grade < 60)
    lettergrade=scores[0];
else{
    lettergrade=scores[(grade-50)/10];
    if(grade != 100)
        if(grade%10 > 7)
            lettergrade +='+'';
        else if(grade % 10<3)
            lettergrade += '-'
}
  • 懸垂else —— else 將會與最近的if匹配

switch語句

unsigned aCnt=0,eCnt=0,iCnt=0,oCnt=0,uCnt=0;
char ch;
while (cin>>ch){

    switch(ch){
        case 'a':
            ++aCnt;
            break;
        case 'e'
            ++eCnt;
            break;
        case 'i'
            ++iCnt;
            break;
        …
        …
    }

}
  • case標籤必須是整型常量表達式

(2)有時,默認的switch行爲纔是程序真正需要的。每個case標籤只能對應一個值,但是有時候我們希望兩個或更多個值共享一組操作,因此故意省略掉break語句

unsigned vowelCnt=0;
switch (ch){
    case 'a':
    case 'e':
    case 'i':
    case 'o':
    case 'u';
        ++vowelCnt;
        break;
}

漏寫break容易引發缺陷

(3)default標籤

(4)switch內部變量的定義
- 一般將變量的定義在case中用塊包圍,以免造成不必要麻煩

迭代語句

while語句

定義在while條件部分或者while循環體內的變量每次迭代都經歷從創建到銷燬的過程

vector<int> v;
int i;
while (cin>>i)
    v.push_back(i);
auto beg=v.begin();
while (beg != v.end() && *beg>=0)
    ++beg;

傳統for循環的執行流程

for(init-statemen;condition;expression)
    statement

(1)傳統for循環的執行流程

(2)for語句頭中的多重定義
- init-statement可以定義多個對象,但是只能有一條聲明語句

// 記錄下v的大小,當達到原來的最後一個元素後結束循環
for(dealtype(v.size()) i=0,sz=v.size() ; i!=sz ; ++i)
    v.push_back(v[i]);

(3)省略for語句頭的部分
- 其中一種,省略expression

vector<int> v;
for(int i ; cin>>i ; /*表達式爲空*/)  //條件部分能夠改變i的值,無需表達式部分
    v.push_back(i);

範圍for語句

  • 形式如下
for(declaration : expression)
    statement
  • expression表示的必須是一個序列,比如用花括號括起來的初始值表、數組、vector、string等類型的對象,它們的共同特點是擁有能返回迭代器begin和end成員
  • declaration定義一個變量,序列中每個元素都得能轉換成該變量的類型,確保相容的最好辦法是auto
vector<int> v={0,1,2,3,4,5,6,7,8,9};
for(auto &r : v)
    r*+2;

do while語句

  • 形式:
do
    statement
while (condition);
  • 小例子:不斷提醒用戶輸入一對數,然後求其和
string rsp;
do{
    cout<<"please enter two values: "
    int val1=0,val2=0;
    cin>>val1>>val2;
    cout<<"The sum of them is: "<<val1+val2<<"\n\n"
        "More?Enter yes or no:";
    cin>>rsp;
}while(!rsp.empty()&&rsp[0]!='n');
  • 因爲do while想執行語句塊,後判斷條件,所以不允許在條件部分定義變量

跳轉語句

break語句

  • break語句:終止離它最近的while、do while、for或switch語句,並從這些語句之後的第一條語句開始繼續執行

continue語句

  • continue語句:終止最近的循環中的當前迭代並立即開始下一次迭代
string buf;
while(cin>>buf && !buf.empty())
    if(buf[0] != '_')
        continue; //接着讀取下一輸入
    //程序處理到此處,即當前輸入是以下劃線開始的;接着處理buf……
}

goto語句

  • goto語句:從goto語句無條件跳轉到同一函數內的另一條語句
    不要在程序中使用goto語句,因爲它以理解和修改
goto label;
其中,label是用於標識一條語句的標示符,例如:“`end: return;“`

練習

do{
    int sz=get_size();
}
while(sz<=0);

try語句塊和異常處理

  • 異常處理機制 爲程序中異常檢測和異常處理這兩部分的協作提供支持,在C++中,異常處理包括:
    1. throws表達式
      • 異常檢測部分使用throw表達式來表示它遇到了無法處理的問題
    2. try語句塊
      • 異常處理部分使用try語句塊處理異常
      • try語句塊以關鍵字try開始,並以一個或多個catch子句結
      • try語句塊中代碼拋出的異常通常會被某一個catch字句處理
    3. 一套異常類
      • 用於在throw表達式和相關的catch字句之間傳遞異常信息

throw表達式

if(item1.isbn() != item2.isbn())
    throw runtime_error("Data must refer to same ISBN");
// 程序執行到此,道標isbn號相同
cout<<item1+item2<<endl;
  • 該異常是類型runtime_error的對象,其定義在stdexcept頭文件中

try語句塊

  • 形式如下:
try{
    program-statement
}catch(exception-declaration){
    handler-statements
}catch(exception-declaration){
    handler-statements
}//……

(1)編寫處理代碼

while(cin>>item1>>item2){
    try{
        //添加兩個Sales_item對象的代碼
        //如果添加失敗,代碼拋出一個runtime_error異常
    }catch(runtime_error err){
        //提醒用戶兩個isbn必須一致
        cout<<err.what()
            <<"\n Try agin? Enter yes or no"<<endl;

        char c;
        cin>>c;
        if(!cin || c=='n')
            break; //跳出while循環
    }
}

(2)函數在尋找處理代碼的過程中退出
- 在尋找處理代碼的過程與函數調用鏈剛好相反。當異常被拋出時,首先搜索拋出異常的函數。如果沒有招到匹配的catch子句,終止該函數,並在調用該函數的函數中繼續尋找。如果還是沒有找到匹配的catch子句,這個新的函數也被終止,繼續搜索調用它的函數。以此類推,沿着程序的執行路徑逐層回退,直到招到適當類型的catch子句爲止
- 如果最終還是沒有找到任何匹配的catch子句,程序將自動轉到名爲terminate的標準庫函數。該函數行爲與系統有關,一般都將導致程序非正常退出

標準異常

  • exception頭文件定義了最常用的異常類exception。它只報告異常的發生,不提供任何額外的信息
  • stdexcept頭文件定義了幾種常用的異常類
異常類 問題
exception 最常見的問題
runtime_erro 只有在運行時才能檢測出的問題
range_error 運行時錯誤:生成的結果超出了有意義的值域範圍
overflow_error 運行時錯誤:計算上溢
underflow_error 運行時錯誤:計算下溢
logic_error 程序邏輯錯誤
domain_error 邏輯錯誤:參數對應的結果值不存在
invalid_argument 邏輯錯誤:無效參數
length_eroor 邏輯錯誤:試圖創建一個超出該類型最大長度的對象
out_of_range 邏輯錯誤:使用一個超出有效範圍的值
  • new頭文件定義了bad_alloc異常類型
  • type_info頭文件定義了bad_cast異常類型
發佈了34 篇原創文章 · 獲贊 5 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章