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

GLibでのGObjectモデルとその使用法を見ることができます。タイプを混在させることができる汎用リストの実装は興味深いものです。

于 2012-09-07T19:23:49.580 に答える
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;
}
于 2012-09-07T21:44:20.623 に答える