栈的应用举例--行编辑程序(第三章 P49 算法3.2)

栈的应用举例--行编辑程序

 

介绍:

一个简单的行编辑程序的功能是:接受用户从终端输入的程序或数据,并存入用户的数据区。由于用户在终端上进行输入时,不能保证不出差错,因此,若在编辑程序中,“每接受一个字符即存入用户数据区” 的做法显然不是最恰当的。

较好的做法是,设立一个输入缓冲区,用以接受用户输入的一行字符,然后逐行存入用户数据区。允许用户输入出差错,并在发现有误时可以及时更正。

例如,当用户发现刚刚键入的一个字符是错的时,可以补进一个退格符 “#” ,以表示前一个字符无效;如果发现当前键入的行内差错较多或难以补救,则可以键入一个退行符 “@” ,以表示当前行中的字符均无效。

 


typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */
typedef char SElemType; /* 定义栈元素的类型 */

#include<malloc.h> /* malloc()等 */
#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<process.h> /* exit() */

/* 函数结果状态代码 */
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2 

/* --------------------------   栈的顺序存储表示   -----------------------------*/

#define STACK_INIT_SIZE 10 /* 存储空间初始分配量 */
#define STACKINCREMENT 2 /* 存储空间分配增量 */
typedef struct SqStack
{
	SElemType *base; /* 在栈构造之前和销毁之后,base的值为NULL */
	SElemType *top; /* 栈顶指针 */
	int stacksize; /* 当前已分配的存储空间,以元素为单位 */
}SqStack; /* 顺序栈 */

/* ----------------------------------------------------------------------------*/


Status visit(SElemType c)
{
	printf("%d ", c);
	return OK;
}


/* ---------------------------------   需要用到的顺序栈基本操作  ------------------------------------*/

Status InitStack(SqStack *S)
{ /* 构造一个空栈S */
	(*S).base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));
	if (!(*S).base)
		exit(OVERFLOW); /* 存储分配失败 */
	(*S).top = (*S).base;
	(*S).stacksize = STACK_INIT_SIZE;
	return OK;
}

Status DestroyStack(SqStack *S)
{ /* 销毁栈S,S不再存在 */
	free((*S).base);
	(*S).base = NULL;
	(*S).top = NULL;
	(*S).stacksize = 0;
	return OK;
}

Status ClearStack(SqStack *S)
{ /* 把S置为空栈 */
	(*S).top = (*S).base;
	return OK;
}

Status Push(SqStack *S, SElemType e)
{ /* 插入元素e为新的栈顶元素 */
	if ((*S).top - (*S).base >= (*S).stacksize) /* 栈满,追加存储空间 */
	{
		(*S).base = (SElemType *)realloc((*S).base, ((*S).stacksize + STACKINCREMENT) * sizeof(SElemType));
		if (!(*S).base)
			exit(OVERFLOW); /* 存储分配失败 */
		(*S).top = (*S).base + (*S).stacksize;
		(*S).stacksize += STACKINCREMENT;
	}
	*((*S).top)++ = e;
	return OK;
}

Status Pop(SqStack *S, SElemType *e)
{ /* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */
	if ((*S).top == (*S).base)
		return ERROR;
	*e = *--(*S).top;
	return OK;
}

Status StackTraverse(SqStack S, Status(*visit)(SElemType))
{ /* 从栈底到栈顶依次对栈中每个元素调用函数visit()。 */
  /* 一旦visit()失败,则操作失败 */
	while (S.top > S.base)
		visit(*S.base++);
	printf("\n");
	return OK;
}




/* -------------------------------------------------------------------------------------------------*/

FILE *fp;

Status copy(SElemType c)
{ /* 将字符c送至fp所指的文件中 */
	fputc(c, fp);
	return OK;
}

void LineEdit()
{ /* 利用字符栈s,从终端接收一行并送至调用过程的数据区。算法3.2 */
	SqStack s;
	char ch, c;
	InitStack(&s);
	printf("请输入一个文本文件,^Z结束输入:\n");
	ch = getchar();
	while (ch != EOF)
	{ /* EOF为^Z键,全文结束符 */
		while (ch != EOF && ch != '\n')
		{
			switch (ch)
			{
			case '#':Pop(&s, &c);
				break; /* 仅当栈非空时退栈 */
			case '@':ClearStack(&s);
				break; /* 重置s为空栈 */
			default:Push(&s, ch); /* 有效字符进栈 */
			}
			ch = getchar(); /* 从终端接收下一个字符 */
		}
		StackTraverse(s, copy); /* 将从栈底到栈顶的栈内字符传送至文件 */
		ClearStack(&s); /* 重置s为空栈 */
		fputc('\n', fp);
		if (ch != EOF)
			ch = getchar();
	}
	DestroyStack(&s);
}

void main()
{
	fp = fopen("ED.DAT", "w"); /* 在当前目录下建立ED.DAT文件,用于写数据, */
	if (fp)                  /* 如已有同名文件则先删除原文件 */
	{
		LineEdit();
		fclose(fp); /* 关闭fp所指的文件 */
	}
	else
		printf("建立文件失败!\n");
}

 

运行结果:

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值