0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
电子发烧友
开通电子发烧友VIP会员 尊享10大特权
海量资料免费下载
精品直播免费看
优质内容免费畅学
课程9折专享价
創(chuàng)作中心

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

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

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

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

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

我們知道,數(shù)組和指針是相同類型有序數(shù)據(jù)的集合,但很多時(shí)候需要將不同類型的數(shù)據(jù)捆綁在一起作為一個(gè)整體來對(duì)待,使程序設(shè)計(jì)更方便。在C語言中,這樣的一組數(shù)據(jù)被稱為結(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.類型與變量

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

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

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

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

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

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

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

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

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

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

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

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

由此可見,當(dāng)將方法作為結(jié)構(gòu)體的一部分聲明時(shí),就直接將方法和數(shù)據(jù)打包成為了一個(gè)新的數(shù)據(jù)類型RangeValidator。有了RangeValidator類型,就可以創(chuàng)建一個(gè)該類型的變量rangeValidator,即可通過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ù)名,使用方法如下:

宏展開后如下:

其相當(dāng)于:

如果有以下定義:

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

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

雖然pValidator與&rangeValidator.validate的類型不一樣,但它們的值相等,因此可以利用這一特性獲取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)用形式如下:

由此可見,rangeCheck()函數(shù)的實(shí)現(xiàn)不依賴任何具體校驗(yàn)器。 注意,在這里,作者并沒有提供完整的代碼,請(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)后,通過運(yùn)行單元測(cè)試以確保改進(jìn)沒有造成任何破壞,然后才去做下一次改進(jìn)。如此往復(fù)周而復(fù)始,每次改進(jìn)后都要運(yùn)行,通過這種方式保證在改進(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í)就要去做的事情,通過重構(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類型校驗(yàn)器。也就是說,如果兩種事物相似的話,必定存在某種抽象能夠統(tǒng)一它們,因此消除重復(fù)的行為會(huì)迫使團(tuán)隊(duì)提煉出許多的抽象,進(jìn)一步減少代碼之間的耦合。

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

2.類型與變量

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

在這里,還是以范圍值校驗(yàn)為例,在RangeValidatro結(jié)構(gòu)體中嵌套一個(gè)Validator類型的結(jié)構(gòu)體,即將Validator類型的變量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類型的isa作為RangeValidator結(jié)構(gòu)體成員時(shí),顯然rangeValidator.isa是一個(gè)結(jié)構(gòu)體變量名,可以象任何普通結(jié)構(gòu)體變量一樣使用。使用Validator類型表達(dá)式:

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

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

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

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

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

宏展開后如下:

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

如果有以下定義:

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

由于pValidator與&rangeValidator.isa不僅類型相同且值相等,則以下關(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)如下:

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

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

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


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

    關(guān)注

    1

    文章

    484

    瀏覽量

    70884
  • C語言編程
    +關(guān)注

    關(guān)注

    6

    文章

    90

    瀏覽量

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

    關(guān)注

    38

    文章

    130

    瀏覽量

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

    關(guān)注

    1

    文章

    130

    瀏覽量

    10998

原文標(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)注明出處。

收藏 6人收藏
  • 纵横天下王者1

評(píng)論

相關(guān)推薦

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

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

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

我們知道,數(shù)組和指針是相同類型有序數(shù)據(jù)的集合,但很多時(shí)候需要將不同類型的數(shù)據(jù)捆綁在一起作為一個(gè)整體來對(duì)待,使程序設(shè)計(jì)方便。在
的頭像 發(fā)表于 09-01 13:47 ?8103次閱讀
<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ù)類型

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

數(shù)組,結(jié)構(gòu)指針C語言里面最難的部分,如果在編程中可以熟練的運(yùn)用這三樣工具,會(huì)大大地提高開發(fā)
的頭像 發(fā)表于 03-02 10:10 ?1275次閱讀
<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語言入門之結(jié)構(gòu)指針

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

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

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

電子發(fā)燒友

中國(guó)電子工程師最喜歡的網(wǎng)站

  • 2931785位工程師會(huì)員交流學(xué)習(xí)
  • 獲取您個(gè)性化的科技前沿技術(shù)信息
  • 參加活動(dòng)獲取豐厚的禮品