c語言介面與實現 第11章序列理解

2021-08-14 22:29:55 字數 3935 閱讀 7050

本章中強調序列是本書中最有用的adt(abstact data type)之一,儘管序列的規格相對簡單,但可以用作陣列、鍊錶、棧、佇列和雙端佇列,實現這些資料結構的adt所需的設施通常都包含在序列中。前面這些基本是書中的原話,話不多說,上**。

seq.h

#ifndef seq_included

#define seq_included

#define t seq_t

typedef struct t *t;

extern t seq_new(int hint);

extern t seq_seq(void *x, ***);

extern

void seq_free(t *seq);

extern

int seq_length(t seq);

extern

void *seq_get(t seq, int i);

extern

void *seq_put(t seq, int i, void *x);

extern

void *seq_addlo(t seq, void *x);

extern

void *seq_addhi(t seq, void *x);

extern

void *seq_remlo(t seq);

extern

void *seq_remhi(t seq);

#undef t

#endif

seq.c

#include 

#include

#include

#include "assert.h"

#include "seq.h"

#include "array.h"

#include "arrayrep.h"

#include "mem.h"

#define t seq_t

struct t

;t seq_new(int hint)

arrayrep_init(&seq->array, hint, sizeof(void *),

alloc(hint*sizeof(void *)));

return seq;

}t seq_seq(void *x, ...)

va_end(ap);

return seq;

}void seq_free(t *seq)

int seq_length(t seq)

void *seq_get(t seq, int i)

void *seq_put(t seq, int i, void *x)

void *seq_remhi(t seq)

void *seq_remlo(t seq)

void *seq_addhi(t seq, void *x)

if(--seq->head < 0)

seq->length++;

return ((void **)seq->array.array)[(seq->head+i)%seq->array.length]=x;

}static

void expand(t seq)

}

這本書在介紹資料結構這塊的介面設計基本類似,所以我覺得我們在學習的時候需要注意總結,看別人的**介面是如何設計的,引數設計成什麼樣,返回值是什麼型別。

我在做開發的時候,需求很明確,但是如何在實現需求的同時,寫出良好的**和實現清晰的設計邏輯,是個很大的問題,用超生游擊隊小品(暴露年齡了,哈哈)的話說「憋三天憋四天,憋出個海南島吐魯番」,到最後功能是實現了,但**實現混亂,冗餘,可讀性差,甚至自己都不想再看寫過的東西,這些都是缺乏設計的表現。

現在主要針對上面的截圖說一下我的理解

函式說明

t seq_new(int

hint)

arrayrep_init(&seq->array, hint, sizeof(void *),

alloc(hint*sizeof(void *)));

return seq;

}

建立乙個seq_t* 變數seq, 並分配hint*sizeof(void *)大小的單元格,如果hint=0,則預設建立16個單元格,即上圖中的結構,此時seq->length=0,seq->head=0, seq->array.length=16,seq->array.size=sizeof(void *), seq->array.array為alloc返回的首位址。

t seq_seq(void *x, ...)

va_end(ap);

return seq;

}

往已建立的seq裡面寫資料,採用可變引數形式va_list實現,用seq_addhi在seq尾部填充資料,seq->head值不變,seq->length長度遞增,比如書中的例子

name=seq_seq(「c」, 「ml」, 「c++」, 「icon」, 「awk」, null);

void seq_free(t *seq)

釋放序列,seq有seq_t *型別強制轉換為array_t*型別,然後通過array_free函式來釋放,我們看看為什麼seq可以轉換為array_t*來釋放,先看array_free的實現

// t 為array_t

void array_free(t *

array)

可以看到seq_t只比array_t多兩個非指標變數int length和 int head,上面函式中「1」可以將seq->array陣列釋放掉,」2」可以將seq釋放掉。

有必要說一下**片段seq[i] 127

((void

**)seq->

array

.array)[(seq->head+i)%seq->

array

.length]

;

這裡的void ** 是二級指標,從順序結構上看直接作用於最後的array,是將array轉換為void *型別的陣列,我們知道陣列位址可以賦值給指標變數,比如int a, int *b; b=a; 所以void ** 是void *型別的陣列,將array這段記憶體空間轉換為陣列後,可以直接用陣列序號來定位某個元素。

理解了之前圖中的資料結構,對於元素的增減就比較好理解了

void * seq_remlo(t seq);

void * seq_remhi(t seq);

void * seq_addlo(t seq, void * x);

void * seq_addhi(t seq, void * x);

最後說明一下expand函式,**如下

// 在add函式中有呼叫,當seq->length == seq->array.length時

// 證明已占用單元格數量與開闢的單元格數量相等,即所有單元格已全部占用,無剩餘空間,

// 如需要再加入資料,需要重新申請更大的空間

演化結構如下圖所示

c語言介面與實現

分類 程式設計 2006 04 13 21 57 7392人閱讀收藏 舉報 語言c 資料結構 c lua exception 書中對atom,list,stack,hashtable,set,ring,exception等都作了 相信看過這邊書後,你使用c程式設計的功力會大為提高。也許使用c 的朋友...

C語言介面與實現 Atom

原子 atom 這一資料結構的工作原理基本類似於拉鍊式雜湊表,每個原子對應唯一的字串,不同的原子對應的字串內容不同 用數學語言講就是在原子和字串之間建立了雙射 原子的特點有三個 其一,每個原子對應的字串是不可變的 其二,相同內容的字串只會儲存一次,節省了儲存空間 其三,比較兩個字串是否相同時不必知道...

《c語言介面與實現》讀後感

書中對atom,list,stack,hashtable,set,ring,exception等都作了 相信看過這邊書後,你使用c程式設計的功力會大為提高。也許使用c 的朋友會認為這些c 的標準模板庫都可以實現,因此對c封裝這些不屑一顧。但是即使是c 程式設計師,我相信你看過本書後,就不會這麼認為了...