C语言数据结构----栈的应用(程序的符号匹配检测)
本节主要讲利用栈来实现一个程序中的成对出现的符号的检测,完成一个类似编译器的符号检测的功能,采用的是链式栈。
一、问题的提出以及解决方法
1.假定有下面一段程序:
#include <stdio.h>
#include <stdlib.h> int main ()
{
int a[5][5];
int(*p)[5]; p = a[0]; printf ("%d", &a[3][3] - &p[3][3]);
}
这段程序中<>[]{}""这些符号都是成对出现的,假如不是成对出现,那么我的程序在编译的时候将会报错。
2.我们即将要编写的程序的主要目的就是来检测程序中所出现的成对的符号是否都匹配。
3.解决方法:
假定我们要检测的程序是上面的一段程序,那么我们要把每一个字符都进行扫描,当程序遇见字母数字或者非成对的符号的时候直接忽略,当程序遇见了成对出现的符号的左符号时我们将左符号压入栈。当扫描的过程中遇见右括号的时候,我们将栈顶元素弹出,进行匹配,如果匹配程序则继续扫描,如果匹配失败,则报错。如果所有的都匹配成功,那么栈为空且所有字符都扫描失败。如果没有匹配成功,那么就是匹配失败或者栈不为空。
4.算法框架
程序的算法框架如下:
二、具体程序的实现
1.程序的具体实现主要采用链式栈的数据结构,同时链式栈是通过复用单向链表来实现的,这些在点击打开链接这篇博文中都有讲解。所以算法实现的主要部分都是在主函数中实现的,也就是我所谓的上层函数。
2.首先采用在主函数中调用其他函数的方式来实现整个程序的运行。
int main()
{
char *a = "#include <stdio.h> #include <stdlib.h> int main () { int a[5][5]; int(*p)[5]; p = a[0]; printf (\"%d\", &a[3][3] - &p[3][3]); } ";
scan(a);
return 0;
}
定义的是一个字符串数组,将字符串数组的首地址传递给scan,这里直接说字符串数组可能不太确切,关于字符和字符串的问题我始终没有搞清楚,拖到了现在。
3.scan函数接部分
(1)scan函数接收的是字符串数组的指针
int scan (char *a)
(2)调用链式栈的函数进行建栈的操作,返回的是栈指针(因为以后只要涉及到栈的操作都要使用到栈指针)
LinkStack * stack = LinkStack_Create();
(3)因为程序的算法中已经说明,我们要不断的扫描所有的字符,直到整个字符串结束,字符串结束的标志是'\0',这里采用while循环来实现
while (a[i] != '\0')
这里通过传递进来的字符串数组的首地址,我们可以通过这个首地址来定义一个字符数组,然后进行操作。
(4)首先判定数组中的元素是否为成对匹配的符号的左符号,如果是左符号,那么将左符号压进栈。
if (left(a[i]) == 1)
{
LinkStack_Push(stack, (void*)(a + i));
}
在将左符号压进栈的操作中,我们压进栈的是数组元素的地址,这里也是链式栈的可复用性的一个体现。
(5)接下来判定数组中的元素是否为成对匹配的符号的右符号,如果是右符号,那么将栈顶元素弹出,并和相应的右符号进行比较。如果栈顶元素为空或者比较失败,那么将进行报错。
if (right(a[i]) == 1)
{
char* bijiao = (char*)LinkStack_Pop(stack);
if ((bijiao == NULL) || !match(*bijiao, a[i]))
{
printf ("%c\n", a[i]);
ret = 0;
break;
}
}
(6)最后,成功的完成了检测的条件是:栈顶为空且已经检测到了最后一个结束符。
if (LinkStack_Top(stack) == NULL && a[i] == '\0')
{
printf ("编译成功\n");
}
(7)程序执行的过程中还有其他几个子函数
1)检测是否为左符号的函数2)检测是否为右符号的函数3)进行比较的函数
三、具体代码
1.程序实现所复用的链式栈的详细代码请看点击打开链接和点击打开链接部分,这里粘的是主函数的实现部分。由于是菜鸟,所以可能有的代码部分写的比较粗糙,望大家见谅。
2.主函数的实现部分代码:
#include <stdio.h>
#include <stdlib.h>
#include "1.h" /*******************************************************************************
*函数名:left
*参数:char a 传进来的数组元素
*返回值:int类型 如果是左侧符号,那么返回1,不是返回0
*功能:判断传进来的字符是否是左侧字符
*******************************************************************************/
int left (char a)
{
int ret = 0;
switch(a)
{
case '<':
ret = 1;
break;
case '(':
ret = 1;
break;
case '[':
ret = 1;
break;
case '{':
ret = 1;
break;
case '\'':
ret = 1;
break;
case '\"':
ret = 1;
break;
default:
ret = 0;
break;
}
return ret;
} /*******************************************************************************
*函数名:right
*参数:char a 传进来的数组元素
*返回值:int类型 如果是右侧符号,那么返回1,不是返回0
*功能:判断传进来的字符是否是右侧字符
*******************************************************************************/
int right (char a)
{
int ret = 0;
switch(a)
{
case '>':
case ')':
case ']':
case '}':
case '\'':
case '\"':
ret = 1;
break;
default:
ret = 0;
break;
}
return ret;
} /*******************************************************************************
*函数名:right
*参数:char a 传进来的数组元素
*返回值:int类型 如果是右侧符号,那么返回1,不是返回0
*功能:判断传进来的字符是否是右侧字符
*******************************************************************************/
int match(char bijiao, char a)
{
int ret = 0;
int i = 0;
switch(bijiao)
{
case '<':
ret = (a == '>');
break;
case '(':
ret = (a == ')');
break;
case '[':
ret = (a == ']');
break;
case '{':
ret = (a == '}');
break;
case '\'':
ret = (a == '\'');
break;
case '\"':
ret = (a == '\"');
break;
default:
ret = 0;
break;
}
return ret;
} /*******************************************************************************
*函数名:scan
*参数:char *a 传进来的字符数组元素的地址
*返回值:int类型 如果是右侧符号,那么返回1,不是返回0
*功能:符号匹配算法的主要实现部分
*******************************************************************************/
int scan (char *a)
{
LinkStack * stack = LinkStack_Create();
int i = 0;
int ret = 0; while (a[i] != '\0')
{
if (left(a[i]) == 1)
{
LinkStack_Push(stack, (void*)(a + i));
} if (right(a[i]) == 1)
{
char* bijiao = (char*)LinkStack_Pop(stack);
if ((bijiao == NULL) || !match(*bijiao, a[i]))
{
printf ("%c\n", a[i]);
ret = 0;
break;
}
}
i++;
} if (LinkStack_Top(stack) == NULL && a[i] == '\0')
{
printf ("编译成功\n");
}
else
{
printf ("出现错误\n");
}
LinkStack_Destroy(stack); return ret;
} int main()
{
char *a = "#include <stdio.h> #include <stdlib.h> int main () { int a[5][5]; int(*p)[5]; p = a[0]; printf (\"%d\", &a[3][3] - &p[3][3]); } ";
scan(a);
return 0;
}
C语言数据结构----栈的应用(程序的符号匹配检测)的更多相关文章
- C语言数据结构----栈与递归
本节主要说程序中的栈函数栈的关系以及栈和递归算法的关系. 一.函数调用时的栈 1.程序调用时的栈是也就是平时所说的函数栈是数据结构的一种应用,函数调用栈一般是从搞地质向低地址增长的,栈顶为内存的低地址 ...
- C语言数据结构-栈的实现-初始化、销毁、长度、取栈顶元素、查找、入栈、出栈、显示操作
1.数据结构-栈的实现-C语言 #define MAXSIZE 100 //栈的存储结构 typedef struct { int* base; //栈底指针 int* top; //栈顶指针 int ...
- 数据结构——栈的应用 NOI2.2 括号匹配问题
栈是一种数据结构,相当于一个容器,将一个又一个变量从顶端压进去,需要使用时,又从顶端拿出来,其具体使用方法,下面是详细讲解: #include<stack>必须使用此头文件 stack&l ...
- C语言数据结构-栈
一.栈的定义 栈(statck)这种数据结构在计算机中是相当出名的.栈中的数据是先进后出的(First In Last Out, FILO).栈只有一个出口,允许新增元素(只能在栈顶上增加). 移出元 ...
- C语言数据结构栈
#include<stdio.h>#include<stdlib.h>typedef struct Node{ int data; struct Node* pnext;}no ...
- C语言数据结构----栈的定义及实现
本节主要说的是数据结构中的栈的基本定义和实现的方式,其中实现的方式采用的是复用顺序表和单向链表的方式. 一.栈的基本定义 1.栈是一种特殊的线性表,只能从固定的方向进出,而且栈进出的基本原则是:先进栈 ...
- 栈的应用:表达式括号匹配检测(C)
问题说明: 假设数学表达式中允许包含两种括号:圆括号"()"和方括号"[]",嵌套顺序任意. 正确的嵌套模式:( [ ] ( ) ).[ ( [ ] [ ] ) ...
- C语言数据结构之栈:中缀表达式的计算
*注:本人技术不咋的,就是拿代码出来和大家看看,代码漏洞百出,完全没有优化,主要看气质,是吧 学了数据结构——栈,当然少不了习题.习题中最难的也是最有意思的就是这个中缀表达式的计算了(可以算+-*/和 ...
- 数据结构——栈(C语言实现)
#include <stdio.h> #include <stdlib.h> #include<string.h> #include<malloc.h> ...
随机推荐
- HTTP中的URL长度限制(资料整理)
HTTP中的URL长度限制 首先,其实http 1.1 协议中对url的长度是不受限制的,协议原文: The HTTP protocol does not place any a priori l ...
- jquery EsayUi 里一个小弹框
网站后台大多的数据展示就都用和此插件有着密切的关系: 来用一下这个小弹框吧: 一个Html里面的代码 <link rel='stylesheet' type='text/css' href='c ...
- python排序(冒泡, 快速)
之前用java时学习的一些基础算法,今天在python上也研究下. 1. 冒泡排序 算法步骤: 50 30 70 90 10 1)50 跟 30 比不用交换. 2)步数+1, 30 跟70比 ...
- Paas
bae sae PowerApp 还有啥???
- zk 节点故障 重连机制
<pre name="code" class="html">如果在连接时候zk服务器宕机 To create a client session th ...
- CC++初学者编程教程(5) 安装codeblocks软件开发环境
Code::Blocks 是一个开放源码的全功能的跨平台C/C++集成开发环境. Code::Blocks是开放源码软件.Code::Blocks由纯粹的C++语言开发完成,它使用了蓍名的图形界面库w ...
- MAC 下使用ipv6、ipv4观看电视、网络电视
换了mac book,ipv6电视却看不了了,为了看电视,只要自己动手了. 关于ipv6是啥和哪里有ipv6这里就不说了,找度娘吧. 我们观看IPv6视频直播信号有两种,一种是mms协议,另外一种 ...
- Android GUI Building Blocks
说明:此笔记为“Android开发”学习视频的笔记,链接如下:http://open.163.com/movie/2010/1/8/D/M79HE97C3_M79HEQJ8D.html 一, Acti ...
- 轻松实现语音识别的完整代码在android开发中
苹果的iphone 有语音识别用的是Google 的技术,做为Google 力推的Android 自然会将其核心技术往Android 系统里面植入,并结合google 的云端技术将其发扬光大. * C ...
- 分布式拒绝服务攻击(DDoS)原理及防范【转】
DDoS攻击概念 DoS的攻击方式有很多种,最基本的DoS攻击就是利用合理的服务请求来占用过多的服务资源,从而使合法用户无法得到服务的响应. DDoS攻击手段是在传统的DoS攻击基础之上产生的一类攻击 ...