关于顺序栈的问题

ouzhf 2010-07-05 07:57:38
程序描述:用顺序栈实现行编辑程序。行编辑程序:当用户发现刚刚键入的一个字符是错的时,可以补进一个退格符“$”,以表示前一个字符无效;如果发现当前键入的行内差错较多或难以补救,则可以键入一个退行符“@”,以表示当前行中的字符均无效。例如:假设从终端接受了这样两行字符:
whli$$ilr$e(s$*s)和outcha@putchar(*s=$++)
则实际有效的是下列两行:while(*s)和putchar(*s++)。

第二个例子运行错误.

虽然栈一般用链式存储,但是发现了问题还是希望能找到解决办法。望各位大大有时间的话帮忙看看,小弟感激不尽,分少可以追加,谢谢!

//sqstack_store_int.h头文件
#include <stdlib.h>
#include <stdio.h>

#ifndef SQSTACK_H_H
#define SQSTACK_H_H

#ifdef _cplusplus
extern "C" {
#endif

#define SQSTACK_MIN_ALLOCATE_NR 10 //初始分配栈的大小

typedef enum
{
SQSTACK_RET_OK,
SQSTACK_RET_FAIL,
SQSTACK_RET_STOP,
}SqStackRet;

struct _SqStack;
typedef struct _SqStack SqStack;

typedef int BOOL;

typedef int (*SqStackVisitFunc)(int *ctx, int data);
// typedef void (*SqStackDataDestroy)(void *ctx, void *data);

SqStack* sqstack_create(void);

SqStackRet sqstack_clear(SqStack *thiz);//清空栈
BOOL sqstack_empty(SqStack *thiz);//判栈是否为空栈,是返回1,否返回0
SqStackRet sqstack_get_top(SqStack *thiz, int *data);//取栈顶元素
SqStackRet sqstack_push(SqStack *thiz, int data);//入栈
SqStackRet sqstack_pop(SqStack *thiz, int *data);//出栈
SqStackRet sqstack_traverse(SqStack *thiz, SqStackVisitFunc sq_visit, int *ctx);//遍历栈,在本例中没有用它

size_t sqstack_length(SqStack *thiz);
void sqstack_destroy(SqStack *thiz);
void print_stack(SqStack *thiz);//本例没用到
void print_stack_str(SqStack *thiz);//本例用到的输出函数:将栈中元素输出(栈底->栈顶).

#ifdef _cplusplus
}
#endif

#endif




//sqstack_store_int.c文件
#include "sqstack_store_int.h"

struct _SqStack
{
int *base;
int *top;
size_t stack_size;
};

//创建一个空栈
SqStack * sqstack_create(void)
{
SqStack *thiz = (SqStack *)malloc(sizeof(SqStack));

if (thiz != NULL)
{
thiz->base = NULL;
thiz->top = NULL;
thiz->stack_size = 0;
}

return thiz;
}

//判栈是否为空栈,是返回1,否返回0
BOOL sqstack_empty(SqStack *thiz)
{
return ( (thiz == NULL) || ((thiz != NULL) && (thiz->base == thiz->top)) ) ? 1 : 0;
}

SqStackRet sqstack_get_top(SqStack *thiz, int *data)
{
if ((thiz != NULL) && (thiz->base != thiz->top))
{
*data = *(thiz->top - 1);

return SQSTACK_RET_OK;
}
else
{
return SQSTACK_RET_FAIL;
}
}

//判断栈中是否满足need的空间,若空间不够,则分配空间。
static SqStackRet stack_need(SqStack *thiz, size_t need)
{
size_t sqstack_len = sqstack_length(thiz);

if ((sqstack_len + need) > thiz->stack_size)
{
size_t alloc_size = thiz->stack_size + (thiz->stack_size>>2) + SQSTACK_MIN_ALLOCATE_NR; //现有元素的1.5倍,为了避免为0,总是加上一个最小量
int *p = (int *)realloc(thiz->base, sizeof(int) * alloc_size);

if (p != NULL)
{
thiz->base = p;
thiz->top = thiz->base + sqstack_len;
thiz->stack_size = alloc_size;
}
}

return sqstack_len + need <= thiz->stack_size ? SQSTACK_RET_OK : SQSTACK_RET_FAIL;
}

//入栈
SqStackRet sqstack_push(SqStack *thiz, int data)
{
SqStackRet ret = stack_need(thiz, 1);//判断有没有空间,若没有则为其分配空间

if (ret == SQSTACK_RET_OK)
{
*(thiz->top) = data;
thiz->top++;
}

return ret;
}

//当栈中元素个数小于栈容量的一半,并且栈的容量大于最小量SQSTACK_MIN_ALLOCATE_NR时,对栈进行压缩.
static SqStackRet sqstack_shrink(SqStack *thiz)
{
size_t sqstack_len = sqstack_length(thiz);

if (sqstack_len < (thiz->stack_size>>1) && thiz->stack_size > SQSTACK_MIN_ALLOCATE_NR)
{
size_t alloc_size = sqstack_len + (sqstack_len>>1);
int *p = (int *)realloc(thiz->base, alloc_size);

if (p != NULL)
{
thiz->base = p;
thiz->top = thiz->base + sqstack_len;
thiz->stack_size = alloc_size;
}
else
{
return SQSTACK_RET_FAIL;
}
}

return SQSTACK_RET_OK;
}

SqStackRet sqstack_pop(SqStack *thiz, int *data)
{
SqStackRet ret = SQSTACK_RET_FAIL;

if (thiz != NULL)
{
if (!sqstack_empty(thiz))
{
*data = *(--thiz->top);
// ret = sqstack_shrink(thiz);//就是这个地方的问题。用下面的语句替代,整个程序就OK。
ret =SQSTACK_RET_OK;
}
}

return ret;
}

size_t sqstack_length(SqStack *thiz)
{
size_t length = 0;

if (thiz != NULL)
{
length = (thiz->base == thiz->top) ? 0 : (thiz->top - thiz->base);
}

return length;
}

SqStackRet sqstack_clear(SqStack *thiz)
{
if (thiz != NULL)
{
free(thiz->base);

thiz->base = NULL;
thiz->top = NULL;
thiz->stack_size = 0;
}

return SQSTACK_RET_OK;
}

//遍历栈,本例没有用到。
SqStackRet sqstack_traverse(SqStack *thiz, SqStackVisitFunc visit, int *ctx)
{
SqStackRet ret = SQSTACK_RET_OK;
int *iter = thiz->top - 1;

while (iter >= thiz->base && ret != SQSTACK_RET_STOP)
{
ret = visit(ctx, *iter);
iter--;
}

return ret;
}


void sqstack_destroy(SqStack *thiz)
{
sqstack_clear(thiz);
free(thiz);

return;
}

//该函数本例没有用到
void print_stack(SqStack *thiz)
{
if (thiz != NULL)
{
int *iter = thiz->base;
while (iter < thiz->top)
{
printf("%4d\t", *iter);
iter++;
}
}

printf("\n");
return ;
}

//本例中用到的输出函数,以字符形式从栈底到栈顶输出内容
void print_stack_str(SqStack *thiz)
{
if (thiz != NULL)
{
int *iter = thiz->base;
while (iter < thiz->top)
{
printf("%c", *iter);
iter++;
}
}

printf("\n");
return ;
}



//main.c文件

#include "sqstack_store_int.h"

static void line_edit_translate(char *string)
{
SqStack *stk = sqstack_create();
int tmp;

while (*string != '\0')
{
switch (*string)
{
case '$':
if (!sqstack_empty(stk))
{
sqstack_pop(stk, &tmp);
}
break;
case '@':
sqstack_clear(stk);
break;

default:
sqstack_push(stk, *string);
break;
}

string++;
}

print_stack_str(stk);
sqstack_destroy(stk);
return;
}

void test_line_edit(void)
{
//为了方便,我直接将两个例子放在两个字符串中

char *string1 = "whli$$ilr$e(s$*s)";
char *string2 = "outjhgjhgcha@putchar(*s=$++)";

printf("the string1:%s\n", string1);
line_edit_translate(string1);
printf("the string2:%s\n", string2);
line_edit_translate(string2);
}

int main(int argc, char *argv[])
{
test_line_edit();

return 0;
}

初步原因:sqstack_shrink函数的问题。(1)断点跟踪调试,发现经过该函数过后,虽然内存地址没有发生变化,但是其中有两个值的内容是随机的。(2)将SQSTACK_MIN_ALLOCATE_NR 宏定义的值改得更大些的话,比如30,函数运行成功。
...全文
248 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
ouzhf 2010-07-06
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 kanongzlg 的回复:]
//首先声明一下,很多的东西是通过STL实现的
#include<iostream>
#include<vector>
#include<string>
using namespace std;

//编辑器
class editor{
public:
//解析文本
virtual string changeToText(const string & str)=0;
……
[/Quote]
多谢关注,但是不是好像有点不对题,(*^__^*) 嘻嘻!问题已经解决,要结贴了!
ouzhf 2010-07-06
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 selooloo 的回复:]
你的类型错了,
struct _SqStack
{
int *base;
int *top;
size_t stack_size;
};
这里base是整型指针,你使用时是char
改成这样
struct _SqStack
{
char *base;
char *top;
size_t stack_size;
};
下面的类型都改下就可以了
……
[/Quote]
多谢!确实是这样的。本来这个顺序栈是为了按整型去实现的,在这个例子中,直接就拿了过来,没有更改指针类型。呵呵,把指向字符的指针解释为整型,虽然有时能得到正确结果,但迟早会出错,并且莫名其妙。再次感谢!
kanongzhang 2010-07-06
  • 打赏
  • 举报
回复
//首先声明一下,很多的东西是通过STL实现的
#include<iostream>
#include<vector>
#include<string>
using namespace std;

//编辑器
class editor{
public:
//解析文本
virtual string changeToText(const string & str)=0;
virtual ~editor(){}
};

//用栈实现文本编辑
class stack_editor:public editor{\
public:
stack_editor();
~stack_editor();
string changeToText(const string & str);
void test();
private:
stack_editor(const stack_editor& editor){}
private:
vector<char> * _stack;
};

stack_editor::stack_editor(){
this->_stack = new vector<char>();
}

stack_editor::~stack_editor(){
delete(this->_stack);
}

//解析文本
string stack_editor::changeToText(const string & str){
string result="";
for(int i=str.size()-1; i>=0; i--){
this->_stack->push_back(str[i]);
}

vector<char> vect;
while(false==this->_stack->empty()){
char c=this->_stack->back();
if('@'==c)
{
vect.clear();
}else if('$'==c){
if(vect.empty==false){
vect.pop_back();
}
}else{
vect.push_back(c);
}
this->_stack->pop_back();
}

vector<char>::iterator c=this->_stack->begin();
for(vector<char>::iterator iter1=vect.begin(); iter1!=vect.end(); iter1++){
result+=(*iter1);
}

return result;
}



void main(){
editor * _editor=new stack_editor();
cout<<_editor->changeToText("@@@@@@sadfasdfasdfasdf$$$$$$")<<endl;
delete(_editor);
}
selooloo 2010-07-05
  • 打赏
  • 举报
回复
你的类型错了,
struct _SqStack
{
int *base;
int *top;
size_t stack_size;
};
这里base是整型指针,你使用时是char
改成这样
struct _SqStack
{
char *base;
char *top;
size_t stack_size;
};
下面的类型都改下就可以了
ouzhf 2010-07-05
  • 打赏
  • 举报
回复
[Quote=引用楼主 ouzhf 的回复:]
程序描述:用顺序栈实现行编辑程序。行编辑程序:当用户发现刚刚键入的一个字符是错的时,可以补进一个退格符“$”,以表示前一个字符无效;如果发现当前键入的行内差错较多或难以补救,则可以键入一个退行符“@”,以表示当前行中的字符均无效。例如:假设从终端接受了这样两行字符:
whli$$ilr$e(s$*s)和outcha@putchar(*s=$++)
则实际有效的是下列两行:while(*s)和p……
[/Quote]

问题补充,为了开头给出的两个例子保持一致,在main.c文件中,test_lin_edit函数中char *string2 = "outjhgjhgcha@putchar(*s=$++)";改为char *string2 = "outcha@putchar(*s=$++)";
ouzhf 2010-07-05
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 zhoutanliang 的回复:]
顶一下。。。

LZ辛苦了。。
[/Quote]
呵呵,不辛苦!希望把问题解释清楚了。
AlanBruce 2010-07-05
  • 打赏
  • 举报
回复
顶一下。。。

LZ辛苦了。。

69,382

社区成员

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

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