回 帖 发 新 帖 刷新版面

主题:如果在一个程序中用到不同数据类型的栈,该怎么解决

最近学习当中,有个问题搞不懂,求大神指点。建了个栈,为了重复使用,将数据类型重定义为为typedef char A        但问题来了,程序中要是栈的数据类型为double,这该怎么办,应该不能typedef double A吧,请问有没有取消类型重定义的方法,类型重定义的作用范围是什么,我想过用文件包含来解决,不知道行不行,求大神帮个忙啊,急用,谢谢

回复列表 (共11个回复)

11 楼

[quote]1、用文件包含的办法,可以解决。
2、如果是C++,建议用模板来做。(C++自己也提供了stack的模板)
模板不用说,C++的教材一般都写得很清楚。下面详细说说文件包含的具体做法。

其实文件包含的做法与C++的模板,在思路上很类似。
先写一个头文件,叫做stack_template.h,内容如下:

[quote]#ifndef STACK_ELEMENT_TYPE
#error "使用本文件前,必须先定义STACK_ELEMENT_TYPE"
#endif

#ifndef STACK_TYPE
#error "使用本文件前,必须先定义STACK_TYPE"
#endif

#include <stdlib.h>

typedef struct
{
    STACK_ELEMENT_TYPE* elements;
    int top;
    int max;
} STACK_TYPE;

/* 注意:
 * 1. 每个操作的宏,都要用#ifndef扩起,否则如果多次使用这个文件,编译器就会报告告警甚至错误
 * 2. C语言的malloc返回值是void*,可以直接赋值给(stack)->elements。但是C++不行,因为C++的类型检查更加严格。
 *    C++可以在STACK_INIT这个宏里面再加入一个参数来表示类型,但是不推荐。C++推荐直接用模板。
 **/
#ifndef STACK_INIT
#define STACK_INIT(stack, maxSize) \
    ((stack).elements = malloc(maxSize * sizeof(((stack).elements)[0])), (stack).top = 0, (stack).max = maxSize)
#endif

#ifndef STACK_DESTROY
#define STACK_DESTROY(stack) \
    (free((stack).elements), (stack).elements = NULL, (stack).top = 0, (stack).max = 0)
#endif

#ifndef STACK_PUSH
#define STACK_PUSH(stack, value) \
    (((stack).elements)[(stack).top++] = (value))
#endif

#ifndef STACK_POP
#define STACK_POP(stack, value) \
    ((value) = ((stack).elements)[--(stack).top])
#endif[/quote]
注意:不要使用常见的#ifndef来防止重复include,因为这个文件本身就应该可以被反复的include

使用示例:
[quote]#define STACK_ELEMENT_TYPE  char
#define STACK_TYPE          CharStack
#include "stack_template.h"
#undef STACK_ELEMENT_TYPE
#undef STACK_TYPE

#define STACK_ELEMENT_TYPE  double
#define STACK_TYPE          DoubleStack
#include "stack_template.h"
#undef STACK_ELEMENT_TYPE
#undef STACK_TYPE

#include <stdio.h>

int main()
{
    CharStack cs;
    DoubleStack ds;
    int i;

    STACK_INIT(cs, 10);
    if (cs.elements == NULL)
    {
        return -1;
    }

    for (i = 0; i < 10; ++i)
    {
        STACK_PUSH(cs, (char)(i * 10));
    }

    for (i = 0; i < 10; ++i)
    {
        char c;
        STACK_POP(cs, c);
        printf("%d\n", c);
    }

    STACK_DESTROY(cs);

    STACK_INIT(ds, 10);
    if (ds.elements == NULL)
    {
        return -1;
    }

    for (i = 0; i < 10; ++i)
    {
        STACK_PUSH(ds, (double)(i * 10));
    }

    for (i = 0; i < 10; ++i)
    {
        double d;
        STACK_POP(ds, d);
        printf("%f\n", d);
    }

    STACK_DESTROY(ds);

    return 0;
}[/quote]

附加说明:
因为这里的"stack_template.h"没有防止重复include的功能,如果是在大型工程中使用,多有不便。为此可以继续封装。例如,建立一个头文件叫做"stack_of_char.h",内容如下:
[quote]#ifndef STACK_OF_CHAR_H_INCLUDED
#define STACK_OF_CHAR_H_INCLUDED

#define STACK_ELEMENT_TYPE  char
#define STACK_TYPE          CharStack
#include "stack_template.h"
#undef STACK_ELEMENT_TYPE
#undef STACK_TYPE

#endif[/quote]

这样以后就使用"stack_of_char.h",而不直接使用"stack_template.h",就不必担心重复include而导致的编译错误了。
当然也可以不用"stack_of_char.h",这样需要每次使用"stack_template.h"时都用#ifdef扩起。效果是一样的,也比较麻烦,但好处是文件的数目会减少。这个可以自行取舍。[/quote]
感谢cowboy,学习到了。。

我来回复

您尚未登录,请登录后再回复。点此登录或注册