上一篇博客博主已经讲过了链表对栈的基本操作,这里我将数组对栈的操作,附上。同时这一篇,我们利用栈 平衡字符。
ok 不多废话,上代码。
这里的代码是在dev上写的,因此与使用vs的小伙伴略有不同,稍微改动即可。
先代码,后讲解
#include<stdio.h>
#include<stdlib.h>
#define error(str) fprintf(stderr,"%s\n",str),exit(1)//自定义错误信息 可以用printf来代替
struct node
{
char c;
struct node *next;
};//声明结构体
typedef struct node * stack;//对结构体进行typedef
int checksymbol(stack s);//检测符号
stack creat();//创建栈
int isempty(stack s);//检测是否为空
void makeempty(stack s);//使栈为空
void push(char a,stack s);//入栈
void pop(stack s);//出栈
char top(stack s);//获取栈顶元素
void dispose(stack s);//处理掉栈
int main()
{
stack s=creat();
if(checksymbol(s))
printf("wrong");
else
printf("right");
return 0;
}
int checksymbol(stack s)
{
char ch;
printf("please input the characters as {,} or (,) or [,]\nand input 0 to quit\n");
while((ch=getchar())!='0')
{
if(ch=='['||ch=='{'||ch=='(')
push(ch,s);
else if(ch==']'||ch==')'||ch=='}')
{
if(isempty(s))//如果判断空没问题的话,则栈有问题。
error("stack is empty");
else
{
switch(ch)
{
case '}':
if(top(s)!='{')//不匹配
error("not match");
else
break;//匹配成功
case ')':
if(top(s)!='(')
error("not match");
else
break;
case ']':
if(top(s)!='[')
error("not match");
else
break;
}
pop(s);
}
}
}
if(!isempty(s))
error("not enough");
else
return 0;
}
stack creat()
{
stack s=(stack)malloc(sizeof(struct node));
if(s==NULL)
error("oyt of space");
s->next=NULL;
makeempty(s);
return s;
}
void makeempty(stack s)
{
if(s==NULL)
error("no stack ");
else
while(!isempty(s))
pop(s);
}
int isempty(stack s)
{
return s->next==NULL;
}
void push(char a,stack s)
{
stack t=(stack)malloc(sizeof(struct node));
if(!t)
error("out of space");
t->c=a;
t->next=s->next;
s->next=t;
}
void pop(stack s)
{
stack t;
if(isempty(s))
error("empty stack");
else
{
t=s->next;
s->next=t->next;
free(t);
}
}
char top(stack s)
{
if(!isempty(s))
return s->next->c;
error("empty stack");
return 0;
}
void dispose(stack s)
{
if(s==NULL)
error("no stack");
makeempty(s);
free(s);
}
- 博主建议思路不清晰的小伙伴先把准备工作做好。头文件,typedef,以及函数的接口,完善之后开始写代码,这里注意,博主用了一个小技巧。如下:
#define error(str) fprintf(stderr,"%s\n",str),exit(1),这段代码,使我们可以自定义错误信息,不再是冰冷而晦涩的英文,我们将其改为简单易懂的英文,这里有几个小知识点。
- error(str)只是形式而已,我们可以任意改写,这段代码重点为stderr,接触过fprintf的小伙伴都知道,往文件写入,但是这里我们不是往文件写入,因为有stderr的存在,(小伙伴们目前不必要这道它具体是什么只需要记住便可)我们这段代码可以理解为往屏幕返回一个str的信息。类似于return 0与return 1.但又与之不同。
- 继续看,我们对栈的基本操作,上一篇博客有明讲,这里便不需要多说,我们的核心思路是checksymbol(stack s),我们知道栈这种结构,我们只可使用栈顶的元素,因此我们可以在这个基本思路下构造该函数的思路。我们先输入一个左括号,将其压入栈中,接着用if-else判断,如果不是左括号,我们便要进行判断,是否与之前的左括号相对,这里便可用到栈顶元素,我们按压入顺序,那么我们第一个右括号,就得与最后压入的左括号比较,很明显,这是栈顶元素,因此我们用top函数,进行判断,判断完之后,如果符合我们就使用跑pop将该元素弹出,用来判断下一个左括号。总体思路就是这样。这里博主用了switch语句,很明显,它在这里很方便,但是还是建议小伙伴们顺着思路自己去敲,按着自己的方法敲。
- 还有我们先前定义的error实际上,有时候非常有用。他可以帮我们检验错误,博主一般是用printf检测问题,不过这倒是个新方法,在敲这段代码的时候,我在一个错误卡出,它可以运行,但是有问题,这里error就帮了我大忙,它让我顺藤摸瓜找到了,问题的出处。这里我附上一些这段代码的知识点,有兴趣的小伙伴可以看看。
#define error(str) fprintf(stderr,"%s\n",str),exit(1)
- 这里的 error与str 都是形式,可以按着自己的写。
- stderr,与其类似的还有一个stdout他们在向屏幕输出信息的时候并没有什么区别。但是在向磁盘输入信息的时候便会不同,这里涉及到缓冲的问题。stderr是一个无缓冲输出,他没有缓冲区直接输出,而stdout是一个行缓冲输出,简单来说就是遇到换行符的时候他会输出,同时因为他有一个空间有限的缓冲区,所以一旦缓冲空间满溢,也会输出。还有一种缓冲方式名为慢缓冲即:只有缓冲区填满之后才会输出。😂😂