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;
}

该代码对我来说很好

上述实现的问题是必须事先知道数据的类型。

是否存在一种在不知道要操作的数据类型的先验信息的情况下实现它的方法[我知道这在 C 中是不可能的,我们可以在 C++ 中做到这一点,如果是,如何?]?

4

2 回答 2

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中的用途,可以混合类型的通用列表的实现很有趣。

于 2012-09-07T19:23:49.580 回答
0

如果我了解您的要求,您可以使用boost::anyC++ 来实现此目的。

#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;
}
于 2012-09-07T21:44:20.623 回答