2012-09-07 69 views
1

如何使用支持不同類型項目的數組實現堆棧。 例如它應該在字符,整數,浮動和雙打上運行。使用數組實現堆棧以支持不同數據類型的項目

我已經使用void指針實現了它。下面是C實現:

void push(void** stack, int* top, void* data, size_t size) 
{ 
    unsigned i; 
    ++*top; 

    stack[*top] = malloc(size); 

    for(i = 0; i < size; ++i) 
      ((char*)stack[*top])[i] = ((char*)data)[i]; 

} 

int main() 
{ 
    void* stack[10]; 
    int top = -1, data = 10; 
    char ch = 'a'; 

    push(stack, &top, (void*)&data, sizeof(int)); 

    push(stack, &top, (void*)&ch, sizeof(char));   

    printf("%d ", *(int*)stack[0]); 
    printf("%c ", *(char*)stack[1]); 

    return 0; 
} 

我的代碼works fine

上述實現的問題是必須事先知道數據的類型。

是否存在一種方法來實現它,而不知道有關要操作的數據類型的先前信息[我知道這在C中是不可能的,我們可以用C++來做,如果是,如何? ]?

+1

[RTTI](http://en.wikipedia.org/wiki/Run-time_type_information)...雖然在C++中通常容器是使用類型參數的模板。請注意['std :: stack'](http://en.cppreference.com/w/cpp/container/stack)。 – oldrinb

+0

是的,容器是模板。但是AFAIK,他們一次只支持一種類型。 –

+0

這是C或C++嗎?因爲每種語言的解決方案都不相同。 –

回答

0

如果我瞭解您的要求,您可以使用boost::any在C++中實現此目的。

#include <boost/any.hpp> 
#include <vector> 

class AnyStack { 
    std::vector<boost::any> vec; 
public: 
    template <class T> void push (const T &e) { 
     boost::any v = e; 
     vec.push_back(v); 
    } 
    class Proxy { 
     friend class AnyStack; 
     std::vector<boost::any> &vec; 
     Proxy(std::vector<boost::any> &v) : vec(v) {} 
    public: 
     template <typename T> operator T() { 
      boost::any v = vec.back(); 
      vec.pop_back(); 
      return boost::any_cast<T>(v); 
     } 
    }; 
    Proxy pop() { return Proxy(vec); } 
    boost::any top() { return vec.back(); } 
}; 

正如其他人所建議的,您可以使用RTTI來確定堆棧中物品的類型。下面的示例演示了執行此操作的輸出例程。

#include <iostream> 
#include <string> 

std::ostream & operator << (std::ostream &os, const boost::any &a) { 
    if (a.type() == typeid(char)) { 
     return os << boost::any_cast<char>(a); 
    } 
    if (a.type() == typeid(int)) { 
     return os << boost::any_cast<int>(a); 
    } 
    if (a.type() == typeid(float)) { 
     return os << boost::any_cast<float>(a); 
    } 
    if (a.type() == typeid(double)) { 
     return os << boost::any_cast<double>(a); 
    } 
    if (a.type() == typeid(std::string)) { 
     return os << boost::any_cast<std::string>(a); 
    } 
} 

int main() { 
    AnyStack a; 
    a.push(3); 
    std::cout << a.top() << std::endl; 
    a.push(std::string("hello")); 
    std::cout << a.top() << std::endl; 
    return 0; 
} 
3

它可以在C.首先要做你需要描述所含類型的枚舉

typedef enum {TYPE_INT, TYPE_CHAR, TYPE_STRING, ... } contained_type_t; 

然後把一切都放在一個結構

typedef struct { 
    contained_type_t contained_type; 
    union { 
    int int_value; 
    char char_value; 
    void* pointer_value; 
    ... and so on ... 
    } data; 
}; 

你可以看看在GObject模型和其用途爲GLib,執行通用列表可混合類型很有意思。

+0

這種方法被廣泛使用。雖然它有一個限制,即工會的所有成員都不能擁有委託人/代理人。另外,應該提前知道支持類型的完整列表。 –

+0

@KirillKobelev如果c-tors和d-tors,這是C++,所以現在的標準是C++ 11,其中union的成員可以有c-tors,d-tors。 – ForEveR

+0

@KirillKobelev有這種方法,但是GObject模型沒有這個限制,但是對於一個簡單的棧實現來說有點矯枉過正 – Kwariz