C++ 第五章 結(jié)構(gòu)化程序設(shè)計(jì)(二)

一個(gè)c++程序可以包含很多個(gè)函數(shù)揽祥,源代碼可能會(huì)很長(zhǎng)泄私,可以將這些函數(shù)分散保存在不同的源文件中欺缘,以多文件結(jié)構(gòu)的形式來組織和管理源代碼重荠。

程序員可以在c++源程序中插入一些特殊指令箭阶,其作用是告訴編譯器該如何編譯本程序,正式編譯源程序之前晚缩,編譯器將預(yù)先處理這些特殊指令尾膊,因此它們被稱為編譯預(yù)處理指令

本章將介紹c++語言中幾種特殊形式的函數(shù)荞彼,以及由c++編譯系統(tǒng)為程序員提供的一些常用函數(shù)冈敛,這些函數(shù)被統(tǒng)稱為系統(tǒng)函數(shù)

程序設(shè)計(jì)可能會(huì)面臨比較復(fù)雜的數(shù)據(jù)鸣皂,這時(shí)程序員需要基于基本數(shù)據(jù)類型來自己定義新的數(shù)據(jù)類型抓谴,這就是自定義數(shù)據(jù)類型。數(shù)組就是一種自定義數(shù)據(jù)類型寞缝,本章講講解幾種常用的自定義數(shù)據(jù)類型

一癌压、c++源文件的多文件結(jié)構(gòu)

一個(gè)c++程序可以包含很多個(gè)函數(shù),源代碼可能會(huì)很長(zhǎng)荆陆,可以將這些函數(shù)分散保存在不同的源文件中滩届,以多文件結(jié)構(gòu)的形式來組織和管理源代碼。

結(jié)構(gòu)化程序設(shè)計(jì)被啼,將一個(gè)復(fù)雜任務(wù)分解成多個(gè)模塊帜消,編碼時(shí)棠枉,講每個(gè)模塊定義成一個(gè)函數(shù),基于團(tuán)隊(duì)協(xié)作開發(fā)程序時(shí)泡挺,可以將不同模塊的程序設(shè)計(jì)和編碼任務(wù)交由不同的程序員去完成辈讶,程序員各自獨(dú)立編程,將所編寫的源程序代碼保存在自己的源文件中娄猫,這樣可以互不干擾贱除,基于團(tuán)隊(duì)協(xié)模式開發(fā)的c++程序會(huì)自然形成多文件結(jié)構(gòu)

工程:一個(gè)程序開發(fā)項(xiàng)目又稱為工程,一個(gè)工程通常包含多個(gè)源程序文件媳溺,c++語言的源程序文件名為.cpp月幌。一個(gè)源程序文件可以包括多個(gè)函數(shù),一個(gè)函數(shù)只能集中放在一個(gè)源程序文件中悬蔽,不能將函數(shù)定義分開存放在不同文件中飞醉,一個(gè)程序工程中可以包括很多個(gè)函數(shù),但是只有一個(gè)主函數(shù)屯阀,函數(shù)名必須為main()

編譯器:使用編譯器將c++語言翻譯成機(jī)器語言,編譯時(shí)轴术,同一源程序文件中的所有函數(shù)难衰,被統(tǒng)一編譯,因此一個(gè)源程序文件被稱為一個(gè)編譯單元逗栽,每個(gè)源程序編譯后都生成一個(gè)目標(biāo)程序盖袭,目標(biāo)程序的擴(kuò)展名通常為.obj,目標(biāo)程序是機(jī)器語言的程序彼宠,機(jī)器語言與cpu相關(guān)鳄虱,相同的c++源程序,可以被不同編譯器編譯凭峡,生成不同機(jī)器語言的目標(biāo)程序拙已,從而運(yùn)行于不同類型的cpu之上,

連接器:每個(gè)源程序文件編譯后都生成一個(gè)目標(biāo)程序文件摧冀,使用連接器倍踪,將多個(gè)目標(biāo)程序連接在一起,最終生成一個(gè)可執(zhí)行程序文件索昂。在windows操作系統(tǒng)上建车,可執(zhí)行操作文件的擴(kuò)展名通常為.exe,可執(zhí)行程序是最終的程序椒惨,可以被計(jì)算機(jī)硬件執(zhí)行缤至。軟件產(chǎn)品銷售的是可執(zhí)行程序,而源程序則是軟件廠家的機(jī)密康谆×斐猓可執(zhí)行程序文件可以復(fù)制嫉到、分發(fā)安裝并執(zhí)行,但很難被閱讀修改戒突。

多文件結(jié)構(gòu):在多文件程序中屯碴,一個(gè)文件定義的函數(shù),可以被其他文件函數(shù)調(diào)用膊存〉级可以被其他文件調(diào)用的函數(shù)稱為外部函數(shù),一個(gè)文件中定義的全局變量隔崎,也可以被其他文件中的函數(shù)訪問今艺,可以被其他文件訪問的全局變量,被稱為外部全局變量爵卒。換句話說虚缎,一個(gè)文件中的函數(shù),可以調(diào)用其他文件中的外部函數(shù)钓株, 也可以訪問其他文件中的外部全局變量实牡,調(diào)用外部函數(shù)時(shí),需要先申明再調(diào)用轴合,訪問外部全局變量時(shí)创坞,也需要現(xiàn)聲明再訪問,聲明的作用受葛,是將外部函數(shù)或外部全局變量的作用域题涨,延申到本程序文件中來。下面以養(yǎng)魚池造價(jià)測(cè)試程序進(jìn)行拆分說明总滩,多文件結(jié)構(gòu)的具體語法和規(guī)則:

源程序文件1.cpp:內(nèi)容包括全局變量和主函數(shù)的定義纲堵,假設(shè)由程序員甲所編寫。

#include <iostream>
using namespace std;

void RectCost();
double CircleCost(double r);

double length,width; //? 全局變量:分別保存長(zhǎng)方形養(yǎng)魚池的長(zhǎng)寬
double r1,r2; //? 全局變量:分別保存圓形清水池和污水池的半徑
double totalCost = 0; //? 全局變量:用于保存最終結(jié)果闰渔,即總造價(jià)

int main()
{
    /*下來語句將使用鍵盤輸入原始數(shù)據(jù)席函,保存到對(duì)應(yīng)的原始變量中*/
    cout <<"請(qǐng)輸入長(zhǎng)方形的長(zhǎng)寬:";
    cin>>length>>width;
    cout<<"請(qǐng)輸入清水池和污水池的半徑:";
    cin>>r1>>r2;
    RectCost();//調(diào)用函數(shù)RectCost計(jì)算長(zhǎng)方形言語此造價(jià)
    totalCost += CircleCost(r1);//調(diào)用CircleCost計(jì)算清水池造價(jià)
    totalCost += CircleCost(r2);//再次調(diào)用CircleCost
    cout<<"工程總造價(jià)為:"<<totalCost<<endl;
    return 0;
}

源程序2.cpp:包括兩個(gè)用于計(jì)算的子函數(shù),由程序員乙編寫

extern double length,width;//聲明外部全局變量:分別保存長(zhǎng)方形養(yǎng)魚池的長(zhǎng)寬
extern double totalCost;//聲明外部全局變量:用于保存最終計(jì)算結(jié)果澜建,即總造價(jià)

void RectCost()
{
    double cost;
    cost = length*width*10; //直接讀取全局變量length和width中的數(shù)據(jù)
    totalCost+=cost;//將計(jì)算結(jié)果直接累加到全局變量totalCost中向挖。
}

double CircleCost(double r)
{
    double cost;
    cost = 3.14*r*r*10;
    return cost;
}

1.1 聲明外部函數(shù)原型和外部全局變量的語法細(xì)則

  • 聲明外部函數(shù)原型

    聲明外部函數(shù)原型,使用extern關(guān)鍵字炕舵,聲明 外部函數(shù)時(shí)何之,extern關(guān)鍵字也可以省略。

    extern void RectCost();//聲明RectCost函數(shù)
    void RectCost(); //extern關(guān)鍵字可以省略咽筋。
    

    使用extern關(guān)鍵字的作用是更明確的指出溶推,所聲明的函數(shù)是一個(gè)外部函數(shù),

  • 聲明外部全局變量

    聲明外部全局變量時(shí),必須加上extern關(guān)鍵字蒜危,不能初始化虱痕。否則就變成了另外一條全局變量定義語句。連接時(shí)辐赞,會(huì)出現(xiàn)和其他文件定義的全局變量重名的錯(cuò)誤部翘。

    extern double totalCost; //聲明外部全局變量totalCost
    double totalCost; //語法錯(cuò)誤,不能省略extern關(guān)鍵字
    extern double totalCost = 0; //語法錯(cuò)誤响委,外部全局變量不能初始化
    
  • 外部函數(shù)可以只聲明不調(diào)用新思,外部全局變量可以只聲明不訪問,也就是說赘风,只聲明不使用不會(huì)引起語法錯(cuò)誤夹囚。

1.2 多文件結(jié)構(gòu)

  1. 源程序文件所定義的函數(shù)默認(rèn)都是外部函數(shù),可以被其他文件中的函數(shù)調(diào)用邀窃;所定義的全局變量默認(rèn)都是外部全局變量荸哟,也可以被其他文件中的函數(shù)訪問。
  2. 外部函數(shù)和外部全局變量被多文件結(jié)構(gòu)中的所有文件共享瞬捕,其他文件只要經(jīng)過聲明都可以使用這些函數(shù)和全局變量
  3. 多文件結(jié)構(gòu)中鞍历,所有的外部函數(shù)不能重名,所有的外部全局變量不能重名肪虎,所有的外部函數(shù)和外部全局變量之間也不能重名

某些情況下堰燎,一個(gè)文件中定義的某些函數(shù)或全局變量只供文件內(nèi)部的其他函數(shù)使用,c++語言可以將這些函數(shù)或全局變量定義成靜態(tài)的笋轨,即靜態(tài)函數(shù)靜態(tài)全局變量,另外c++語言還可以定義靜態(tài)局部變量赊淑。

靜態(tài)函數(shù)與靜態(tài)變量:

  1. 靜態(tài)函數(shù)

    定義函數(shù)時(shí)爵政,再函數(shù)頭前加static關(guān)鍵字,該函數(shù)就被定義為靜態(tài)函數(shù)陶缺。靜態(tài)函數(shù)只能被本文件內(nèi)部的其他函數(shù)調(diào)用钾挟,其他文件不能調(diào)用,即使經(jīng)過聲明也不行饱岸。

    static void RectRoct()
    { ... ... }
    

    static關(guān)鍵字掺出,將所定義的函數(shù)作用域,限制在本文件范圍內(nèi)苫费,禁止延申到其他文件汤锨,合理定義靜態(tài)函數(shù),可以防止其他文件對(duì)該函數(shù)的誤調(diào)用百框。不同文件中的靜態(tài)函數(shù)可以重名

  2. 靜態(tài)全局變量

    全局變量具有文件作用域闲礼,靜態(tài)和非靜態(tài)指的是他們能否被其他文件中的函數(shù)訪問。

    定義全局變量時(shí),在語句前加static關(guān)鍵字柬泽,該變量就被定義為靜態(tài)全局變量慎菲,靜態(tài)全局變量只能被本文將內(nèi)的函數(shù)訪問,其他文件不能訪問锨并,即使經(jīng)過聲明也不行露该。

    static double r1,r2;
    

    static關(guān)鍵字,將所定義的全局變量作用域第煮,限制在本文件范圍內(nèi)解幼,禁止延申到其他文件,合理定義靜態(tài)全局變量空盼,可以防止其他文件對(duì)該全局變量的誤操作书幕。不同文件中的靜態(tài)全局變量可以重名

  3. 靜態(tài)局部變量

    局部變量只具有塊作用域,只能在本函數(shù)內(nèi)部使用揽趾、訪問台汇,任何時(shí)候都不能被其他函數(shù)訪問,更別說其他文件中的函數(shù)篱瞎,c++語言中苟呐,局部變量有靜態(tài)和非靜態(tài)之分,但含義與全局變量相比較俐筋,是不一樣的牵素。

    定義方法:在函數(shù)體或復(fù)合語句中定義的變量就是局部變量,在函數(shù)體或復(fù)合語句中定義局部變量時(shí)澄者,在語句前加“static”關(guān)鍵字笆呆,該變量就被定義為靜態(tài)局部變量。

    作用域:在源程序中具有塊作用域(與普通局部變量相同)

    內(nèi)存分配:普通的局部變量在執(zhí)行時(shí)粱挡,是自動(dòng)分配內(nèi)存的赠幕,而靜態(tài)局部變量是靜態(tài)分配內(nèi)存,就是程序執(zhí)行時(shí)立即分配內(nèi)存询筏,一直到程序執(zhí)行結(jié)束才釋放榕堰;存放在靜態(tài)儲(chǔ)存區(qū)(與全局變量相同)。

    綜上所述嫌套,靜態(tài)局部變量其作用域與局部變量相同逆屡,程序執(zhí)行時(shí),其內(nèi)存生存期和存放位置與全局變量一樣踱讨。也就是說魏蔗,靜態(tài)局部變量是一種居于全局變量和局部變量之間的一種折中變量。

    演示程序:對(duì)比靜態(tài)和非靜態(tài)局部變量

    #include <iostream>
    using namespace std;
    
    void func()
    {
        int x=0; //定義普通局部變量(非靜態(tài))x痹筛,初始化為0
        static int y=0;//定義靜態(tài)局部變量y沫勿,初始化為0
        x++; y++; //對(duì)x挨约,y同樣做加1操作。
        cout<<x<<"and"<<y<<endl;
    }
    
    int main()
    {   
        /*
        x在動(dòng)態(tài)儲(chǔ)存區(qū)产雹,計(jì)算機(jī)執(zhí)行到其定義語句時(shí)诫惭,才分配內(nèi)存,函數(shù)調(diào)用結(jié)束蔓挖,其內(nèi)存即被釋放夕土,第一次運(yùn)行func結(jié)束時(shí),x的值就被丟失了瘟判。再次調(diào)用時(shí)怨绣,從新賦值。
        y儲(chǔ)存在靜態(tài)內(nèi)存區(qū)拷获,程序加載時(shí)即分配內(nèi)存篮撑,并初始化為0,其內(nèi)存釋放要等到源程序結(jié)束匆瓜。因此第一次調(diào)用結(jié)束釋放func的棧幀赢笨,不會(huì)影響到y(tǒng)的值。
        */
        func(); //調(diào)用函數(shù)func驮吱,函數(shù)中顯示x=1茧妒,y=1,
        func(); //再次調(diào)用func左冬,函數(shù)中顯示x=1桐筏,y=2,
        return 0;
    }
    

    c++語言中的static關(guān)鍵字拇砰,是一個(gè)多義詞梅忌,使用這個(gè)關(guān)鍵字定義局部變量和全局變量時(shí),其含義是不一樣的除破,程序員應(yīng)該根據(jù)上下文來推斷它的含義铸鹰。

1.3 頭文件

團(tuán)隊(duì)協(xié)作開發(fā)時(shí),加上某個(gè)程序員編寫了一個(gè)c++程序文件(假設(shè)為1.cpp)皂岔,其中定義了一組函數(shù),也定義了若干全局變量展姐。其他程序員需要訪問1.cpp中的函數(shù)或全局變量躁垛,就需要對(duì)這些函數(shù)或全局變量進(jìn)行聲明,訪問多少個(gè)外部函數(shù)或全局變量圾笨,就需要寫多少條聲明語句教馆。對(duì)于項(xiàng)目組的所有程序員,只要訪問1.cpp中的函數(shù)或全局變量擂达,就都需要在自己的程序文件中編寫聲明語句土铺。編寫這些聲明語句時(shí)重復(fù)而枯燥的工作,為此c++語言引入了頭文件(header)的概念。

程序員甲在編寫好1.cpp源程序文件后悲敷,另外再編寫一個(gè)頭文件究恤,其中包含1.cpp所有外部函數(shù)和全局變量的聲明語句。習(xí)慣上將這個(gè)頭文件命名為1.h(或1.hpp)后德,即與源文件同名部宿,擴(kuò)展名為.h或.hpp,項(xiàng)目組的其他程序員需要訪問1.cpp中的函數(shù)或全局變量瓢湃,只要再自己的程序文件增加語句:#include "1.h"理张,該語句的作用就是將頭文件1.h中的所有聲明語句自動(dòng)插入到該語句位置,這就消除了以往一條一條手工編寫聲明語句的繁瑣绵患。

#include <iostream>
using namespace std;

#include "2.h" //用于替代下方的函數(shù)聲明語句雾叭。
// void RectCost();
// double CircleCost(double r);

double length,width; //? 全局變量:分別保存長(zhǎng)方形養(yǎng)魚池的長(zhǎng)寬
double r1,r2; //? 全局變量:分別保存圓形清水池和污水池的半徑
double totalCost = 0; //? 全局變量:用于保存最終結(jié)果,即總造價(jià)

int main()
{
    /*下來語句將使用鍵盤輸入原始數(shù)據(jù)落蝙,保存到對(duì)應(yīng)的原始變量中*/
    cout <<"請(qǐng)輸入長(zhǎng)方形的長(zhǎng)寬:";
    cin>>length>>width;
    cout<<"請(qǐng)輸入清水池和污水池的半徑:";
    cin>>r1>>r2;
    RectCost();//調(diào)用函數(shù)RectCost計(jì)算長(zhǎng)方形言語此造價(jià)
    totalCost += CircleCost(r1);//調(diào)用CircleCost計(jì)算清水池造價(jià)
    totalCost += CircleCost(r2);//再次調(diào)用CircleCost
    cout<<"工程總造價(jià)為:"<<totalCost<<endl;
    return 0;
}
/* "2.h"頭文件聲明 */
void RectCost();
double CircleCost(double r);

頭文件的內(nèi)容主要包含织狐,外部函數(shù)的申明,外部全局變量的申明掘殴,還包含一些共用的符號(hào)常量定義等等赚瘦。插入頭所使用的include指令是一種特殊指令,被稱為編譯預(yù)處理指令奏寨。

二起意、編譯預(yù)處理指令

程序員可以再c++源程序中插入一些特殊指令,其作用時(shí)告訴編譯器如何編譯本程序病瞳。正式編譯源程序之前揽咕,編譯器預(yù)先處理這些特殊指令,他們被稱為編譯預(yù)處理指令套菜,例如插入文件頭所使用的"#include"指令

編譯預(yù)處理指令亲善,不屬于c++語言的主體,是其附屬組成部分逗柴,其作用時(shí)方便程序員使用c++語言編程蛹头,常用的編譯預(yù)處理指令有:

  1. 文件包含指令
  2. 宏定義指令
  3. 條件編譯指令

在c++源程序中,編譯預(yù)處理指令可以寫在代碼的任意位置戏溺,每條指令單獨(dú)寫一行渣蜗,必須以井號(hào)"#"開頭,不加分號(hào)";"結(jié)束符旷祸。

2.1 文件包含指令:#include

編寫c++源程序時(shí)耕拷,程序員可以使用文件包含指令(#include)將某個(gè)指定文件的內(nèi)容插入到程序代碼的任意位置,通常是用于將某個(gè)頭文件(.h)插入到源程序文件(.cpp)中托享。

編譯一個(gè)c++源程序時(shí)骚烧,c++編譯器會(huì)首先進(jìn)行預(yù)處理浸赫,預(yù)處理時(shí),編譯器將指定文件的內(nèi)容插入該代碼位置赃绊,詳細(xì)語法如下:

//編譯預(yù)處理指令語法:文件報(bào)告指令
#include <文件名>  //缺省路徑時(shí)既峡,編譯器將到標(biāo)準(zhǔn)目錄下搜索指定的文件。
#include "文件名"  //缺省路徑時(shí)凭戴,編譯器將首先在當(dāng)前目錄下搜索涧狮,如果找不到指定文件,編譯器將到標(biāo)準(zhǔn)目錄下搜索指定的文件么夫。
  • 文件名:通常不寫完整的全路徑文件名者冤,而使用缺省值路徑,只寫頭文件名档痪,通常頭文件被集中存放在2個(gè)目錄下涉枫,一是c++編譯器安裝目錄下的"include"子目錄,該目錄稱為標(biāo)準(zhǔn)目錄腐螟,二是源程序文件所在的目錄愿汰,稱為當(dāng)前目錄
  • #include <文件名>:缺省路徑時(shí),編譯器將到標(biāo)準(zhǔn)目錄下搜索指定的文件乐纸。
  • #include "文件名":缺省路徑時(shí)衬廷,編譯器將首先在當(dāng)前目錄下搜索,如果找不到指定文件汽绢,編譯器將到標(biāo)準(zhǔn)目錄下搜索指定的文件吗跋。
  • 文件必須以井號(hào)"#"開頭,不加分號(hào)";"結(jié)束符宁昭。

2.2 宏定義指令:#define

用一個(gè)標(biāo)識(shí)符來表示一段代碼文本跌宛,這就稱為一個(gè)(macro),其中的標(biāo)識(shí)符稱為宏名积仗,所表示的代碼文本稱為宏文本疆拘,宏需要先定義再使用,習(xí)慣上寂曹,宏名用大寫字母來命名隆圆。程序員編寫指令時(shí),使用宏定義指令#define來定義一個(gè)新的宏匾灶,這樣凡是再后續(xù)代碼中租漂,需要用到宏代碼的地方都可以用宏名來代替颊糜。宏可以使代碼更加簡(jiǎn)潔,易于閱讀衬鱼。

宏定義指令是一個(gè)編譯預(yù)處理指令鸟赫,預(yù)處理時(shí)抛蚤,編譯器將源程序中所有的宏名自動(dòng)替換回原來的宏文本岁经,這稱為宏替換或宏展開蛋逾。c++語言有3種形式的宏:

  1. 無參宏
  2. 有參宏
  3. 空宏

已經(jīng)定義的宏框舔,可以用宏刪除指令(#undef)刪除戒傻。

實(shí)例代碼:定義無參宏

#define 宏名 宏文本
#define PI 3.14   //將常量3.14定義為符號(hào)常量PI
  • 宏名需復(fù)合標(biāo)識(shí)符的命名規(guī)則
  • 宏文本指定宏名所表示的字符串,可以由任意字符組成岳瞭,不需要加引號(hào)瞳筏。

無參宏主要用于定義符號(hào)常量姚炕。

#include <iostream>
using namespace std;
#define PI 3.14  //將常量3.14定義為符號(hào)常量PI
int main()
{
    double r;
    cout<<"請(qǐng)輸入圓的半徑:";
    cin>>r;
    cout<<"圓的面積是:"<<PI*r*r<<endl; //用符號(hào)常量PI代替3.14
    cout<<"圓的周長(zhǎng)是:"<<PI*2*r<<endl; //用符號(hào)常量PI代替3.14
    rerurn 0;
}

實(shí)例代碼:有參宏

#define 宏名(參數(shù)列表) 宏文本
#define AREA(x) 3.14159*x*x 
  • 宏名:復(fù)合標(biāo)識(shí)符的命名規(guī)則
  • 參數(shù)列表:指定若干可被替換的參數(shù)柱宦,參數(shù)間用逗號(hào)","隔開掸刊,
  • 宏文本:指定宏名所表示的字符串忧侧,可以由任意字符組成蚓炬,不需要加引號(hào)肯夏,字符串通常是包含參數(shù)的表達(dá)式

利用有參宏,可以實(shí)現(xiàn)簡(jiǎn)單的函數(shù)功能烁兰。通過實(shí)例代碼缚柏,可以寫出一個(gè)計(jì)算圓面積程序币喧。

#include <iostream>
using namespace std;
#define AREA(x) 3.14159*x*x
int main()
{
    int r=5;
    cout<<"圓的面積為:"<<3.14159*r*r<<endl;
    cout<<"圓的面積為:"<<AREA(r)<<endl; //使用宏進(jìn)行簡(jiǎn)寫杀餐。
    return 0;
}

使用有參宏的實(shí)參可以是表達(dá)式史翘,例如:

AREA(3+4) //執(zhí)行預(yù)處理時(shí),會(huì)展開為3.14159*3+4*3+4钻蹬,這顯然時(shí)不對(duì)的问欠, 這是因?yàn)槎x有參宏時(shí)的沒有考慮到運(yùn)算符計(jì)算的優(yōu)先級(jí)問題顺献。
/*從新定義AREA有參宏*/
#define AREA(x) 3.14159*(x)*(x)
AREA(3+4) //執(zhí)行預(yù)處理時(shí)展開為3.14159*(3+4)*(3+4)

實(shí)例代碼:空宏

#define 宏名 
  • 宏名需要符合標(biāo)識(shí)符命名規(guī)范注整,無宏文本肿轨。

定義空宏是為了配合條件編譯指令使用萝招。下面將做介紹槐沼,已經(jīng)定義的有參宏岗钩、無參宏兼吓、空宏视搏,都是用宏刪除指令(#undef)刪除浑娜。

#undef 宏明//宏名就是指定將被刪除的宏

刪除宏以后筋遭,宏就不能再繼續(xù)使用了漓滔。但可以再次被定義

2.3 條件編譯指令

程序開發(fā)過程中响驴,源程序可能有多個(gè)版本踏施,例如不同語種的版本,或者是調(diào)試版本和發(fā)行版本日熬,如果用不同的程序文件存放不同版本的源代碼竖席,文件數(shù)量將迅速增加毕荐,也容易導(dǎo)致代碼修改時(shí)的不一致問題憎亚,條件編譯指令運(yùn)行程序員將不同版本的源代碼寫在同一程序文件中第美,便于管理維護(hù)修改什往,條件編譯指令别威,有2種格式省古。

編譯預(yù)處理指令語法:條件編譯指令(格式1)

#ifdef 空宏名
    代碼段1
#else
    代碼段2
#endif
  • 編譯器在編譯這段代碼時(shí)飒赃,如果指定的空宏已定義载佳,則編譯代碼段1蔫慧,否則編譯代碼段2
  • 如果沒有代碼段2姑躲,則可以省略#else
#include <iostream>
using namespace std;
#define PI 3.14159 //為pi定義一個(gè)符號(hào)常量
#define ENGLISH_VERSION //定義一個(gè)空宏ENGLISH_VERSION黍析,將這條語句注釋調(diào),此程序就會(huì)編譯成一個(gè)中文版程序蔼两。
int main()
{
#ifdef ENGLISH_VERSION //如果定義了ENGLISH_VERSION额划,則編譯以下代碼
    cout<<"Please input a radius";
#else //否則編譯以下代碼
    cout<<"請(qǐng)輸入圓的半徑";
#endif
    /* 以下2條指令是中英文版公用的指令俊戳,故無需指定條件編譯*/
    double r;
    cin >>r;
#ifdef ENGLISH_VERSION
    cout<<"Area:"<<PI*r*r<<endl;
    cout<<"perimeter"<<PI*2*r<<endl;
#else
    cout<<"面積為:"<<PI*r*r<<endl;
    cout<<"周長(zhǎng)為"<<PI*2*r<<endl;
#endif
    return 0;
}

編譯預(yù)處理指令語法:條件編譯指令(格式2)

#ifdef 常量表達(dá)式
    代碼段1
#else
    代碼段2
#endif
  • 編譯器在編譯這段代碼時(shí),如果指定的常量表達(dá)式結(jié)果不為0圆恤,則編譯代碼段1盆昙,否則編譯代碼段2淡喜,常量表達(dá)式只能包含常量或符號(hào)常量
  • 如果沒有代碼段2炼团,則可以省略#else
#include <iostream>
using namespace std;
#define PI 3.14159 //為pi定義一個(gè)符號(hào)常量
#define ENGLISH_VERSION 1 //定義一個(gè)符號(hào)常量ENGLISH_VERSION,值為1锌俱,則編譯為英文版贸宏,當(dāng)值設(shè)為0吭练,將編譯中文版。
int main()
{
#ifdef ENGLISH_VERSION //如果ENGLISH_VERSION的值不為0浑侥,則編譯以下代碼
    cout<<"Please input a radius";
#else //否則編譯以下代碼
    cout<<"請(qǐng)輸入圓的半徑";
#endif
    /* 以下2條指令是中英文版公用的指令寓落,故無需指定條件編譯*/
    double r;
    cin >>r;#ifdef ENGLISH_VERSION
    cout<<"Area:"<<PI*r*r<<endl;
    cout<<"perimeter"<<PI*2*r<<endl;
#else
    cout<<"面積為:"<<PI*r*r<<endl;
    cout<<"周長(zhǎng)為"<<PI*2*r<<endl;
#endif
    return 0;
}

三史飞、幾種特殊形式的函數(shù)

3.1 帶默認(rèn)形參的函數(shù)

  • 定義函數(shù)或聲明函數(shù)原型時(shí)可以指定形式參數(shù)的默認(rèn)值构资,這就是帶默認(rèn)形參值的函數(shù)
  • 調(diào)用帶默認(rèn)形參值得函數(shù)時(shí)吐绵,如果給出實(shí)參值己单,則將實(shí)參值賦給形參變量,如果沒有廷痘,則將默認(rèn)值賦給形參變量牍疏。

例子:人民幣匯率轉(zhuǎn)換表(2015年6月19日)

外幣(數(shù)量:1) 人民幣(單位:元)
美元 6.1104
歐元 6.9698
英鎊 9.7347
港幣 0.78817
#include <iostream>
using namespace std;
double Exchange(double amount=100,double rate=6.1104) //給定匯率默認(rèn)形參值為美元的匯率
{
    return amount/rate;
}

int main()
{
    int x;
    cout <<"請(qǐng)輸入人民數(shù)量,單位元:";
    cin >> x;
    cout<<x<<"元人民幣="<<Exchange(x)<<"美元"<<endl; //人民幣>>美元厦滤,計(jì)算美元時(shí)掏导,不需要傳遞匯率
    cout<<x<<"元人民幣="<<Exchange(x,6.9698)<<"歐元"<<endl; //人民幣>>歐元
    cout<<x<<"元人民幣="<<Exchange(x,9.7347)<<"英鎊"<<endl; //人民幣>>英鎊
    cout<<x<<"元人民幣="<<Exchange(x,0.78817)<<"港幣"<<endl; //人民幣>>港幣
    return 0;
}

帶默認(rèn)形參值函數(shù)的語法細(xì)則:

  • 帶默認(rèn)值的形參:調(diào)用時(shí)如果給出實(shí)參值添瓷,則將實(shí)參值賦值給形參變量鳞贷,如果沒有搀愧,則將默認(rèn)值賦值給形參變量,不帶默認(rèn)值的形參在調(diào)用時(shí)必須給出實(shí)參迅箩,否則屬于語法錯(cuò)誤饲趋。
  • 在函數(shù)原型聲明中指定默認(rèn)值:如果函數(shù)定義在調(diào)用語句之后投队,應(yīng)該在調(diào)用語句之前對(duì)函數(shù)原型進(jìn)行聲明敷鸦“桥可以在聲明語句中指定形式參數(shù)的默認(rèn)值愿险,此時(shí)函數(shù)定義中不能再指定默認(rèn)值辆亏。函數(shù)具有文件作用域扮叨,同一函數(shù)在相同的作用域中只能指定一次默認(rèn)值碍沐。
  • 如果函數(shù)定義在其他文件中累提,應(yīng)該在調(diào)用語句之前聲明外部函數(shù)的原型刻恭,可以在聲明語句中指定形式參數(shù)在本文件中的默認(rèn)值,并且可以與原函數(shù)定義中的默認(rèn)值不同骑科。
  • 同一函數(shù)在不同的作用域中可以指定不同的默認(rèn)值咆爽。如果多個(gè)默認(rèn)值同時(shí)有效,調(diào)用函數(shù)時(shí)根據(jù)局部?jī)?yōu)先原則選擇默認(rèn)值呛凶。

演示程序:在不同作用域?yàn)楹瘮?shù)形參指定默認(rèn)值

#include <iostream>
using namespace std;
void fun(int p=10);//在申明函數(shù)fun時(shí)漾稀,指定文件作用域的形參p的默認(rèn)值為10
int main()
{
    fun(); //使用文件作用域的默認(rèn)值,函數(shù)fun的顯示結(jié)果為10
    {
        void fun(int p=20);//再次申明函數(shù)fun殷蛇,將具有塊作用域的形參p的默認(rèn)值為20
        fun(); //使用塊作用域(局部?jī)?yōu)先),fun的顯示結(jié)果為20
    }
    return 0;
}

void fun(int p) //在申明函數(shù)時(shí)谍倦,已經(jīng)指定了p的默認(rèn)值昼蛀,此時(shí)不能再指定
{
    cout<<p<<endl; //顯示形參p接收到的實(shí)參值
}

帶默認(rèn)值的形參仇哆,必須定義在形參列表的后面讹剔,形參列表中,可能有的形參帶默認(rèn)值由捎,有的不帶狞玛,定義函數(shù)或聲明函數(shù)原型時(shí),必須把帶默認(rèn)值的形參放在不帶默認(rèn)值的形參的后面硬鞍。

3.2 重載函數(shù)

調(diào)用函數(shù)時(shí)通過函數(shù)名指定調(diào)用哪個(gè)函數(shù)碑隆,函數(shù)名是函數(shù)的標(biāo)識(shí)上煤,通常拴疤,同一文件之中的函數(shù)不能重名呐矾,不文件中的非靜態(tài)函數(shù)(外部函數(shù))之間也不能重名组橄,

c++語言規(guī)定玉工,如果兩個(gè)函數(shù)的形參個(gè)數(shù)不同或數(shù)據(jù)類型不同,那么這兩個(gè)函數(shù)就可以重名狭郑,重名的函數(shù)被稱為重載函數(shù)。

將兩個(gè)或兩個(gè)以上函數(shù)定義為重載函數(shù)的原因缨历,是這些函數(shù)的功能相同或相近辛孵,使用相同的名字方便碼農(nóng)記憶,也不用絞盡腦子去想如何起不同的名字

#include <iostream>
using namespace std;
// Max為重載函數(shù)名冶匹,功能是求最大值。
int Max(int x,int y){return ((x>y)?x:y);}
//double型浮點(diǎn)類型飞蛹,為64位寬度,float型為32位寬度
double Max(double x,double y){return ((x>y)?x:y);}
int Max(int x, int y, int z)
{
    int m;
    m = (x>y)?x:y;
    m = (x>z)?m:z;
    return m;
}
cout<<Max(9,5); //自動(dòng)調(diào)用:int Max(int x,int y)
cout<<Max(9.0,5.0); //自動(dòng)調(diào)用:double Max(double x,double y)
cout<<Max(9,5,17); //自動(dòng)調(diào)用:int Max(int x, int y, int z)

C++在編譯語言時(shí)霉囚,由編譯器根據(jù)調(diào)用語句中實(shí)參的個(gè)數(shù)和類型逻澳,來自動(dòng)調(diào)用形參最匹配的那個(gè)重載函數(shù)斜做,簡(jiǎn)而言之就是通過形參和實(shí)參的匹配原則來調(diào)用重載函數(shù)。

注意:在應(yīng)用重載函數(shù)時(shí)霸旗,如果兩個(gè)函數(shù)僅僅是返回值類型不同或形參名不同,那么不能講這兩個(gè)函數(shù)命名為重載函數(shù)精居,否則會(huì)出現(xiàn)語法錯(cuò)誤。也不能將兩個(gè)功能差異很大的函數(shù)命名為重載函數(shù)佛吓,雖然沒有語法錯(cuò)誤,但是會(huì)在運(yùn)用中給程序員造成混淆吱型。

3.3 內(nèi)聯(lián)函數(shù)

調(diào)用函數(shù):函數(shù)跳轉(zhuǎn)和數(shù)據(jù)傳遞需要執(zhí)行一些額外的操作耕陷,實(shí)現(xiàn)相同的功能饺蔑,單一主函數(shù)程序比主函數(shù)+子函數(shù)程序執(zhí)行速度更快猾警,及函數(shù)跳轉(zhuǎn)會(huì)降低程序的執(zhí)行效率崔慧,但函數(shù)是團(tuán)隊(duì)分工協(xié)作和代碼重用的基礎(chǔ),函數(shù)能夠提高程序的開發(fā)效率皇钞。

內(nèi)聯(lián)函數(shù):內(nèi)聯(lián)函數(shù)是一種特殊的函數(shù),它在保障程序開發(fā)效率的同時(shí)可柿,不會(huì)減低程序的執(zhí)行效率趾痘。

其原理是:編譯源程序時(shí)將函數(shù)代碼直接嵌入到每一個(gè)調(diào)用語句處,而在執(zhí)行時(shí)不再進(jìn)行函數(shù)跳轉(zhuǎn)和數(shù)據(jù)傳遞侣集。

#include <iostream>
using namespace std;
//使用inline關(guān)鍵字申明內(nèi)聯(lián)函數(shù)
inline double Exchange(double amount,double rate=6.1104){ return amount / rate; }

int main()
{
    int x;
    cout <<"請(qǐng)輸入人民數(shù)量,單位元:";
    cin >> x;
    cout<<x<<"元人民幣="<<Exchange(x)<<"美元"<<endl; //人民幣>>美元
    cout<<x<<"元人民幣="<<Exchange(x,6.9698)<<"歐元"<<endl; //人民幣>>歐元
    cout<<x<<"元人民幣="<<Exchange(x,9.7347)<<"英鎊"<<endl; //人民幣>>英鎊
    cout<<x<<"元人民幣="<<Exchange(x,0.78817)<<"港幣"<<endl; //人民幣>>港幣
    return 0;
}

內(nèi)聯(lián)函數(shù)需要在被調(diào)用的函數(shù)前加上inline關(guān)鍵值進(jìn)行申明。

內(nèi)聯(lián)函數(shù)需要是簡(jiǎn)單的函數(shù)瓢阴,編譯器不能保證程序員所定義或申明的內(nèi)聯(lián)函數(shù)最終都能按照內(nèi)聯(lián)的方式進(jìn)行編譯,如果該函數(shù)的函數(shù)體比較復(fù)雜少漆,比如有循環(huán)語句示损,那么編譯器將自動(dòng)按照非內(nèi)聯(lián)函數(shù)的方式進(jìn)行編譯。

內(nèi)聯(lián)函數(shù)只有被多次調(diào)用嚷硫,其執(zhí)行效率才能體現(xiàn)出來屎媳,因此一般只是將頻繁調(diào)用的簡(jiǎn)單函數(shù),定義為內(nèi)聯(lián)函數(shù)论巍。

3.4 帶形參和返回值的主函數(shù)

計(jì)算機(jī)系統(tǒng)包括硬件和軟件2部分,操作系統(tǒng)是計(jì)算機(jī)中最基礎(chǔ)最重要的軟件嘉汰,操作系統(tǒng)直接運(yùn)行于硬件之上丹禀,啟動(dòng)計(jì)算機(jī)后,計(jì)算機(jī)自動(dòng)加載執(zhí)行鞋怀,只有在操作系統(tǒng)運(yùn)行之后双泪,其他軟件才能運(yùn)行,用戶執(zhí)行某個(gè)程序密似,其實(shí)是向操作系統(tǒng)下達(dá)了一個(gè)執(zhí)行程序的指令焙矛。在命令行操作系統(tǒng)中,如果要執(zhí)行某個(gè)程序残腌,就可以下達(dá)類似于:test.exe或test指令村斟,然后回車,操作系統(tǒng)接收該指令抛猫,然后將程序文件讀入內(nèi)存蟆盹,找到該程序的主函數(shù)main,從主函的第一條指令開始執(zhí)行闺金,程序執(zhí)行結(jié)束后逾滥,從主函數(shù)main返回操作系統(tǒng)。

可以將操作系統(tǒng)執(zhí)行某個(gè)程序的過程败匹,理解成操作系統(tǒng)調(diào)用該程序主函數(shù)main 的過程寨昙。

用戶在向操作系統(tǒng)下的程序執(zhí)行指令的同時(shí),可以傳遞某些原始數(shù)據(jù)掀亩。也就是說舔哪,一個(gè)程序的主函數(shù)main可以定義形參,接收數(shù)據(jù)归榕,可以定義返回值尸红,將自己的運(yùn)行狀態(tài)返回給操作系統(tǒng)吱涉。

c++程序中的主函數(shù)main()的語法細(xì)則:

  • 一個(gè)c++程序必須有并取只有1個(gè)名為main的主函數(shù)刹泄。
  • 主函數(shù)是程序執(zhí)行的起點(diǎn)
  • 主函數(shù)不能被重載
  • 主函數(shù)的類型應(yīng)該為int型外里,需要返回一個(gè)int型整數(shù)
  • 主函數(shù)可以
    1. 定義形參來接收實(shí)參數(shù)據(jù)
    2. 也可以省略形參(此時(shí)操作系統(tǒng)所傳遞過來的實(shí)參數(shù)據(jù)將被忽略)

定義有形參的主函數(shù)main:

int main(int argc, char*argv[])
{
    /*
    此處定義代碼語句
    */
    return 0;
}

語法說明:

  • argc標(biāo)識(shí)所接收到的參數(shù)個(gè)數(shù);
  • argv是一個(gè)char型指針數(shù)組特石,數(shù)組元素分別為argv[0]~arbv[argc-1]盅蝗。參數(shù)以字符串形式傳遞,其中argc[0]所指向的字符數(shù)組存放的是該文件程序的文件名姆蘸,argc[1]所指向的字符數(shù)組存放的是第1個(gè)實(shí)參數(shù)據(jù)墩莫,......;
  • 采用無參形式時(shí),操作系統(tǒng)所傳遞過來的實(shí)參數(shù)據(jù)將被忽略
  • 主函數(shù)通過返回值將自己的運(yùn)轉(zhuǎn)狀態(tài)返回給操作系統(tǒng)逞敷,通常0表示正常狂秦,用-1表示異常。

代碼示例:帶形參和返回值的主函數(shù)定義格式

#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
    for(int n=0; n<argc; n++) //接收用戶輸入的參數(shù)推捐,使用循環(huán)語句        
    cout<<argv[n]<<endl; //顯示用戶輸入的參數(shù)裂问。
    return 0;
}     

Microsoft c++編譯器對(duì)主函數(shù)語法處理的差異

美國微軟公司開發(fā)的c++編譯器,在對(duì)c++語法的處理上有一定的差異牛柒,主要提現(xiàn)在visual c++ 6.0和visual studio系列這兩個(gè)集成開發(fā)環(huán)境的使用上堪簿。

  • visual c++ 6.0中,主函數(shù)可以沒有返回值皮壁,也就是主函數(shù)可以定義為void椭更,例如:

    #include <iostream>
    using namespace std;
    void main(){
      //此處定義函數(shù)體代碼
      return; //如果該語句是最后一條語句,則可以省略
    }
    
  • visual studio 系列集成開發(fā)環(huán)境

    該環(huán)境在主函數(shù)的定義上蛾魄,于其他環(huán)境有所區(qū)別虑瀑,該系列可以使用應(yīng)用程序向?qū)硇陆ㄩ_發(fā)項(xiàng)目,例如:假設(shè)我們新建win32控制臺(tái)應(yīng)用程序滴须,該環(huán)境將自動(dòng)創(chuàng)建一個(gè)c++源文件缴川,該文件的文件頭和主函數(shù)如下:

    #include "stdafx.h" //包含visualstudio集成開發(fā)環(huán)境所必須的一些信息。
    int _tmain(int argc, _TCHAR *argv[]) 
    {
      system("pause");//添加該語句描馅,暫停程序執(zhí)行把夸,以便程序員檢查運(yùn)行結(jié)果。
      return 0;
    }
    

    這是因?yàn)関isual studio集成開發(fā)環(huán)境同時(shí)支持ANSI編碼和Unicode編碼的程序開發(fā)铭污,使用_tmain()命名主函數(shù)恋日,可以很方便的在兩種字符代碼之間切換。

    初學(xué)者使用visual studio時(shí)嘹狞,可以選擇空項(xiàng)目岂膳,然后自己添加新建源程序文件,在return語句之前磅网,記得加入一個(gè)system("pause");添加該語句谈截,暫停程序執(zhí)行,以便程序員檢查運(yùn)行結(jié)果。

  • 使用Windows圖形界面程序時(shí)

    需要將主函數(shù)定義為WinMain()或_tWinMain()簸喂,這個(gè)時(shí)windows運(yùn)用程序執(zhí)行的起點(diǎn)毙死。這兩個(gè)名字是微軟公司為Windows圖形界面的主函數(shù)所指定的函數(shù)名。并不是c++標(biāo)準(zhǔn)指定的喻鳄。

3.6遞歸函數(shù)

假設(shè)要求一個(gè)數(shù)N的階乘扼倘,也就是求N!

1、遞推法:

遞推法利用已知條件(0除呵!= 1)和地推公式:

n再菊!= n x(n-1)

逐步遞推求出1!颜曾、2纠拔!、... ...泛豪、直到求出N绿语!

#include <iostream>
using namespace std;
int Factorial(int N)
{
    int result = 1; //已知:0!=1
    for(int n = 1; n<=N;n++)
        result = n*result; //遞推公式:n候址!= n*(n-1)  
    return result;
  }
int main()
{
    int N;
    cout<<"請(qǐng)輸入原始值N:";
    cin>>N;
    cout<<Factorial(N);
    return 0;
}

遞推法求解問題的基本思想是從已知條件出發(fā)吕粹,根據(jù)地推公司由簡(jiǎn)到繁,逐步逼近岗仑,最終求出問題的解匹耕,這種方式也稱為正向遞推。正向遞推的每一步驟都是已知問題n-1的解荠雕,遞推求解問題n的解稳其,這些遞推步驟是在重復(fù)計(jì)算遞推公式,可使用循環(huán)結(jié)構(gòu)來描述遞推算法炸卑。

2既鞠、遞歸法:

遞歸法是程序設(shè)計(jì)中一種基于“函數(shù)嵌套調(diào)用”原理求解問題的方法。遞歸法求解問題的過程分2步完成:

  1. 第一步

    按照遞推公式由繁到簡(jiǎn)盖文,將求問題n的解降階成求問題n-1的解嘱蛋,直到滿足已知條件(稱為遞歸終結(jié)條件)不能降階為止,這個(gè)過程稱為逆向遞推五续;

  2. 第二步

    函數(shù)逐級(jí)返回結(jié)果洒敏,最終求出問題的解,這個(gè)過程稱為回歸疙驾。

#include <iostream>
using namespace std;
int Factorial(int N)
{
    int result; //用于保存結(jié)果
    if(N==0)
        result=0;
    else if(N==1)
        result = 1;
     else
        result = N*Factorial(N-1); //調(diào)用自身凶伙,參數(shù)降階為N-1
        return result;
}
int main()
{
    int N;
    cout<<"請(qǐng)輸入原始值N:";
    cin>>N;
    cout<<Factorial(N);
    return 0;
}

c++語言將直接或間接調(diào)用自身的函數(shù),稱為遞歸函數(shù)它碎。

與前面所講解的重載函數(shù)函荣,帶默認(rèn)形參值显押、內(nèi)聯(lián)函數(shù)的函數(shù)不同的是,遞歸函數(shù)不僅僅是一個(gè)語法概念傻挂,其背后還暗含了遞歸法求解問題的算法設(shè)計(jì)思想乘碑。

遞歸函數(shù)的定義和調(diào)用:

函數(shù)類型 函數(shù)名(形式參數(shù)列表)
{
    ... ...
    if(遞歸終結(jié)條件) //條件一
        取得已知結(jié)果 //條件二
    else
        按照遞歸公式調(diào)用自身 //條件三
    ... ...
}

遞歸函數(shù)的執(zhí)行過程:

  1. 計(jì)算機(jī)在執(zhí)行函數(shù)調(diào)用語句跳轉(zhuǎn)到被調(diào)函數(shù)時(shí),為其形參及函數(shù)體中定義的局部變量分配內(nèi)存踊谋,建立被調(diào)函數(shù)的棧幀
  2. 函數(shù)可以嵌套調(diào)用蝉仇,每增加一級(jí)函數(shù)調(diào)用旋讹,棧幀就增加一個(gè)殖蚕,每退出一級(jí)函數(shù)調(diào)用,棧幀就減少一個(gè)
  3. 計(jì)算機(jī)執(zhí)行遞歸函數(shù)的過程就是遞歸函數(shù)不斷嵌套調(diào)用自身沉迹、不斷建立新棧幀的過程睦疫,即逆向遞推的過程。
  4. 當(dāng)遞歸終結(jié)條件成立時(shí)停止調(diào)用鞭呕,開始逐級(jí)返回結(jié)果蛤育,退出遞歸函數(shù)并依次釋放棧幀,這就是回歸的過程葫松。

遞歸的函數(shù)嵌套調(diào)用瓦糕,次數(shù)必須是有限的,無線調(diào)用腋么,會(huì)不停建立新的棧幀咕娄,最終超出程序的內(nèi)存占用,會(huì)導(dǎo)致棧溢出的錯(cuò)誤珊擂。

  1. 遞歸法比遞推法速度慢圣勒。

    遞推算法使用循環(huán)算法來實(shí)現(xiàn),速度塊摧扇,遞歸算法圣贸,使用函數(shù)調(diào)用,需要額外的操作扛稽, 因此速度慢

  2. 遞歸法比遞推法適用范圍廣

    能用遞推求解的算法吁峻,一定可以使用遞歸來求解,反之則不然在张。

漢諾塔問題:

#include <iostream>
using namespace std;
void hanoi(int N,char source, char relay, char destination)
{
    if(N==1)
        cout<<source<<"-->>"<<destination<<endl;
    else
    {
        /*hanoi(N-1,source=a,destination=b,relay=c)把a(bǔ)上的N-1個(gè)盤中移到b*/
        hanoi(N-1, source, destination, relay);
        cout<<source<<"-->>"<<destination<<endl;// a-->>b
        /*hanoi(N-1,relay=a, source=b, destination=c)把b上的N-1個(gè)移動(dòng)到c*/
        hanoi(N-1, relay, source, destination);
    }
}
int main()
{
    int N;
    cout<<"請(qǐng)輸入要移動(dòng)的圓盤數(shù)量N:";
    cin>>N;
    cout<<"移動(dòng)"<<N<<"個(gè)盤子的步驟"<<endl;
    hanoi(N,'a','b','c');
    return 0;
}

四锡搜、系統(tǒng)函數(shù)

程序員編寫的函數(shù)可以在下個(gè)項(xiàng)目中繼續(xù)使用,這就是重用函數(shù)的代碼瞧掺,隨著時(shí)間的推移耕餐,程序員將積累越來越多的函數(shù),重用這些函數(shù)辟狈,可以顯著的提高開發(fā)效率

c++也預(yù)先編寫了很多常用的函數(shù)肠缔,提供給廣大程序員使用夏跷,這些函數(shù)統(tǒng)稱為系統(tǒng)函數(shù)

c++語言是在C語言基礎(chǔ)上發(fā)展而來的,C語言是機(jī)構(gòu)化程序設(shè)計(jì)語言明未,系統(tǒng)函數(shù)是其重要的附屬組成部分槽华。C語言函數(shù)的源代碼,被編譯成機(jī)器語言趟妥,以庫文件的形式猫态,隨編譯器系統(tǒng)提供。庫文件的名稱披摄,通常為”.lib“亲雪,庫文件通常存在編譯器安裝文件目錄中的lib子目錄中,這些庫文件被稱為標(biāo)準(zhǔn)C庫疚膊。

調(diào)用標(biāo)準(zhǔn)C庫中的系統(tǒng)函數(shù)义辕,都需要先聲明其函數(shù)原型,為了方便程序員寓盗,C語言預(yù)先編寫好這些系統(tǒng)函數(shù)的原型聲明語句灌砖,并按功能分別保存在若干個(gè)不同的頭文件中。程序員只要用#include指令傀蚌,包含相應(yīng)的頭文件基显,就可以調(diào)用這些系統(tǒng)函數(shù)。程序鏈接時(shí)善炫,被調(diào)用的系統(tǒng)函數(shù)代碼將被連接到可執(zhí)行程序文件之中撩幽。

c++語言全盤繼承了C語言的標(biāo)準(zhǔn)C庫,另外又增加了一些新的庫销部,新庫中包括了新增的系統(tǒng)函數(shù)摸航,但更對(duì)的是新增了面向?qū)ο蟮南到y(tǒng)類庫,這些新庫舅桩,就被稱為c++標(biāo)準(zhǔn)庫酱虎。c++標(biāo)準(zhǔn)庫引入了命名空間的概念,所有的新增的系統(tǒng)函數(shù)和系統(tǒng)類庫擂涛,都定義在命名空間std當(dāng)中读串。

4.1 C語言系統(tǒng)函數(shù)

系統(tǒng)函數(shù)極大的擴(kuò)展了C語言的功能,程序員能夠站在更高的起點(diǎn)上開發(fā)程序撒妈,程序員在調(diào)用系統(tǒng)函數(shù)前恢暖,需閱讀系統(tǒng)提供的手冊(cè),學(xué)習(xí)各系統(tǒng)函數(shù)的功能及調(diào)用語法狰右,并用#include指令包含相應(yīng)的頭文件杰捂。標(biāo)準(zhǔn)C庫的頭文件的擴(kuò)展名都是“.h

1 、輸入輸出函數(shù)

C語言本身沒有輸入輸出語句棋蚌,而是通過輸入輸出函數(shù)來實(shí)現(xiàn)輸入和輸出嫁佳,下面介紹兩個(gè)標(biāo)準(zhǔn)的輸入函數(shù)以及2個(gè)標(biāo)準(zhǔn)的輸出函數(shù)挨队。使用這些輸入輸出函數(shù),需要使用#include指令包含頭文件<stdio.h>

格式化輸入函數(shù):scanf

int scanf(char *format, 變量地址列表);
  • 參數(shù)format是格式控制字符串蒿往,其中包括格式符和分隔符盛垦,格式符是以”%“開頭的字符串,用于指定輸入數(shù)據(jù)的類型或格式瓤漏,參見表6-2
  • 變量地址列表指定保存輸入數(shù)據(jù)的變量地址腾夯,一次可為多個(gè)變量輸入數(shù)據(jù),此時(shí)應(yīng)為每個(gè)變量指定一個(gè)格式符蔬充,格式符應(yīng)與變量的數(shù)據(jù)類型一致蝶俱,多個(gè)變量地址之間用逗號(hào)”,“隔開娃惯,多個(gè)格式符之間通常用空格或逗號(hào)隔開跷乐,輸入數(shù)據(jù)時(shí)相應(yīng)地也用空格或逗號(hào)隔開肥败,以回車結(jié)束趾浅。
  • 返回值是int型,返回輸入數(shù)據(jù)的個(gè)數(shù)馒稍。
  • 調(diào)用函數(shù)時(shí)皿哨,程序暫停執(zhí)行,等待用戶從鍵盤輸入數(shù)據(jù)纽谒,以回車結(jié)束证膨。
#include <stdio.h>
int x; scanf("%d",&x); //輸入十進(jìn)制整數(shù),保存到int型變量x中
float y; scanf("%f",&y ); //輸入十進(jìn)制實(shí)數(shù)鼓黔,保存到float型變量y中
double z; scanf("%lf",&z);//輸入十進(jìn)制實(shí)數(shù)央勒,保存到double型變量z中
char ch; scanf("%c",&ch);//輸入一個(gè)字符,保存在char型變量ch中
char str[20]; scanf("%s",str)//輸入一個(gè)字符串澳化,保存到char型數(shù)組str中
scanf("%d %f %lf %c %s",&x,&y,&z,&ch,&str)//一次性輸入5個(gè)不同類型的數(shù)據(jù)

表6-2:

整數(shù) %d 十進(jìn)制數(shù)
整數(shù) %o 八進(jìn)制數(shù)
整數(shù) %x 十六進(jìn)制數(shù)
實(shí)數(shù) %f float型浮點(diǎn)數(shù)
實(shí)數(shù) %lf double型浮點(diǎn)數(shù)
- %c 單個(gè)字符
- %s 字符串

格式化輸出函數(shù)printf:

int printf(char*format,表達(dá)式列表);
  • 參數(shù)format是格式化控制字符串崔步,其中包括格式符和非格式符,格式符是以“%”開頭缎谷,用于指定輸出數(shù)據(jù)的類型或格式井濒,參見表6-2,非格式符原樣輸出
  • printf中的格式符可以指定輸出數(shù)據(jù)的域?qū)挘达@示時(shí)的占位寬度)捆毫,實(shí)際數(shù)據(jù)達(dá)不到域?qū)挄r(shí)補(bǔ)空格愚墓,輸出實(shí)數(shù)時(shí)還可以指定輸出的精度(即輸出幾位小數(shù))
  • 表達(dá)式列表指定需要輸出的常量音念、變量表達(dá)式,一次性可以輸出多個(gè)表達(dá)式者甲,此時(shí)應(yīng)為每個(gè)表達(dá)式指定一個(gè)格式符,格式符應(yīng)與表達(dá)式結(jié)果的數(shù)據(jù)類型一致砌创,多個(gè)表達(dá)式之間用逗號(hào)“,”隔開
  • 返回值是int型虏缸,返回輸出數(shù)據(jù)的個(gè)數(shù)
  • 調(diào)用該函數(shù)時(shí)將從右到左的順序計(jì)算各表達(dá)式甥厦,然后按從左至右的順序顯示各表達(dá)式的結(jié)果。

舉例:

int x=10; printf("x+5=%d",x+5); //輸出x+5=15
float y=5.5; printf("y+1=%f",y+1);//輸出y+1=6.5
double z=5.5; printf("z=%lf",z);//輸出z=5.5
char ch='A';printf("ch=%c",ch);//輸出ch=A
char str[20]="china";printf("%s",str);//輸出china
printf("%5d, %5.2f, %5.2lf, %5c, %5s",x, y, z, ch, str);//一次顯示5各不同類型的數(shù)據(jù)//格式花每個(gè)數(shù)據(jù)的輸出寬度為5寇钉,輸出實(shí)數(shù)時(shí)保留2位小數(shù)刀疙。

單字符輸入函數(shù)getchar

語法說明:

int getchar();
  • 調(diào)用該函數(shù)時(shí),程序暫停執(zhí)行扫倡,等待用戶從鍵盤輸入一個(gè)字符串谦秧,以回車結(jié)束
  • 返回值是int型,返回所輸入字符的ASCII編碼值
char ch; 
ch = getchar();//輸入一個(gè)字符撵溃,保存到變量ch中

單字符輸出函數(shù)putchar

int putchar(int c);
  • 調(diào)用該函數(shù)將變量c中的字符輸出到顯示器上疚鲤,實(shí)際上,變量c中保存的式字符的ASCII碼值缘挑,
  • 返回值是int型集歇,返回所輸出的字符的ASCII碼值
putchar('A');//顯示字符A
putchar('A'+32);//顯示字符A

4.2 數(shù)學(xué)函數(shù):#include <math.h>

求一元二次方程根ax^2+bx+c=0的演示程序

首先要判斷\Delta = b^2-4ac\geq0,則x = \frac{-b\pm\sqrt{b^2-4ac}}{2a}语淘,否則x無實(shí)數(shù)根

#include <stdio.h>
#include <math.h>
#include <iostream>
int main()
{
    double a, b, c; //一元二次方程的實(shí)數(shù)部分诲宇。
    scanf("%lf %lf %lf",&a,&b,&c); //輸入這三個(gè)實(shí)數(shù)
    double d = b * b - 4 * a * c; //計(jì)算Δ的值
    if (d < 0) printf("無實(shí)數(shù)根\n");
    else
    {
        double x1, x2;
        x1 = (-b + sqrt(d)) / (2 * a);   x2 = (-b - sqrt(d)) / (2 * a);
        printf("x1=%.10lf,x2=%.10lf\n", x1, x2);
    }
    system("pause");
    return 0;
}

4.3 字符串處理函數(shù)

#include <stdio.h>
#include <string.h>
#include <iostream>
int main()
{
    char str1[20]="hello",str2[10];
    printf("%d\n",strlen(str1));// 函數(shù)strlen求字符數(shù)組str1中字符串的長(zhǎng)度,結(jié)果為5
    strcpy(str2,",world!");//函數(shù)strcpy將字符串“,world!"拷貝到字符數(shù)組str2中
    strcat(str1,str2);//函數(shù)strcat將str2中的字符串連接到str1中字符串的后面
    printf("%s\n",str1);//顯示連接后的str1字符串惶翻,結(jié)果為hello world姑蓝!
    printf("%d\n",strlen(str1));//顯示連接后str1中新字符串的長(zhǎng)度,結(jié)果為13
    system("pause");
    return 0;
}

4.4動(dòng)態(tài)內(nèi)存分配函數(shù)

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
int main()
{
    int *p;
    /* 函數(shù)malloc返回所分配內(nèi)存的首地址吕粗,且必須制定分配的內(nèi)存單元的大小纺荧,返回值其類型為“void”,
       需轉(zhuǎn)為“int*”,而10*sizeof(int)可以計(jì)算出颅筋,1個(gè)int型變量所占用的字節(jié)數(shù)宙暇。 */
    p = (int *)malloc(10*sizeof(int));//動(dòng)態(tài)分配一個(gè)含有10個(gè)元素的int型數(shù)組
    for(int n=0;n<10;n++)
    {
        *(p+n) = n*n;
        printf("%d\n",p[n]);
    }
    free(p);
    system("pause");
    return 0;
}

4.5 命名空間

我們?cè)诰帉懗绦驎r(shí),可以使用各種渠道得到的函數(shù)议泵,但是C語言和C++都規(guī)定占贫,所有的外部函數(shù)不能重名,但我們?cè)谑褂猛鈦砗瘮?shù)時(shí)肢簿,不同的機(jī)構(gòu)不同的程序員開發(fā)的函數(shù)難免會(huì)重名靶剑,比如山東的德州和美國的德州,單獨(dú)看德州兩個(gè)字池充,這兩個(gè)地方重名了桩引,但是如果加上國度,這兩個(gè)地方就能夠準(zhǔn)確的區(qū)分開來收夸,這個(gè)國度就是命名空間的概念坑匠。

C++引入了命名空間的概念,不同的程序員在各自的命名空間內(nèi)定義外部函數(shù)和全局變量卧惜,就可以消除重名的問題厘灼。

1夹纫、定義方式

在命名空間中定義函數(shù)和全局變量,使用namespace關(guān)鍵值進(jìn)行申明设凹。然后將函數(shù)和全局變量定義在其后的一對(duì)大括號(hào){}之中舰讹。例子如下:

namespace Tom // 通過namespace進(jìn)行申明一個(gè)名叫Tom的命名空間
{
    int x,y;
    void fun1(){......}
    void fun2(){......}
}

2、訪問方式

訪問命名空間中的函數(shù)和全局變量

1闪朱、直接訪問

通過命名空間名稱+雙冒號(hào)::+全局變量標(biāo)識(shí)符/函數(shù)名的方式進(jìn)行訪問:

Tom::x=10; Tom::y=20; //訪問全局變量
Tom::fun1(); Tom::fun2(); //調(diào)用命名空間Tom里的函數(shù)

雙冒號(hào)(::)稱之為作用域運(yùn)算符

2月匣、使用關(guān)鍵字using先申明各個(gè)標(biāo)識(shí)符的命名空間

也可以先聲明各個(gè)標(biāo)識(shí)符的命名空間,使用關(guān)鍵字using奋姿,如果事先聲明了要訪問的各個(gè)標(biāo)識(shí)符锄开,再訪問的時(shí)候,可以省略命名空間名称诗。

using Tom::x; //先聲明各標(biāo)識(shí)符的命名空間
using Tom::y;
using Tom::fun1();
using Tom::fun2();
x = 10; y = 20; 
//再通過標(biāo)識(shí)符訪問萍悴,訪問時(shí)可以省略命名空間
fun1(); fun2();

3、統(tǒng)以申明命名空間的所有標(biāo)識(shí)符

也可以先統(tǒng)一聲明命名空間里的所有標(biāo)識(shí)符寓免,再通過標(biāo)識(shí)符直接訪問癣诱。

using namespace Tom; //先統(tǒng)一聲明命名空間Tom里的所有標(biāo)識(shí)符
x = 10; y = 20; 
//再通過標(biāo)識(shí)符訪問,訪問時(shí)可以省略命名空間
fun1(); fun2();

通過這種方式訪問方式是最簡(jiǎn)單直接的再榄。

4.6 匿名命名空間

using 和 namespace都是C++語言保留的關(guān)鍵字狡刘,C++語言還有個(gè)默認(rèn)的匿名的命名空間享潜,如果程序員編寫函數(shù)或全局變量困鸥,定義時(shí)沒有定義在任何命名空間里,則默認(rèn)就屬于該匿名命名空間剑按,C++標(biāo)準(zhǔn)庫就引入了命名空間的概念疾就,所有函數(shù)實(shí)體,例如外部函數(shù)艺蝴、全局變量或?qū)ο蟮肉级x再命名空間std當(dāng)中,使用這些函數(shù)實(shí)體猜敢,除了需要使用#include指令包含相應(yīng)的頭文件之外姑荷,還需要聲明其命名空間,例如需要使用cin>>和cout<<對(duì)象輸入輸出數(shù)據(jù)缩擂,則除了需要用#include指令包含頭文件<iostream>之外鼠冕,還需要聲明其命名空間std,就是using namespace std;的由來胯盯。

4.7 c++中的系統(tǒng)函數(shù)

c++語言全盤繼承了c語言的語法規(guī)則懈费,同時(shí)也全盤繼承了C語言的標(biāo)準(zhǔn)C庫。c++標(biāo)準(zhǔn)庫新增了一些系統(tǒng)函數(shù)博脑,更多是新增了面向?qū)ο蟪绦蛟O(shè)計(jì)的系統(tǒng)類庫

1憎乙、c++語言系統(tǒng)類庫

經(jīng)常使用的cin票罐,cout輸入輸出語句,實(shí)際上就是c++標(biāo)準(zhǔn)庫預(yù)先定義好的對(duì)象泞边,cin是c++標(biāo)準(zhǔn)庫定義的一個(gè)標(biāo)準(zhǔn)輸入流對(duì)象该押,而cout則是一個(gè)標(biāo)準(zhǔn)輸出流對(duì)象,使用cin和cout對(duì)象使用#include指令包含相應(yīng)的文件頭“iostream”阵谚,還需要聲明其命名空間“std”

#include <iostream>using namespace std;

c++語言是在c語言基礎(chǔ)上發(fā)展而來的沈善,可以在很大程度上替代c語言,例如

  1. 用cin椭蹄,cout輸入/輸出流對(duì)象闻牡,代替原來的輸入輸出函數(shù)
  2. 用字符串類string,代替原來的字符數(shù)組和字符串處理函數(shù)
  3. 用new和delete這2個(gè)運(yùn)算符绳矩,代替原來的動(dòng)態(tài)內(nèi)存分配函數(shù):malloc和free

C語言是機(jī)構(gòu)化設(shè)計(jì)語言罩润,它使用函數(shù)來提很多常使用的功能,c++語言繼承了這些機(jī)構(gòu)化程序設(shè)計(jì)方法翼馆,但又新增了面向?qū)ο蟪绦蛟O(shè)計(jì)方法割以,就是使用類和對(duì)象來實(shí)現(xiàn)程序功能。

4.8 多文件結(jié)構(gòu)下程序員與函數(shù)的關(guān)系

  1. 為別人提供函數(shù)的程序員
    • 將常用功能或算法定義成函數(shù)应媚,保存到源文件(擴(kuò)展名為.cpp)严沥;將源程序文件編譯成目標(biāo)代碼文件(擴(kuò)展名為.obj);通常還會(huì)進(jìn)一步將目標(biāo)代碼打包成一個(gè)函數(shù)庫文件(擴(kuò)展名通常為.lib)
    • 為函數(shù)庫中的函數(shù)編寫聲明語句中姜,集中保存在一個(gè)頭文件中(擴(kuò)展名為.h)
    • 發(fā)布或小數(shù)函數(shù)庫產(chǎn)品消玄,其中包含庫文件和頭文件,庫文件為目標(biāo)代碼(即機(jī)器語言)丢胚,其他程序員只能調(diào)用翩瓜,無法閱讀修改,而頭文件是函數(shù)聲明語句的源碼携龟,其它程序員可以閱讀兔跌,以了解函數(shù)的功能與調(diào)用接口
  2. 使用別人函數(shù)的程序員
    • 可以使用系統(tǒng)函數(shù),也可以獲得(比如購買)第三方開發(fā)的函數(shù)庫
    • 編寫程序時(shí)調(diào)用別人函數(shù)庫中的函數(shù)峡蟋,以實(shí)現(xiàn)某種特定的功能坟桅,調(diào)用前需要用#include指令包含相應(yīng)的文件頭
    • 連接時(shí),連接器將函數(shù)庫中被調(diào)函數(shù)代碼與自己的程序連接到一起蕊蝗,形成最終語句仅乓。

五、結(jié)構(gòu)化程序設(shè)計(jì)回顧

運(yùn)用結(jié)構(gòu)化程序設(shè)計(jì)匿又,可以將一個(gè)大型功能方灾,分解成多個(gè)模塊,分而治之,c++語言以函數(shù)的形式來描述各個(gè)模塊裕偿,這就是函數(shù)的定義洞慎。然后再通過調(diào)用,將各個(gè)算法模塊組裝起來嘿棘,最終形成一個(gè)完整的算法流程劲腿。

一個(gè)編寫好的c++函數(shù)可以備同一項(xiàng)目的多個(gè)程序員調(diào)用,也可以在今后的項(xiàng)目中繼續(xù)使用鸟妙,這就是函數(shù)代碼的重用焦人。

市場(chǎng)上還要很多廠家為程序員提供編寫好的,可以實(shí)習(xí)的各種不同功能得函數(shù)庫重父,本章將以Windows圖形用戶界面GUI程序花椭,win32 AP1函數(shù)庫進(jìn)行講解如何開發(fā)一個(gè)windows圖形界面程序

Windows圖形用戶界面程序編程原理

  1. 使用圖形界面設(shè)計(jì)器設(shè)計(jì)圖形界面窗口,設(shè)計(jì)好的窗口備稱為資源房午。
  2. 編寫主函數(shù)矿辽,創(chuàng)建并顯示窗口。
  3. Windows系統(tǒng)負(fù)責(zé)監(jiān)控鼠標(biāo)并捕獲用戶操作郭厌,如果用戶對(duì)窗口進(jìn)行了操作(例如點(diǎn)擊了某個(gè)按鈕)袋倔,那么Windows操作系統(tǒng)自動(dòng)調(diào)用該窗口對(duì)應(yīng)的處理函數(shù)(被稱為窗口過程
  4. 調(diào)用時(shí)會(huì)以消息的形式傳遞參數(shù),消息參數(shù)用于區(qū)分用戶進(jìn)行了何種操作折柠,消息參數(shù)以整數(shù)來標(biāo)記用戶所做的不同操作宾娜,為了方便程序員,win32 API將這些編號(hào)定義成易于記憶的符號(hào)常量扇售,例如WM_COMMAND(表示點(diǎn)擊了某個(gè)按鈕或菜單)前塔、WM_CLOSED(點(diǎn)擊了關(guān)閉窗口的x號(hào))等。

windows操作系統(tǒng)調(diào)用某個(gè)窗口過程缘眶,并傳遞消息參數(shù)嘱根,這邊稱為向該窗口過程發(fā)送消息;窗口過程接收消息巷懈,然后進(jìn)行處理,這被稱為對(duì)消息的響應(yīng)慌洪。

Windows圖形用戶界面運(yùn)行方式:

  1. 用戶啟動(dòng)程序

    主函數(shù)負(fù)責(zé)創(chuàng)建程序窗口顶燕,主函數(shù)是由程序員編寫語句定義的

  2. 用戶操作界面

    Windows將捕捉鼠標(biāo)操作,調(diào)用窗口過程函數(shù)冈爹,并傳遞WM_COMMAND消息涌攻,窗口過程不是程序員在主函數(shù)中編寫函數(shù)調(diào)用語句來調(diào)用的,而是由Windows操作系統(tǒng)自動(dòng)調(diào)用的频伤。像窗口過程這樣由Windows操作系統(tǒng)調(diào)用的函數(shù)恳谎,稱為回調(diào)函數(shù)。

  3. 窗口過程函數(shù),根據(jù)接收到的消息參數(shù)因痛,可以判斷出用戶進(jìn)行了何種操作婚苹,并按照程序功能執(zhí)行相應(yīng)的算法并顯示結(jié)果。因此程序員需要在窗口操作過程中編寫功能實(shí)現(xiàn)的語句鸵膏。

項(xiàng)目創(chuàng)建方法:

  1. 新建一個(gè)win32 Application工程
  2. 使用圖形界面設(shè)計(jì)器來設(shè)計(jì)窗口界面
  3. 新建一個(gè)c++源程序文件膊升,在其中編寫對(duì)應(yīng)的完整的c++程序代碼。

六谭企、自定義數(shù)據(jù)類型

c++語言提供了比較完善的基本數(shù)據(jù)類型廓译,其中包括整型(int、short债查、long)非区、浮點(diǎn)型(float、double)盹廷、字符型(char)和布爾類型(bool)等4大類

程序員可以根據(jù)需要為這些基本數(shù)據(jù)類型重新命名一個(gè)別名院仿,或基于這些基本數(shù)據(jù)定義新的復(fù)雜數(shù)據(jù)類型,這些類型被統(tǒng)稱為自定義數(shù)據(jù)類型速和,可以使用自定義數(shù)據(jù)類型來定義變量歹垫。

本節(jié)將介紹“typedef”類型定義語句,以及枚舉颠放、結(jié)構(gòu)體排惨、聯(lián)合體等常用自定義數(shù)據(jù)類型的定義和使用方法。

6.1 類型定義typedef

可以使用typedef關(guān)鍵字為基本數(shù)據(jù)類型碰凶,命名一個(gè)別名暮芭,或者為指針,數(shù)組定義新的數(shù)據(jù)類型

為基本數(shù)據(jù)類型命名一個(gè)別名:

typedef unsigned char AGE;
AGE X; //等價(jià)于unsigned char x欲低;

指針類型:

typedef int* IPointer; //為整型指針int* 起一個(gè)別名辕宏,IPointer
IPointer p1; //等價(jià)于:int*p1

定義數(shù)組類型:

typedef char NAME[10]; //定義一個(gè)字符型數(shù)組類型,命名為NAME,共計(jì)10個(gè)元素砾莱。
NAME name; //等價(jià)于:char name[10];

通過typedef統(tǒng)一數(shù)組類型的使用瑞筐,也能簡(jiǎn)化代碼,是程序易于閱讀腊瑟。也可以將類型定義與編譯預(yù)處理指令搭配使用聚假。

#include <iostream>
using namespace std;
#define _UNICODE
#ifdef _UNICODE;
    typedef wchar_t TCHAR;
#else
    typedef char TCHAR;
#endif

int main()
{
    TCAR ch;
    /*    代碼段    */
    return 0;
}

6.2 枚舉類型

布爾類型的一個(gè)主要特征是其值域只有2個(gè)取值,即真和假闰非,分別用關(guān)鍵字true和false表示膘格,實(shí)際的程序處理任務(wù)也會(huì)碰到和bool類型相似的數(shù)據(jù)類型,他們的值是有限的财松,我們稱他們的值域是可枚舉的瘪贱。例如一個(gè)星期只有星期一到星期日,這個(gè)值域就是可枚舉的值域。

c++語言可以將值域可枚舉的數(shù)據(jù)定義成新的數(shù)據(jù)類型菜秦,這些數(shù)據(jù)類型被統(tǒng)稱為枚舉類型甜害,值域中的每個(gè)取值稱之為一個(gè)枚舉元素。

enum 枚舉類型名 {枚舉常量1喷户,枚舉常量2唾那,... ...,枚舉常量n};//n是有限的
  • enum是定義枚舉類型的關(guān)鍵字
  • 枚舉類型名需要符合標(biāo)識(shí)符命名規(guī)則,
  • 枚舉常量是表示各個(gè)枚舉元素的名稱褪尝,須符合標(biāo)識(shí)符的命名規(guī)則闹获,相當(dāng)于是一個(gè)符號(hào)常量
  • 計(jì)算機(jī)內(nèi)部?jī)?chǔ)存枚舉型數(shù)據(jù)時(shí),用整數(shù)表示每個(gè)枚舉常量河哑,默認(rèn)情況下避诽,枚舉常量1=0,枚舉常量2=1璃谨,... ...沙庐,枚舉常量n=n-1,可以定義時(shí)為枚舉常量另行指定其他的值佳吞。
enum WeekDay{sun,mon,tur,thu,fri,sat};//默認(rèn)取值拱雏。sun=0,mon=1底扳,......
enum WeekDay{sun=7,mon=1,tur=2,wed=3,thu=4,fri=5,sat=6};//指定元素取值
enum WeekDay{sun=7,mon=1,tur,wed,thu,fri,sat};//等價(jià)上一條語句

演示程序:

#include <iostream>
using namespace std;
enum WeekDay{sun,mon,tur,thu,fri,sat};

int main(){
    enum WeekDay x;//定義1個(gè)WeekDay類型的枚舉變量x
    x=mon;//為x賦值铸抑,mon是枚舉常量,內(nèi)部數(shù)值是1
    cout<<x<<endl;//顯示枚舉類型對(duì)應(yīng)的數(shù)值衷模,結(jié)果為1
    return 0;
}    

注:枚舉變量不能直接用整數(shù)賦值鹊汛,因?yàn)閮烧邤?shù)據(jù)類型不同。

6.3 聯(lián)合體類型和結(jié)構(gòu)體類型

c++語言可以將多個(gè)變量組合在一起形成一個(gè)邏輯上的整體阱冶,使變量成為整體的一個(gè)成員刁憋,變量成員的類型可以相同,也可以不同木蹬,將多個(gè)變量成員組成的整體定義成新的數(shù)據(jù)類型至耻,這種數(shù)據(jù)類型能夠描述程序涉及所面臨的復(fù)雜數(shù)據(jù)。

  • 聯(lián)合體類型

    如果多個(gè)變量成員不會(huì)同時(shí)使用届囚,那就可以將它們定義成聯(lián)合體類型有梆,聯(lián)合體類型的特點(diǎn)是變量成員共用同一內(nèi)存單元,同一時(shí)刻只能保存一個(gè)成員的數(shù)據(jù)意系。定義聯(lián)合體的目的是節(jié)約內(nèi)存。

    語法:

    union 聯(lián)合體類型名{    數(shù)據(jù)類型1 變量成員名1;    數(shù)據(jù)類型2 變量成員名2;    ... ...    數(shù)據(jù)類型n 變量成員名n;};
    
    • union是定義聯(lián)合體類型的關(guān)鍵字
    • 聯(lián)合體類型名需符合標(biāo)識(shí)符的命名規(guī)則
    • 變量成員之間的數(shù)據(jù)類型可以相同饺汹,也可以不同蛔添,但變量名不能相同。

    代碼實(shí)例:

    /*定義聯(lián)合體變量數(shù)據(jù)類型 UType*/
    union UType{
      char ch;
      int x;
      double y;
    };
    /*使用聯(lián)合體類型可以定義聯(lián)合體變量,定義時(shí)需要union關(guān)鍵字迎瞧,聯(lián)合體變量定義好后夸溶,
    可以訪問其中的成員,訪問聯(lián)合體成員的語法形式是:聯(lián)合體變量名.成員名其中圓點(diǎn)"."稱為成員運(yùn)算符*/
    union UType a; //定義聯(lián)合體變量a
    a.ch;a.x; a.y; //訪問聯(lián)合體變量成員
    

    聯(lián)合體類型也稱為共用體類型凶硅,每個(gè)聯(lián)合體變量所占用的字節(jié)數(shù)缝裁,等于其最大成員的字節(jié)數(shù)。因?yàn)槁?lián)合變量的成員是共用同一內(nèi)存單元足绅,故聯(lián)合體變量同一時(shí)刻只能保持一個(gè)成員的數(shù)據(jù)捷绑。應(yīng)當(dāng)準(zhǔn)確理解聯(lián)合體類型的這個(gè)特點(diǎn),否則會(huì)造成數(shù)據(jù)丟失氢妈。

  • 結(jié)構(gòu)體類型

    如果多個(gè)變量成員同時(shí)使用粹污,那就將他們定義成結(jié)構(gòu)體類型,結(jié)構(gòu)體類型的特點(diǎn)是個(gè)變量成員單獨(dú)分配內(nèi)存單元首量,分別保存各自的數(shù)據(jù)壮吩。定義結(jié)構(gòu)體數(shù)據(jù)的目的是存儲(chǔ)復(fù)雜數(shù)據(jù)。

    c++語言可以將多個(gè)變量組合在一起形成邏輯上的整體加缘,使變量稱為整體的一個(gè)成員鸭叙,變量成員的類型可以相同,也可以不同拣宏,如果多個(gè)變量成員需要同時(shí)使用沈贝,那就可以將它們定義成結(jié)構(gòu)體類型。

    演示實(shí)例:

    int main()
    {
      char ID[11],Name[9];//保存學(xué)號(hào)和姓名
      int Age;//保存年齡    double Source;//保存成績(jī)
          strcpy(ID,"1510078620");
      strcpy(Name,"李若溪");
      Age=19;
      Score=90;
      /*在上述代碼種蚀浆,學(xué)生的學(xué)號(hào)缀程,姓名,成績(jī)市俊,年齡都存在關(guān)聯(lián)關(guān)系可以將其看作一個(gè)整體杨凑。
        它們都是某個(gè)學(xué)生個(gè)人信息的一部分。學(xué)生信息需要同時(shí)包含這些部分摆昧,否則信息就不完整了撩满。
         所以可以將學(xué)生信息定義成結(jié)構(gòu)體類型*/
    }
    

    定義結(jié)構(gòu)體類型語法:

    struct 結(jié)構(gòu)體類型名{    數(shù)量類型1 變量成員名1;    數(shù)量類型2 變量成員名2;    ... ...;    數(shù)據(jù)類型n 變量成員名n;};
    
    • struct是定義結(jié)構(gòu)體類型的關(guān)鍵字;
    • 結(jié)構(gòu)體類型名需符合標(biāo)識(shí)符的命名規(guī)則
    • 變量成員之間的數(shù)據(jù)類型可以相同绅你,也可以不同伺帘,但變量名不能相同。

    演示代碼:

    /*定義結(jié)構(gòu)體類型Student*/struct Student{
      char ID[11],Name[9];
      int Age;
      double Score;
     };
      struct Student a; //定義結(jié)構(gòu)體變量a
      a.ID; a.Name; a.Age; a.Score; //訪問各個(gè)成員
    

    與聯(lián)合體變量不同的是忌锯,結(jié)構(gòu)體數(shù)據(jù)類型的各個(gè)成員伪嫁,單獨(dú)分配內(nèi)存單元,分別保存各自的數(shù)據(jù)偶垮,每個(gè)結(jié)構(gòu)體變量占用的字節(jié)數(shù)张咳,等于其所有成員占用字節(jié)數(shù)的總和帝洪。

    結(jié)構(gòu)體類型的指針變量

    我們也可以定義結(jié)構(gòu)體的指針變量來保存某個(gè)結(jié)構(gòu)體的內(nèi)存地址。然后通過指針變量間接訪問結(jié)構(gòu)體變量及其成員脚猾,實(shí)例:

    struct Student a;
    struct Student *p; //定義**結(jié)構(gòu)體類型的指針變量**
    p = &a; //獲取結(jié)構(gòu)體變量a的內(nèi)存地址
    (*p).ID;(*p).Name;(*p).Age;(*p).Score; //通過指針間接訪問內(nèi)部成員葱峡。
    p->ID; p->Name; p->Age; p->Score;//通過指向運(yùn)算符,間接訪問龙助。
    

    由于通過(*p)的方式訪問結(jié)構(gòu)體成員比較繁瑣砰奕,c++語言引入了一種新的更加直觀的運(yùn)算符,就是指向運(yùn)算符:”->“提鸟,

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末军援,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子沽一,更是在濱河造成了極大的恐慌盖溺,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件铣缠,死亡現(xiàn)場(chǎng)離奇詭異烘嘱,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)蝗蛙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門蝇庭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人捡硅,你說我怎么就攤上這事哮内。” “怎么了壮韭?”我有些...
    開封第一講書人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵北发,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我喷屋,道長(zhǎng)琳拨,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任屯曹,我火速辦了婚禮狱庇,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘恶耽。我一直安慰自己密任,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開白布偷俭。 她就那樣靜靜地躺著浪讳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪涌萤。 梳的紋絲不亂的頭發(fā)上驻债,一...
    開封第一講書人閱讀 51,443評(píng)論 1 302
  • 那天乳规,我揣著相機(jī)與錄音形葬,去河邊找鬼合呐。 笑死,一個(gè)胖子當(dāng)著我的面吹牛笙以,可吹牛的內(nèi)容都是我干的淌实。 我是一名探鬼主播,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼猖腕,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼拆祈!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起倘感,我...
    開封第一講書人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤放坏,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后老玛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體淤年,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年蜡豹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了麸粮。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡镜廉,死狀恐怖弄诲,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情娇唯,我是刑警寧澤齐遵,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站塔插,受9級(jí)特大地震影響梗摇,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜佑淀,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一留美、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧伸刃,春花似錦谎砾、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至碉哑,卻和暖如春挚币,著一層夾襖步出監(jiān)牢的瞬間亮蒋,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來泰國打工妆毕, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留慎玖,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓笛粘,卻偏偏與公主長(zhǎng)得像趁怔,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子薪前,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容