随笔
C++博客
首页
新随笔
联系
聚合
管理
posts - 6, comments - 30, trackbacks - 0
关于Visual C++2010编译器的问题
今天使用
visual
C++ 2010
编译
器编写
程序
逆波兰表达式求值
但是遭遇了以前从未看到的问题,在此
求助
各位,谢谢
头
文件
Stack.h
1
template
<
class
T
>
2
class
Stack
3
{
4
public
:
5
Stack(
int
size
=
0
);
//
构造大小为size的堆栈
6
~
Stack()
{delete p;}
//
撤销堆栈
7
bool
IsFull();
//
判断堆栈是否已满
8
bool
IsEmpty();
//
判断堆栈是否为空
9
void
Push(T
&
x);
//
将x压入堆栈
10
T Pop(T
&
x);
//
将栈顶元素弹出用x保存
11
private
:
12
int
Size;
//
大小
13
int
top;
//
栈顶
14
T
*
p;
//
数组指针
15
}
;
实现源文件Stack.cpp
1
#include
"
Stack.h
"
2
3
template
<
class
T
>
4
void
Stack
<
T
>
::Push(T
&
x)
5
{
6
p[top
++
]
=
x;
//
将x保存于栈顶,栈顶+1
7
}
8
9
template
<
class
T
>
10
T Stack
<
T
>
::Pop(T
&
x)
11
{
12
x
=
p[
--
top];
//
x保存栈顶元素,栈顶-1
13
return
x;
14
}
15
16
template
<
class
T
>
17
Stack
<
T
>
::Stack(
int
size)
18
{
19
Size
=
size;
//
栈大小为size
20
top
=
0
;
//
栈顶top指向0
21
p
=
new
T[Size];
//
为p开辟Size大小的空间
22
}
23
24
template
<
class
T
>
25
bool
Stack
<
T
>
::IsFull()
26
{
27
return
top
==
Size;
28
}
//
判断堆栈是否已满
29
30
template
<
class
T
>
31
bool
Stack
<
T
>
::IsEmpty()
32
{
33
return
top
==
0
;
34
}
//
判断堆栈是否为空
main.cpp
1
#include
<
iostream
>
2
#include
<
stdio.h
>
3
#include
"
Stack.h
"
4
const
int
MaxSize
=
40
;
//
由于定义数组时开辟空间大小
5
using
namespace
std;
6
7
/**/
/*
8
*逆波兰表达式求值函数
9
*/
10
float
LiBolan(
char
*
array)
{
//
array存储表达式
11
Stack
<
float
>
sta(MaxSize);
//
建立大小为Maxsize的堆栈
12
int
i
=
0
;
13
if
(array[
0
]
==
'
.
'
)
{
14
cout
<<
"
表达式错误:小数表示错误
"
<<
endl;
15
return
0
;
16
}
17
while
(array[i]
!=
'
\0
'
)
{
//
当表达式没有结束
18
if
(array[i]
==
'
.
'
)
{
//
数字第一个字符为小数点或运算符后是小数点
19
cout
<<
"
表达式错误:小数表示错误
"
<<
endl;
20
return
0
;
21
}
22
if
(i
==
0
&&
array[i]
==
'
-
'
)
{
//
判断第一个是否负数,后面的没有必要判断,如果是
23
i
++
;
//
处理下一个字符
24
float
tem
=
0
;
25
while
(array[i]
>=
'
0
'
&&
array[i]
<=
'
9
'
)
{
26
tem
=
(
float
)array[i]
-
48
+
tem
*
10
;
//
先计算该负数的绝对值
27
i
++
;
28
}
29
if
(array[i]
==
'
.
'
)
{
//
若存在小数
30
i
++
;
//
忽略该位
31
if
(
!
(array[i]
>=
'
0
'
&&
array[i]
<=
'
9
'
))
{
//
小数点后不是数字
32
cout
<<
"
表达式错误:小数表示错误
"
<<
endl;
33
return
0
;
34
}
35
}
36
Stack
<
char
>
s(
7
);
//
用于存储小数字符
37
while
(array[i]
>=
'
0
'
&&
array[i]
<=
'
9
'
)
{
38
s.Push(array[i]);
39
i
++
;
40
}
41
float
item
=
0
;
42
char
x;
43
while
(
!
s.IsEmpty())
44
item
=
((
float
)s.Pop(x)
-
48
)
*
0.1
+
item
*
0.1
;
//
计算小数
45
tem
+=
item;
46
tem
=-
tem;
//
取相反数得到原数
47
sta.Push(tem);
//
将该数压入栈中
48
}
49
if
(array[i]
>=
'
0
'
&&
array[i]
<=
'
9
'
)
{
//
其他时候,判断是否为数字
50
float
tem
=
0
;
51
while
(array[i]
>=
'
0
'
&&
array[i]
<=
'
9
'
)
{
//
计算整数部分
52
tem
=
(
float
)array[i]
-
48
+
tem
*
10
;
53
i
++
;
54
}
55
if
(array[i]
==
'
.
'
)
{
//
若存在小数
56
i
++
;
//
忽略该位
57
if
(
!
(array[i]
>=
'
0
'
&&
array[i]
<=
'
9
'
))
{
//
小数点后不是数字
58
cout
<<
"
表达式错误:小数表示错误
"
<<
endl;
59
return
0
;
60
}
61
}
62
Stack
<
char
>
s(
7
);
//
用于存储小数字符
63
while
(array[i]
>=
'
0
'
&&
array[i]
<=
'
9
'
)
{
64
s.Push(array[i]);
65
i
++
;
66
}
67
float
item
=
0
;
68
char
x;
69
while
(
!
s.IsEmpty())
70
item
=
((
float
)s.Pop(x)
-
48
)
*
0.1
+
item
*
0.1
;
//
计算小数
71
tem
+=
item;
72
sta.Push(tem);
73
}
74
if
(array[i]
==
'
+
'
||
array[i]
==
'
-
'
||
array[i]
==
'
*
'
||
array[i]
==
'
/
'
)
{
75
float
it1,it21,it22;
//
it21栈顶元素,it22倒数第二个,it1是it21,it22对应运算的值
76
char
ch
=
array[i];
77
switch
(ch)
{
78
case
'
+
'
:it21
=
sta.Pop(it21);
79
if
(sta.IsEmpty())
{
80
cout
<<
"
表达是错误:运算符比对应所需的运算数多
"
<<
endl;
//
弹出一个运算数后为空
81
return
0
;
82
}
83
it22
=
sta.Pop(it22);
84
it1
=
it21
+
it22;
85
sta.Push(it1);
break
;
86
case
'
-
'
:it21
=
sta.Pop(it21);
87
if
(sta.IsEmpty())
{
88
cout
<<
"
表达式错误:运算符比对应所需的运算数多
"
<<
endl;
89
return
0
;
90
}
91
it22
=
sta.Pop(it22);
92
it1
=
it22
-
it21;
93
sta.Push(it1);
break
;
94
case
'
*
'
:it21
=
sta.Pop(it21);
95
if
(sta.IsEmpty())
{
96
cout
<<
"
表达式错误:运算符比对应所需的运算数多
"
<<
endl;
97
return
0
;
98
}
99
it22
=
sta.Pop(it22);
100
it1
=
it21
*
it22;
101
sta.Push(it1);
break
;
102
case
'
/
'
:it21
=
sta.Pop(it21);
103
if
(sta.IsEmpty())
{
104
cout
<<
"
表达式错误:运算符比对应所需的运算数多
"
<<
endl;
105
return
0
;
106
}
107
it22
=
sta.Pop(it22);
108
it1
=
it22
/
it21;
109
sta.Push(it1);
break
;
110
default
:
break
;
111
}
112
i
++
;
113
}
114
else
115
i
++
;
116
}
117
float
value;
118
sta.Pop(value);
119
if
(
!
sta.IsEmpty())
{
120
cout
<<
"
表达式错误:运算数多于所需的运算符
"
<<
endl;
//
最后栈不为空
121
return
0
;
122
}
123
return
value;
124
}
125
void
main()
{
126
printf(
"
请输入一个后缀表达式:
"
);
127
char
str[MaxSize];
128
gets(str);
129
float
value
=
LiBolan(str);
130
printf(
"
%2.2f\n
"
,value);
131
}
当用Visual C++ 6.0编译时正确,用visualC++201编译时,如果不分头文件源文件,即直接把这三个文件放在man.cpp中编译正确,当时当把他们分开后
其文件结构图如下时编译通不过
其问题描述如下
1>t.obj : error LNK2019: 无法解析的外部符号 "public: bool __thiscall Stack<float>::IsEmpty(void)" (
?IsEmpty@?$Stack@M@@QAE_NXZ
),该符号在函数 "float __cdecl LiBolan(char *)" (
?LiBolan@@YAMPAD@Z
) 中被引用
1>t.obj : error LNK2019: 无法解析的外部符号 "public: float __thiscall Stack<float>::Pop(float &)" (
?Pop@?$Stack@M@@QAEMAAM@Z
),该符号在函数 "float __cdecl LiBolan(char *)" (
?LiBolan@@YAMPAD@Z
) 中被引用
1>t.obj : error LNK2019: 无法解析的外部符号 "public: void __thiscall Stack<float>::Push(float &)" (
?Push@?$Stack@M@@QAEXAAM@Z
),该符号在函数 "float __cdecl LiBolan(char *)" (
?LiBolan@@YAMPAD@Z
) 中被引用
1>t.obj : error LNK2019: 无法解析的外部符号 "public: char __thiscall Stack<char>::Pop(char &)" (
?Pop@?$Stack@D@@QAEDAAD@Z
),该符号在函数 "float __cdecl LiBolan(char *)" (
?LiBolan@@YAMPAD@Z
) 中被引用
1>t.obj : error LNK2019: 无法解析的外部符号 "public: bool __thiscall Stack<char>::IsEmpty(void)" (
?IsEmpty@?$Stack@D@@QAE_NXZ
),该符号在函数 "float __cdecl LiBolan(char *)" (
?LiBolan@@YAMPAD@Z
) 中被引用
1>t.obj : error LNK2019: 无法解析的外部符号 "public: void __thiscall Stack<char>::Push(char &)" (
?Push@?$Stack@D@@QAEXAAD@Z
),该符号在函数 "float __cdecl LiBolan(char *)" (
?LiBolan@@YAMPAD@Z
) 中被引用
1>t.obj : error LNK2019: 无法解析的外部符号 "public: __thiscall Stack<char>::Stack<char>(int)" (
??0?$Stack@D@@QAE@H@Z
),该符号在函数 "float __cdecl LiBolan(char *)" (
?LiBolan@@YAMPAD@Z
) 中被引用
1>t.obj : error LNK2019: 无法解析的外部符号 "public: __thiscall Stack<float>::Stack<float>(int)" (
??0?$Stack@M@@QAE@H@Z
),该符号在函数 "float __cdecl LiBolan(char *)" (
?LiBolan@@YAMPAD@Z
) 中被引用
1>E:\Visual2010\t\Debug\t.exe : fatal error LNK1120: 8 个无法解析的外部命令
1>
1>生成失败。
1>
1>已用时间 00:00:00.79
========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========
posted on 2011-01-19 14:22
あ维wêiセ
阅读(2734)
评论(12)
编辑
收藏
引用
所属分类:
C++
FeedBack:
#
re: 关于Visual C++2010编译器的问题
2011-01-19 14:42 |
coolypf
Stack.cpp的内容全部放到Stack.h里面。
回复
更多评论
#
re: 关于Visual C++2010编译器的问题
2011-01-19 14:45 |
あ维wêiセ
@coolypf
但是按照程序编写习惯,不是应该把他们分开吗?
回复
更多评论
#
re: 关于Visual C++2010编译器的问题
2011-01-19 14:49 |
ChowZenki
如果不想写在hpp中你可以去掉template
回复
更多评论
#
re: 关于Visual C++2010编译器的问题
2011-01-19 14:54 |
あ维wêiセ
去掉template后那个T就是一个未知符号了@ChowZenki
回复
更多评论
#
re: 关于Visual C++2010编译器的问题
2011-01-19 14:59 |
ChowZenki
@あ维wêiセ
实现写在hpp中是template的使用约定...
具体去看看stl相关的书吧
如果要用就必须这么做
否则你只能改写成非模板的类了
回复
更多评论
#
re: 关于Visual C++2010编译器的问题
2011-01-19 15:06 |
あ维wêiセ
@ChowZenki
额,是不是用了template就必须把.cpp与.h文件写在一起呀?
谢谢你为我解决
回复
更多评论
#
re: 关于Visual C++2010编译器的问题[未登录]
2011-01-19 20:12 |
codejie
建议不要C和C++混用。。。下面这个风格非常不好。。
1#include<iostream>
2#include<stdio.h>
回复
更多评论
#
re: 关于Visual C++2010编译器的问题
2011-01-19 20:14 |
あ维wêiセ
@codejie
关键是要用的gets()函数
用while(...)
{
.....
}老是不能结束
回复
更多评论
#
re: 关于Visual C++2010编译器的问题
2011-01-19 22:51 |
jmchxy
template的参数需要在使用时候特化,你不放到包含文件中,调用的文件不知道怎么特化。
template函数或类是在被调用到的时候才生成真正的函数体或类,如果调用者看不到模板的实现就不能生成真正的函数体或类
回复
更多评论
#
re: 关于Visual C++2010编译器的问题
2011-01-23 08:28 |
coderman
对于模板,编译时和普通代码的编译是有区别的,普通代码在编译时只需要知道函数定义即可编译通过,但模板不一样,模板编译有两个阶段:
1、先编译类模板本身,看是否有语法错误,例如是不是少写了分号
2、当模板实例化时再进行一次编译,即编译实例化的后的代码,检查你指定的类型能不能在模板里被支持,这时编译器需要清楚的知道模板的具体实现,所以常规的做法是将声明和实现都放在一个.h文件里
你可以看一下开源的代码(例如 boost库的 asio),里面的模板都放.h文件里
感觉楼主的代码在安全上有点问题,作为一个stack,对它的调用者来说应该是安全的,你的代码里应该检查下标是否越界,指针是否为空,删除指针时应该判空并置NULL
回复
更多评论
#
re: 关于Visual C++2010编译器的问题
2011-01-28 12:37 |
summerheart
vc6.共认的对标准C++支持不够好,大概也就60%上下吧。
而Vc2010对标准C++的支持更完全。这也是新版本的亮点之一。
所以 楼主还是按标准的C++模板编写方法写吧。
回复
更多评论
#
re: 关于Visual C++2010编译器的问题
2011-02-27 21:28 |
marmot
楼上说的比较对,写模板最好用包含模型
用分离模型编译容易出问题
Boost中很多子库都采用的是包含模型
回复
更多评论
刷新评论列表
只有注册用户
登录
后才能发表评论。
【推荐】100%开源!大型工业跨平台软件C++源码提供,建模,组态!
相关文章:
关于除以2的n次方求余数的思考
中缀表达式转为后缀表达式
关于Visual C++2010编译器的问题
有关二叉查找树的一些功能(BST)
链表实验
网站导航:
博客园
IT新闻
BlogJava
博问
Chat2DB
管理
<
2011年1月
>
日
一
二
三
四
五
六
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
常用链接
我的随笔
我的评论
我参与的随笔
留言簿
(1)
给我留言
查看公开留言
查看私人留言
随笔分类
C++(5)
Java(1)
随笔档案
2011年2月 (1)
2011年1月 (5)
文章分类
个人总结(1)
文章档案
2011年1月 (1)
搜索
最新评论
1. re: 中缀表达式转为后缀表达式
你可以考虑先将表达式中的数字字符转换成对应的数字,成为一个元素,那么打印时加空格就好@js
--yangwei
2. re: 中缀表达式转为后缀表达式
是的,要牺牲一个来区分队空和队满@jhayumu
--yangwei
3. re: 中缀表达式转为后缀表达式
(8+9*10)-4/2+3
与
(8+91*0)-4/2+3
怎么区分?
--js
4. re: 关于除以2的n次方求余数的思考[未登录]
好像法
--zhang
5. re: 关于Visual C++2010编译器的问题
楼上说的比较对,写模板最好用包含模型
用分离模型编译容易出问题
Boost中很多子库都采用的是包含模型
--marmot
阅读排行榜
1. 中缀表达式转为后缀表达式(6016)
2. 关于除以2的n次方求余数的思考(3918)
3. 关于Visual C++2010编译器的问题(2734)
4. 链表实验(1939)
5. 有关二叉查找树的一些功能(BST)(1908)
评论排行榜
1. 关于Visual C++2010编译器的问题(12)
2. 中缀表达式转为后缀表达式(5)
3. 链表实验(5)
4. 关于除以2的n次方求余数的思考(5)
5. 初学java(一)(3)