0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線(xiàn)課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

周立功教你學(xué)C語(yǔ)言編程:結(jié)構(gòu)體,使程序設(shè)計(jì)更方便——內(nèi)置函數(shù)指針和嵌套結(jié)構(gòu)體

AGk5_ZLG_zhiyua ? 來(lái)源:未知 ? 作者:電子大兵 ? 2017-09-06 09:27 ? 次閱讀

第二章為程序設(shè)計(jì)技術(shù),本文為2.2.3 內(nèi)置函數(shù)指針和2.2.4 嵌套結(jié)構(gòu)體

我們知道,數(shù)組和指針是相同類(lèi)型有序數(shù)據(jù)的集合,但很多時(shí)候需要將不同類(lèi)型的數(shù)據(jù)捆綁在一起作為一個(gè)整體來(lái)對(duì)待,使程序設(shè)計(jì)更方便。在C語(yǔ)言中,這樣的一組數(shù)據(jù)被稱(chēng)為結(jié)構(gòu)體。

>>>2.2.3內(nèi)置函數(shù)指針

面對(duì)一系列數(shù)據(jù),真正重要的不是如何存儲(chǔ)數(shù)據(jù),而是如何使用數(shù)據(jù)。實(shí)際上,一個(gè)結(jié)構(gòu)體的成員可以是數(shù)據(jù),還可以是包含操作數(shù)據(jù)的函數(shù)指針。為了支持這種風(fēng)格,在這里不妨引入一個(gè)新的概念——方法是作為某個(gè)結(jié)構(gòu)體的一部分聲明的,有了方法就可以操作存儲(chǔ)在結(jié)構(gòu)體中的數(shù)據(jù)。

1.類(lèi)型與變量

當(dāng)函數(shù)指針作為結(jié)構(gòu)體的成員時(shí),即將校驗(yàn)參數(shù)和調(diào)用校驗(yàn)器的函數(shù)指針?lè)庋b在一起,形成了一個(gè)新的結(jié)構(gòu)體類(lèi)型。有了類(lèi)型就可以定義一個(gè)該類(lèi)型的變量,然后就可以用這個(gè)變量引用校驗(yàn)參數(shù)和調(diào)用校驗(yàn)器函數(shù)。

為了支持這種風(fēng)格,C允許將方法作為某個(gè)結(jié)構(gòu)體的一部分來(lái)聲明,那么操作存儲(chǔ)在結(jié)構(gòu)體中的數(shù)據(jù)就很容易了,詳見(jiàn)程序清單2.18。

程序清單 2.18 范圍值校驗(yàn)器接口

接下來(lái)需要設(shè)計(jì)一個(gè)判斷value值是否符合范圍值要求的validateRange()接口函數(shù),其具體的實(shí)現(xiàn)詳見(jiàn)程序清單2.19。

程序清單 2.19 范圍值校驗(yàn)器接口函數(shù)的實(shí)現(xiàn)

同理,偶校驗(yàn)器OddEvenValidator和變量oddEvenValidator的定義詳見(jiàn)程序清單2.20。

程序清單 2.20 偶校驗(yàn)器接口

接下來(lái)同樣需要設(shè)計(jì)一個(gè)判斷value值是否符合偶校驗(yàn)要求的validateOddEven()接口函數(shù),其具體的實(shí)現(xiàn)詳見(jiàn)程序清單2.21。

程序清單 2.21 偶校驗(yàn)器接口函數(shù)的實(shí)現(xiàn)

顯然,無(wú)論是什么校驗(yàn)器,其共性是value值合法性判斷,因此可以共用一個(gè)函數(shù)指針,即特殊的函數(shù)指針類(lèi)型RangeValidate和OddEvenValidate被泛化成了一般的函數(shù)指針類(lèi)型Validate。其次,由于每個(gè)函數(shù)都有一個(gè)指向當(dāng)前對(duì)象的pThis指針,因此特殊的結(jié)構(gòu)體類(lèi)型struct _RangeValidator*和struct _OddEvenValidator *被泛化成了void *類(lèi)型,即可接受任何類(lèi)型數(shù)據(jù)的實(shí)參。比如:

這就是范型編程,校驗(yàn)器泛化接口的實(shí)現(xiàn)詳見(jiàn)程序清單 2.22。由于pRangeValidator與pThis的類(lèi)型不同,因此必須對(duì)pThis指針強(qiáng)制類(lèi)型轉(zhuǎn)換才能引用相應(yīng)結(jié)構(gòu)體的成員。

程序清單 2.22 通用校驗(yàn)器接口的實(shí)現(xiàn)(validator.c)

由此可見(jiàn),當(dāng)將方法作為結(jié)構(gòu)體的一部分聲明時(shí),就直接將方法和數(shù)據(jù)打包成為了一個(gè)新的數(shù)據(jù)類(lèi)型RangeValidator。有了RangeValidator類(lèi)型,就可以創(chuàng)建一個(gè)該類(lèi)型的變量rangeValidator,即可通過(guò)rangeValidator引用該結(jié)構(gòu)體的數(shù)據(jù),并調(diào)用相應(yīng)的處理函數(shù)。真正想強(qiáng)化的是由方法定義結(jié)構(gòu)體的思想,而不是實(shí)現(xiàn)結(jié)構(gòu)體時(shí)碰巧用到的那些數(shù)據(jù)。

2.初始化

使用名為newRangeValidator的宏將結(jié)構(gòu)體初始化:

其中,validateRange為范圍值校驗(yàn)器的函數(shù)名,使用方法如下:

宏展開(kāi)后如下:

其相當(dāng)于:

如果有以下定義:

即可通過(guò)pValidator引用RangeValidator的min和max。校驗(yàn)函數(shù)的調(diào)用方式如下:

以上調(diào)用形式的前提是已知pValidator指向了確定的結(jié)構(gòu)體類(lèi)型,如果pValidator將指向未知的校驗(yàn)器,顯然以上調(diào)用形式無(wú)法做到通用,那么將如何調(diào)用?

雖然pValidator與&rangeValidator.validate的類(lèi)型不一樣,但它們的值相等,因此可以利用這一特性獲取validateRange()函數(shù)的地址。比如:

其調(diào)用形式如下:

3.接口與實(shí)現(xiàn)

為了便于閱讀,如程序清單2.23所示詳細(xì)地展示了通用校驗(yàn)器的接口。

程序清單 2.23 通用校驗(yàn)器接口(validator.h)

以范圍值校驗(yàn)器為例,調(diào)用validateRange()的rangeCheck()函數(shù)的實(shí)現(xiàn)如下:

rangeCheck()函數(shù)的調(diào)用形式如下:

由此可見(jiàn),rangeCheck()函數(shù)的實(shí)現(xiàn)不依賴(lài)任何具體校驗(yàn)器。 注意,在這里,作者并沒(méi)有提供完整的代碼,請(qǐng)讀者補(bǔ)充完善。

>>>2.2.4嵌套結(jié)構(gòu)體

1.重構(gòu)

隨著添加一個(gè)又一個(gè)功能,處理一個(gè)又一個(gè)錯(cuò)誤,代碼的結(jié)構(gòu)會(huì)逐漸退化。如果對(duì)此置之不理,這種退化最終會(huì)導(dǎo)致糾結(jié)不清,難以維護(hù)的混亂代碼,因此需要經(jīng)常性地重構(gòu)代碼扭轉(zhuǎn)這種退化。

重構(gòu)就是在不改變代碼行為的前提下,對(duì)其進(jìn)行一系列小的改進(jìn),旨在改進(jìn)系統(tǒng)結(jié)構(gòu)的實(shí)踐活動(dòng)。雖然每個(gè)改進(jìn)都是微不足道的,甚至幾乎不值得去做,但如果將所有的改造疊加在一起時(shí),對(duì)系統(tǒng)設(shè)計(jì)和架構(gòu)的改進(jìn)效果是十分明顯的。

在每次細(xì)微改進(jìn)后,通過(guò)運(yùn)行單元測(cè)試以確保改進(jìn)沒(méi)有造成任何破壞,然后才去做下一次改進(jìn)。如此往復(fù)周而復(fù)始,每次改進(jìn)后都要運(yùn)行,通過(guò)這種方式保證在改進(jìn)系統(tǒng)設(shè)計(jì)的同時(shí)系統(tǒng)能夠正常工作。

重構(gòu)是持續(xù)進(jìn)行的,而不是在項(xiàng)目結(jié)束時(shí)、發(fā)布版本時(shí)、迭代結(jié)束時(shí)、甚至每天下班時(shí)才進(jìn)行。重構(gòu)是每隔一個(gè)小時(shí)或半個(gè)小時(shí)就要去做的事情,通過(guò)重構(gòu)可以持續(xù)地保持盡可能干凈、簡(jiǎn)單且有表現(xiàn)力的代碼。

大量的實(shí)踐證明,重復(fù)可能是軟件中一切邪惡的根源,許多原則和實(shí)踐規(guī)則都是為了控制與消除重復(fù)而創(chuàng)建的。消除重復(fù)最好的方法就是抽象,即將所有公共的函數(shù)指針移到一個(gè)單獨(dú)的結(jié)構(gòu)體中,創(chuàng)建一個(gè)通用的Validator類(lèi)型校驗(yàn)器。也就是說(shuō),如果兩種事物相似的話(huà),必定存在某種抽象能夠統(tǒng)一它們,因此消除重復(fù)的行為會(huì)迫使團(tuán)隊(duì)提煉出許多的抽象,進(jìn)一步減少代碼之間的耦合。

自從發(fā)明子程序以來(lái),軟件開(kāi)發(fā)領(lǐng)域的所有創(chuàng)新都是在不斷嘗試從源代碼中消滅重復(fù),即DRY(Don't Repeat Yourself)原則——?jiǎng)e重復(fù)自己,因?yàn)橹貜?fù)黏貼會(huì)帶來(lái)很多的問(wèn)題,所以無(wú)論在哪里發(fā)現(xiàn)重復(fù)的代碼,都必須消除它們。

2.類(lèi)型與變量

實(shí)際上,不管是范圍值校驗(yàn)器還是奇偶校驗(yàn)器,其本質(zhì)上都是校驗(yàn)器,其相同的屬性是校驗(yàn)參數(shù)和待校驗(yàn)的值,其相同的行為可以共用一個(gè)函數(shù)指針調(diào)用不同的校驗(yàn)器。根據(jù)依賴(lài)倒置原則,將它們相同的屬性和行為抽象為一個(gè)結(jié)構(gòu)體類(lèi)型Validator。比如:

在這里,還是以范圍值校驗(yàn)為例,在RangeValidatro結(jié)構(gòu)體中嵌套一個(gè)Validator類(lèi)型的結(jié)構(gòu)體,即將Validator類(lèi)型的變量isa作為RangeValidator結(jié)構(gòu)體的成員。比如:

由于&rangeValidator與&rangeValidator.isa的值相等,因此以下關(guān)系恒成立。比如:

即可將validateRange()函數(shù)原型:

中的“void *pThis”轉(zhuǎn)換為“Validator *pThis”,validatrRange()函數(shù)原型進(jìn)化為:

3.初始化

當(dāng)將Validator類(lèi)型的isa作為RangeValidator結(jié)構(gòu)體成員時(shí),顯然rangeValidator.isa是一個(gè)結(jié)構(gòu)體變量名,可以象任何普通結(jié)構(gòu)體變量一樣使用。使用Validator類(lèi)型表達(dá)式:

即可引用rangeValidator變量的結(jié)構(gòu)體成員isa的成員validate,即將rangeValidator.isa作為另一個(gè)點(diǎn)操作符的左操作符。比如:

由于點(diǎn)操作符的結(jié)合性是從左向右的,因此可以省略括號(hào)。其等價(jià)于:

只要將rangeValidator.isa看作一個(gè)Validator類(lèi)型的變量即可。

使用名為newRangeValidator的宏將結(jié)構(gòu)體初始化:

其中,validateRange為范圍值校驗(yàn)器函數(shù)名,使用方法如下:

宏展開(kāi)后如下:

其中,外面的{}為RangeValidator結(jié)構(gòu)體賦值,內(nèi)部的{}為RangeValidator結(jié)構(gòu)體的成員變量isa賦值。即:

如果有以下定義:

即可用pValidator引用RangeValidator的min和max。

由于pValidator與&rangeValidator.isa不僅類(lèi)型相同且值相等,則以下關(guān)系同樣成立:

因此可以利用這一特性獲取validateRange()函數(shù)的地址,即pValidator->validate指向validateRange()。其調(diào)用形式如下:

4.接口與實(shí)現(xiàn)

以范圍值校驗(yàn)器為例,validatorCheck()函數(shù)的調(diào)用形式如下:

當(dāng)然,也可以采取以下調(diào)用形式:

其效果是一樣的。

為了便于閱讀,如程序清單 2.24所示詳細(xì)地展示了通用校驗(yàn)器的接口。

程序清單 2.24通用校驗(yàn)器接口(validator.h)

以范圍值校驗(yàn)器為例,調(diào)用validateRange()的validatorCheck()函數(shù)的實(shí)現(xiàn)如下:

由此可見(jiàn),validatorCheck()函數(shù)的實(shí)現(xiàn)不依賴(lài)任何具體校驗(yàn)器,通用校驗(yàn)器接口的實(shí)現(xiàn)詳見(jiàn)程序清單 2.25。

程序清單 2.25 通用校驗(yàn)器接口的實(shí)現(xiàn)(validator.c)

在這里,作者并沒(méi)有提供完整的代碼,請(qǐng)讀者補(bǔ)充完善。


聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 指針
    +關(guān)注

    關(guān)注

    1

    文章

    480

    瀏覽量

    70564
  • C語(yǔ)言編程
    +關(guān)注

    關(guān)注

    6

    文章

    90

    瀏覽量

    21108
  • 周立功
    +關(guān)注

    關(guān)注

    38

    文章

    130

    瀏覽量

    37634
  • 結(jié)構(gòu)體
    +關(guān)注

    關(guān)注

    1

    文章

    130

    瀏覽量

    10844

原文標(biāo)題:周立功:結(jié)構(gòu)體,使程序設(shè)計(jì)更方便——內(nèi)置函數(shù)指針和嵌套結(jié)構(gòu)體

文章出處:【微信號(hào):ZLG_zhiyuan,微信公眾號(hào):ZLG致遠(yuǎn)電子】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    立功教你學(xué)C語(yǔ)言編程程序設(shè)計(jì):這樣寫(xiě)函數(shù)指針數(shù)組最好用

    立功教授數(shù)年之心血之作《程序設(shè)計(jì)與數(shù)據(jù)結(jié)構(gòu)》以及《面向AMetal框架與接口的編程(上)》,電子版已無(wú)償性分享到電子工程師與高校群體,在公
    的頭像 發(fā)表于 08-31 14:06 ?6908次閱讀
    <b class='flag-5'>周</b><b class='flag-5'>立功</b><b class='flag-5'>教你</b><b class='flag-5'>學(xué)</b><b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言</b><b class='flag-5'>編程</b>與<b class='flag-5'>程序設(shè)計(jì)</b>:這樣寫(xiě)<b class='flag-5'>函數(shù)</b><b class='flag-5'>指針</b>數(shù)組最好用

    立功教你學(xué)程序設(shè)計(jì)結(jié)構(gòu):內(nèi)存對(duì)齊和基本數(shù)據(jù)類(lèi)型

    我們知道,數(shù)組和指針是相同類(lèi)型有序數(shù)據(jù)的集合,但很多時(shí)候需要將不同類(lèi)型的數(shù)據(jù)捆綁在一起作為一個(gè)整體來(lái)對(duì)待,使程序設(shè)計(jì)方便。在
    的頭像 發(fā)表于 09-01 13:47 ?7998次閱讀
    <b class='flag-5'>周</b><b class='flag-5'>立功</b><b class='flag-5'>教你</b><b class='flag-5'>學(xué)</b><b class='flag-5'>程序設(shè)計(jì)</b><b class='flag-5'>結(jié)構(gòu)</b><b class='flag-5'>體</b>:內(nèi)存對(duì)齊和基本數(shù)據(jù)類(lèi)型

    高手們幫忙看下這個(gè)結(jié)構(gòu)嵌套程序,編譯無(wú)法通過(guò)

    ;<unnamed>" has no field "x"我查了一下C語(yǔ)言的相關(guān)書(shū)籍,問(wèn)題是內(nèi)層嵌套結(jié)構(gòu)沒(méi)有變量名,由于子
    發(fā)表于 03-15 11:08

    新書(shū)創(chuàng)作談:立功教授數(shù)十年之心血力作《程序設(shè)計(jì)與數(shù)據(jù)結(jié)構(gòu)

    整理出《程序設(shè)計(jì)與數(shù)據(jù)結(jié)構(gòu)》這本書(shū),其內(nèi)容如同培訓(xùn)講師的教案,是立功和團(tuán)隊(duì)的讀書(shū)筆記和程序設(shè)計(jì)實(shí)踐的心得。《
    發(fā)表于 05-15 18:04

    【完整資料】《程序設(shè)計(jì)與數(shù)據(jù)結(jié)構(gòu)立功數(shù)十年心血力作

    ,是立功和團(tuán)隊(duì)的讀書(shū)筆記和程序設(shè)計(jì)實(shí)踐的心得。《程序設(shè)計(jì)與數(shù)據(jù)結(jié)構(gòu)》重點(diǎn)闡述了三大方向內(nèi)容。C
    發(fā)表于 05-16 16:43

    漫談C語(yǔ)言結(jié)構(gòu)

    變量的方法代替函數(shù)(入口參數(shù))的重新定義就表示了結(jié)構(gòu)“中用”。繼續(xù)以上面的結(jié)構(gòu)為例子,我們來(lái)分析。假如現(xiàn)在我有如下
    發(fā)表于 11-15 15:59

    單片機(jī)C語(yǔ)言 -- 基于結(jié)構(gòu)的面向?qū)ο?b class='flag-5'>編程技巧

    1、Keil4 C51工程網(wǎng)址:2、需要一定的C語(yǔ)言基礎(chǔ),才看得懂此文。一、面向?qū)ο髥纹瑱C(jī)C語(yǔ)言的面向?qū)ο?/div>
    發(fā)表于 02-04 21:48

    程序設(shè)計(jì)與數(shù)據(jù)結(jié)構(gòu)》【完整資料】分享!

    。 在當(dāng)前工程師在C語(yǔ)言學(xué)習(xí)時(shí),遇到如指針函數(shù)函數(shù)指針,如何靈活應(yīng)用
    發(fā)表于 08-31 16:20

    C語(yǔ)言結(jié)構(gòu)對(duì)函數(shù)指針封裝示例

    C語(yǔ)言結(jié)構(gòu)對(duì)函數(shù)指針封裝示例示例:#include int i, j;struct DATE{
    發(fā)表于 07-15 06:18

    C語(yǔ)言入門(mén)教程-指向結(jié)構(gòu)指針

    指向結(jié)構(gòu)指針C語(yǔ)言中幾乎可以創(chuàng)建指向任何類(lèi)型的指針,包括用戶(hù)自定義的類(lèi)型。創(chuàng)建
    發(fā)表于 07-29 12:04 ?3153次閱讀

    C語(yǔ)言程序設(shè)計(jì)介紹

    包括:C 語(yǔ)言概述,算法基礎(chǔ),數(shù)據(jù)類(lèi)型、運(yùn)算符與表達(dá)式,順序 結(jié)構(gòu)程序設(shè)計(jì),選擇結(jié)構(gòu)程序設(shè)計(jì)
    發(fā)表于 02-17 15:49 ?0次下載

    C語(yǔ)言程序設(shè)計(jì)教程之結(jié)構(gòu)與共用的詳細(xì)資料說(shuō)明

    本文檔詳細(xì)介紹的是C語(yǔ)言程序設(shè)計(jì)教程之結(jié)構(gòu)與共用的詳細(xì)資料說(shuō)明主要內(nèi)容包括了:1
    發(fā)表于 03-01 17:20 ?11次下載
    <b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言</b><b class='flag-5'>程序設(shè)計(jì)</b>教程之<b class='flag-5'>結(jié)構(gòu)</b><b class='flag-5'>體</b>與共用<b class='flag-5'>體</b>的詳細(xì)資料說(shuō)明

    C程序設(shè)計(jì)基礎(chǔ)-數(shù)組與結(jié)構(gòu)

    數(shù)組,結(jié)構(gòu)指針C語(yǔ)言里面最難的部分,如果在編程中可以熟練的運(yùn)用這三樣工具,會(huì)大大地提高開(kāi)發(fā)
    的頭像 發(fā)表于 03-02 10:10 ?1031次閱讀
    <b class='flag-5'>C</b><b class='flag-5'>程序設(shè)計(jì)</b>基礎(chǔ)-數(shù)組與<b class='flag-5'>結(jié)構(gòu)</b><b class='flag-5'>體</b>

    C語(yǔ)言入門(mén)之結(jié)構(gòu)指針

    C語(yǔ)言中,指向結(jié)構(gòu)對(duì)象的指針變量既可以指向結(jié)構(gòu)
    的頭像 發(fā)表于 03-24 14:59 ?1059次閱讀

    結(jié)構(gòu)指針的關(guān)系

    C語(yǔ)言中,結(jié)構(gòu)(Struct)是一種用戶(hù)自定義的數(shù)據(jù)類(lèi)型,它允許您將不同類(lèi)型的數(shù)據(jù)項(xiàng)組合在一起,以便形成一個(gè)復(fù)雜的數(shù)據(jù)
    的頭像 發(fā)表于 01-11 08:00 ?1002次閱讀
    <b class='flag-5'>結(jié)構(gòu)</b><b class='flag-5'>體</b>與<b class='flag-5'>指針</b>的關(guān)系