2012-09-07 1 views
1

다른 형식의 항목을 지원하는 배열을 사용하여 스택을 구현하는 방법. 예 : 문자, 정수, 수레 및 복식에서 작동해야합니다.배열을 사용하여 다른 데이터 형식의 항목을 지원하는 스택 구현

void 포인터를 사용하여 구현했습니다. 나를 위해

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
그것은 당신이

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

그런 다음 당신은 GObject 모델을 살펴 수

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

구조에 모든 것을 넣어 포함 된 유형을 설명 열거 필요 C. 먼저 수행 할 수 있습니다

GLib에서 그 용도는 일반 유형을 혼합 할 수있는 목록을 작성하는 것이 흥미 롭습니다.

+0

이 방법이 널리 사용됩니다. 노동 조합의 모든 구성원은 단체/부문을 가질 수 없다는 제한이 있지만. 또한 지원되는 유형의 전체 목록을 미리 알려야합니다. –

+0

@KirillKobelev c-tors와 d-tors 인 경우, 이것은 C++이므로 표준은 C++ 11이며, 조합원은 c-tors, d-tors를 가질 수 있습니다. – ForEveR

+0

@KirillKobelev 이런 종류의 접근법은 가능하지만 GObject 모델에는 이러한 제한이 없지만 간단한 스택 구현을 위해서는 약간 과잉입니다. – Kwariz