关于栈设计实现的疑问

zhshto886 2009-10-29 04:39:52
我在实现栈的时候,怎样设计实现栈边界处理的问题上有些疑惑。
我就拿栈设计中的pop函数为例,来说明我的疑惑,希望大牛们帮我解惑。
我接触的教课书上的栈pop函数都是如下的实现:


struct node {
int capacity;
int top; /* 栈顶 */
int *array; /* 指向存储栈元素的数组 */
};


int
pop(struct node *S)
{
if (is_empty(S) == 1) { //表示栈空
//error
} else {
return S->array[S->top--];
}
}

上面pop函数中,对栈空的这种状态做了判断,如果栈为空,怎提示错误:
提示错误的方式:
1 输出一条错误信息,然后终结程序
fprintf(.....);
exit(-1);

2 返回一个错误的标志值
return ERROR_NUM;


我的疑惑:
如果采用第一种提示错误的方式,程序直接退出!is_empty()最为一个接口提供给用户。
很多的教科书上又这样使用pop函数

if (is_empty(S) == 0) {
i = pop(S);
}

因为我们要写健壮的程序,不可能让我们的程序在一个小错误就终止阿,但是这里pop函数内的if (is_empty(S) == 1) 判断是不是就没有用处了?使用assert是不是更合适
int
pop(struct node *S)
{
assert(S != NULL);
assert(is_empty(S) == 0);

return S->array[S->top--];
}


何时用assert、何时用if语句对输入的参数进行判断?
我在做栈的练习时,很多的地方不知道该怎么写,很多的判断是留给模块开发者,还是使用者?比如这里的栈空、栈满的处理。



如果采用第二种方法,那么ERROR_NUM的值怎么确定,怎么不和合法的程序冲突,这时is_empty()就作为一个内部函数,而不是一个外部接口了。

if ((i = pop(S)) != ERROR_NUM) {
//正确取值
} else {
//错误处理
}


疑问:
那在这里ERROR_NUM的值怎么确定,怎么不和合法的程序冲突?
我没有写过很大的程序,大牛们大程序的栈满、栈空时的错误处理怎么写?建立新栈。。




我学习的是C语言,没有栈模型,我看了STL中的栈的实现,他在STL中做了栈空栈满的判断和处理,但是没有看太懂,大家遇到栈问题时都是怎样处理的?







...全文
147 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
cphj 2009-10-30
  • 打赏
  • 举报
回复
契约式编程,几年前看的,也没有详细研究,印象不深了,似乎是一本讲Eiffel的书

简单说一下我的理解,契约式编程是一种编程方法论,有时候我们需要反思一下:
那么不顾一切的防御错误值得吗?有效吗?
既然“提前优化”、“过度优化”不好,那么“提前防御”、“过度防御”是不是也需要适可而止?
zhshto886 2009-10-30
  • 打赏
  • 举报
回复
顶上去,吃饭去!
zhshto886 2009-10-30
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 cphj 的回复:]
另外建议你看看“基于契约的编程”

再一个,C/C++的思想是“不为可能不使用的东西付出开销”,还有“相信程序员”,所以不建议你在pop()里面做empty检测

如果倾向于预防错误,那么推荐用Java或者C#,它们都会对pop() empty的stack的动作抛出异常
[/Quote]
@cphj
在网上搜了搜契约编程的概念,感觉很不错,不过很零散,没有找到相关的书籍,你那有详细些的资料吗?
有的话麻烦给我发一份:zhshto886@gmail.com
Caballeroo 2009-10-30
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 onebleach 的回复:]
学习了!
[/Quote]



顶!
OneBleach 2009-10-30
  • 打赏
  • 举报
回复
学习了!
j260749883 2009-10-30
  • 打赏
  • 举报
回复
栈、栈……
qq272552209 2009-10-30
  • 打赏
  • 举报
回复
书只是参考,有可能 是印刷错误,不要但相信书了,要有自己的想法。
出栈的时候,首先判断是否为空,这个是调用上边的函数,函数一定有返回值,如果是1的话,说明是空栈,否则就不是空栈。
if(is_empty(S) == 1)
printf("输出一些提示错误信息等、、、");
else

return s->a[s->top];

这个就是利用一个函数的调用,来判断是否为空。
sxjkk 2009-10-29
  • 打赏
  • 举报
回复
刚写的程序没编译检查,不好意思,再发一次,这次编译通过,并且测试过


#include <stdio.h>

/** 栈的大小 **/
#define _MAX_ 10
/** 栈结构 **/
int array[_MAX_];
/** 栈指针 **/
int top = -1;

/** 是否为空栈 **/
int isEmpty()
{
return top == -1;
}

/** 栈是否满 **/
int isFull()
{
return top == _MAX_;
}

/** 数据入栈 **/
void push(int j)
{
if(!isFull())
array[++top] = j;
}

/** 数据出栈 **/
int pop()
{
if(!isEmpty())
return array[top--];
}

/** 当前栈指针位置的数据 **/
int peek()
{
return array[top];
}

int main()
{

push(20);
push(40);
push(60);
push(80);

while(isEmpty() != 1)
{
printf("%d,", pop());
}
}

sxjkk 2009-10-29
  • 打赏
  • 举报
回复
容易出现异常的地方是POP出栈函数和PUSH压栈函数

那么,我们对这两个函数再改进下


/** 数据入栈 **/
void push(int j)
{
if(!isFull())
array[++top] = j;
}

/** 数据出栈 **/
int pop()
{
if(!isEmpty)
return array[top--];
}


这样就规避了在入栈和出栈时出错的可能
james_hw 2009-10-29
  • 打赏
  • 举报
回复
感觉你两个写法大同小异,因为assert同样会中断程序,和exit没什么差别。

我认为这种代价还是由程序员保护,即程序员调用pop前先自己判断is_empty。
火山1009 2009-10-29
  • 打赏
  • 举报
回复
学习了哈。。。。
sxjkk 2009-10-29
  • 打赏
  • 举报
回复
我觉得你写的栈有些麻烦了,其实很简单的,我给你我的一个栈实现参考


#include <stdio.h>

/** 栈的大小 **/
int max = 10;
/** 栈结构 **/
int array[max];
/** 栈指针 **/
int top = -1;

/** 数据入栈 **/
void push(int j)
{
array[++top] = j;
}

/** 数据出栈 **/
int pop()
{
return array[top--];
}

/** 当前栈指针位置的数据 **/
int peek()
{
return array[top];
}

/** 是否为空栈 **/
int isEmpty()
{
return top == -1;
}

/** 栈是否满 **/
int isFull()
{
reutrn top == max
}

int main()
{

push(20);
push(40);
push(60);
push(80);

while(isEmpty() != 1)
{
printf("%d,", pop());
}
}



基本原理就是一个后进先出的数据结构
cattycat 2009-10-29
  • 打赏
  • 举报
回复
空的话,抛出异常,或返回错误标志也行。
cphj 2009-10-29
  • 打赏
  • 举报
回复
另外建议你看看“基于契约的编程”

再一个,C/C++的思想是“不为可能不使用的东西付出开销”,还有“相信程序员”,所以不建议你在pop()里面做empty检测

如果倾向于预防错误,那么推荐用Java或者C#,它们都会对pop() empty的stack的动作抛出异常
cphj 2009-10-29
  • 打赏
  • 举报
回复
个人建议你参考STL的实现

比如STL中,在pop()里面的empty检查是用DEBUG宏包起来的,也就说release版本里面,stack本身并不检查empty

而你使用stack的代码应该确保不对empty的stack做pop()动作,比如算法的设计本身确保stack里面一定有元素,或者用empty来做为算法结束条件等等
feifanup 2009-10-29
  • 打赏
  • 举报
回复
由谁负责判断verify 应该是事前约定好的
还包括对入参判断合法性,已经出参合法性的判断都有约定
jackyjkchen 2009-10-29
  • 打赏
  • 举报
回复
如果发生了内存分配、访问错误,出一点错就退出是正解

69,369

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧