【问题标题】:Can I push string and int values onto a stack?我可以将字符串和 int 值推入堆栈吗?
【发布时间】:2012-10-15 03:05:47
【问题描述】:

我需要我的堆栈来接收 int 和 char 数组(字符串)。有什么想法吗?我知道目前我有使用整数操作的 pop 和 push 命令。不同类型的结构会更好吗?我似乎记得某些结构能够接受不同的论点。如果我定义不同的函数来处理 char 数组会有帮助吗?我知道你不能在 c 中超载。我的另一个想法是让堆栈接收字符串并根据需要在字符串和 int 之间进行转换,但这似乎有点冒险在两种变量类型之间进行常量切换。

typedef struct Stack
{
int capacity;       // max # of elements the stack can hold
int size;           // current size of the stack
int *elements;      // the array of elements
}Stack;

Stack * createStack(int maxElements)
{        

Stack *S;        
S = (Stack *)malloc(sizeof(Stack));     
S->elements = (int *)malloc(sizeof(int)*maxElements);        
S->size = 0;        
S->capacity = maxElements;      
return S;
}


// STACK COMMANDS


void pop(Stack *S)
{               
if(S->size==0)        
{                
    printf("Stack is Empty\n");                
return;        
}        

else        
{                
    S->size--;        
}        

return;
}

int top(Stack *S)
{        
if(S->size==0)        
{                
    printf("Stack is Empty\n");               
    exit(0);        
}               
return S->elements[S->size-1];
}

void push(Stack *S,int element)
{                
if(S->size == S->capacity)        
{                
    printf("Stack is Full\n");        
}        
else        
{                               
    S->elements[S->size++] = element;        
}        
return;
}

【问题讨论】:

    标签: c string stack int


    【解决方案1】:

    你可以创建一个联合类型:

    union mType
    {
        int integer;
        char *string;
    };
    

    然后你可以让 mType 成为你的元素类型。

    编辑:

    联合在某种意义上类似于结构,因为它们具有可由 .和 -> 运算符。但是每个成员的内存是重叠的。

    【讨论】:

    • 您可能希望将其放在struct 中,并带有一个标签,用于标识该值是int 还是char*
    • 嗯...所以“联合”将充当可互换的变量类型?并且标题是 mType top(Stack *S) 和 push(Stack *S, mType elememt)? (只是确认,因为我从未与工会合作过
    • @user1770173 部分正确。正如 Jonathon 提到的,您需要知道 mType 是否包含 intchar*。理想的数据结构应该是:typedef enum type { INT, STRING } type; typedef struct mContainer { type thisType; union mType { int integer, char* string; }; } mContainer;
    • @user1770173,是的,您可以考虑在另一个结构中使用联合变量来识别类型是 int 还是 char,就像 Jonathon Reinhart 说的那样。
    【解决方案2】:

    您可以根据需要使用联合。实际上,您所追求的是 variant 数据类型。所以我就叫它Variant

    typedef enum VariantType {
        v_int,
        v_string
    } EVariantType;
    
    typedef struct Variant
    {
        EVariantType type;
        union {
            int m_int;
            char * m_string;
        };
    } SVariant;
    

    凭记忆,我很确定这个匿名工会没问题。这意味着您可以存储整数:

    SVariant v;
    v.type = v_int;
    v.m_int = 42;
    

    和字符串:

    SVariant v;
    v.type = v_string;
    v.m_string = strdup( "Hello, World!" );
    

    我在这里使用枚举是为了通用性,因为您以后可以轻松地扩展到其他类型(而不是使用一个标志来指示它是 int 还是不是 int)。

    当你来使用数据时,当然可以在switch语句中处理:

    switch( v.type )
    {
        case v_int:  printf( "Integer value: %d\n", v.m_int ); break;
        case v_string: printf( "String value: %s\n", v.m_string ); break;
    }
    

    您的堆栈现在声明为:

    typedef struct Stack
    {
        int capacity;       // max # of elements the stack can hold
        int size;           // current size of the stack
        SVariant *elements; // the array of elements
    }Stack;
    

    希望对您有所帮助。

    【讨论】:

    • 在这种情况下,无论在何处使用元素,SVariant 都是变量类型。 (如果我错了,请告诉我。)在这种情况下,在我调用堆栈元素的代码中的任何地方,我都需要使用 switch 语句来处理它,一个用于在实例中处理元素是 int 并且一个用于当它是一个字符串(字符数组)时处理
    • 嗯,是的。这实际上是一种多态性。 C 编译器在编译时不知道您的数据类型是什么,因此您需要在运行时处理它。您真的不需要开关。例如,您可能只关心它是否是整数。在这种情况下,您只需使用 if... 检查整数,但您确实需要一种方法来清理您的变体。如果你弹出它并且它包含一个字符串,你将不得不在你处理元素之前释放那个字符串。我建议一个简单的函数delete_variant 或其他东西,它检查它是否是一个字符串并释放指针。
    • 请注意我之前的评论。您可能不需要释放字符串...可能是您正在存储来自字符串表的静态字符串、在其他地方共享或管理的字符串、指向较大字符串中的标记的指针,或者甚至使用 char 数组声明您的变体指针(通常不推荐,因为它会使复制结构变慢)。您可以根据自己的需要进行调整。
    猜你喜欢
    • 2011-04-22
    • 1970-01-01
    • 2018-12-30
    • 2021-12-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多