主题:如果在一个程序中用到不同数据类型的栈,该怎么解决
卡卡罗特as
[专家分:0] 发布于 2012-04-17 22:03:00
最近学习当中,有个问题搞不懂,求大神指点。建了个栈,为了重复使用,将数据类型重定义为为typedef char A 但问题来了,程序中要是栈的数据类型为double,这该怎么办,应该不能typedef double A吧,请问有没有取消类型重定义的方法,类型重定义的作用范围是什么,我想过用文件包含来解决,不知道行不行,求大神帮个忙啊,急用,谢谢
最后更新于:2012-04-18 15:57:00
回复列表 (共11个回复)
11 楼
fragileeye [专家分:1990] 发布于 2012-04-22 23:11:00
[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,学习到了。。
我来回复