2014-04-28 45 views
0

我的大學教授告訴我們,一般堆棧看起來是這樣的(我基本上從課程支持文件複製粘貼此):是C中的通用堆棧數據結構鏈接列表實現嗎?

typedef struct 
{ size_t maxe, dime; 
    char *b, *sv, *vf; 
} TStiva, *ASt; 

#define DIME(a) (((ASt)(a))->dime) 
#define BS(a) (((ASt)(a))->b) 
#define SV(a) (((ASt)(a))->sv) 
#define VF(a) (((ASt)(a))->vf) 
#define DIMDIF(s,d) (DIME(s) != DIME(d)) 
#define VIDA(a) (VF(a) == BS(a)) 
#define PLINA(a) (VF(a) == SV(a)) 

// Function Declarations 
void* InitS(size_t d,...); 
int Push(void* a, void* ae); 
int Pop (void* a, void* ae); 
int Top (void* a, void* ae); 

void *InitS(size_t d,...) 
{ ASt a = (ASt)malloc(sizeof (TStiva)); 
    va_list ap; 
    if (!a) return NULL; 
    va_start(ap,d); 
    a->maxe = va_arg(ap,size_t); 
    va_end(ap); 
    a->dime = d; 
    a->b = (char*)calloc(a->maxe, d);   
    if (!a->b) { free(a); return NULL; }  
    a->vf = a->b; 
    a->sv = a->b + d * a->maxe; 
    return (void *)a; 
} 

int Push(void *a, void *ae) 
{ if(PLINA(a)) return 0; 
    memcpy (VF(a), ae, DIME(a)); 
    VF(a) += DIME(a);   
    return 1; 
} 

int Pop(void *a, void *ae)  
{ if(VIDA(a)) return 0; 
    VF(a) -= DIME(a);   
    memcpy (ae, VF(a), DIME(a)); 
    return 1; 
} 

int Top(void *a, void *ae) 
{ if(VIDA(a)) return 0; 
    memcpy (ae, VF(a)-DIME(a), DIME(a)); 
    return 1; 
} 

不管怎麼說,這要成爲一個通用的堆棧實現與矢量,從中我不明白爲什麼Top,PushPop函數需要將堆棧數據結構稱爲void *

通過泛型,它不是想表示數據結構想要容納的值是通用的?這意味着如果您將泛型數據結構稱爲typedef而不是void *,這並不意味着它不是通用的。

我在問這個,因爲我即將創建一個使用鏈接列表實現的通用堆棧,我有點困惑。

這是我的通用鏈表數據結構:

typedef struct Element { 
    struct Element *next; 
    void *value; 
} TElement, *TList, **AList; 

而對於堆棧:

typedef struct Stack { 
    size_t size; 
    TList top; 
} TStack, *AStack; 

/* Function Definitions */ 
TStack InitStack(size_t); 
void DeleteStack(AStack); 
int Push(TStack, void*); 
int Pop(TStack, void*); 
int Top(TStack, void*); 

做任何事情似乎不是通用在我的執行?

+0

您將要'Pop'和'Top'採取'void **',因此您可以爲調用者提供指向數據的指針。由於您不知道數據有多大,因此您不能對提供的指針執行「memcpy」操作。 –

+1

必須抵制...抱怨...關於宏觀濫用。嗯 – this

+1

我完全讓你在那裏。我有同樣的感覺。我複製粘貼從課程支持。 –

回答

1

通用意味着它可以保存任何數據類型(char*,int*等)或包含任何數據類型。空指針void *C讓你投項目本身並獲得這些項目了(需要重新扮演他們的檢索。

因此,它允許程序,不懂你在你的自定義有數據類型數據結構

參考結構本身(只要你沒有指定在所述結構中保存的數據),不會破壞泛型,因此,只要在函數中使用TStack在該棧內操作的數據是一般的(id estvoid *)。

0

void*用於通用目的。把它想象成一個指向內存的指針,當然內存可以容納任何東西。通過void*你的意思是你不知道你指的是什麼,但是你知道你指向某個東西。

+0

是的,我知道。但是爲什麼我需要將我的棧作爲'void *'來引用呢?只有當我不知道我想要保存在我的棧中的數據是什麼類型的時候,因此我將這些數據稱爲void。 –

+0

如果不是'void *',那麼是什麼?哦,但是等等,你的函數(pop等)實際上會處理你在棧中存儲的數據。 – gsamaras

+0

將棧本身稱爲'TStack',它存儲通用的'void *'值。 –

0

是的一個void*可以正確實現一個通用堆棧,但是這會產生一個問題,即您不知道要存儲在堆棧中的數據的類型。 void*的概念是它指向一些有效的內存塊,但是對內存的類型完全沒有線索。因此,使用這個通用堆棧的代碼必須明確地進行類型轉換。 void*僅用於存儲數據,不允許使用它們進行操作。

+0

你有這個問題都是錯誤的。 –