C 栈实例
就近匹配:
应用1:就近匹配
几乎所有的编译器都具有检测括号是否匹配的能力
如何实现编译器中的符号成对检测?
#include <stdio.h> int main() { int a[][]; int (*p)[]; p = a[]; return ; 算法思路
从第一个字符开始扫描
当遇见普通字符时忽略,
当遇见左符号时压入栈中
当遇见右符号时从栈中弹出栈顶符号,并进行匹配
匹配成功:继续读入下一个字符
匹配失败:立即停止,并报错
结束:
成功: 所有字符扫描完毕,且栈为空
失败:匹配失败或所有字符扫描完毕但栈非空
当需要检测成对出现但又互不相邻的事物时
可以使用栈“后进先出”的特性
栈非常适合于需要“就近匹配”的场合 计算机的本质工作就是做数学运算,那计算机可以读入字符串
“ + ( - ) * + / ”并计算值吗?
#include "stdio.h"
#include "stdlib.h"
#include "linkstack.h" int isLeft(char c)
{
int ret = ; switch(c)
{
case '<':
case '(':
case '[':
case '{':
case '\'':
case '\"':
ret = ;
break;
default:
ret = ;
break;
} return ret;
} int isRight(char c)
{
int ret = ; switch(c)
{
case '>':
case ')':
case ']':
case '}':
case '\'':
case '\"':
ret = ;
break;
default:
ret = ;
break;
} return ret;
} int match(char left, char right)
{
int ret = ; switch(left)
{
case '<':
ret = (right == '>');
break;
case '(':
ret = (right == ')');
break;
case '[':
ret = (right == ']');
break;
case '{':
ret = (right == '}');
break;
case '\'':
ret = (right == '\'');
break;
case '\"':
ret = (right == '\"');
break;
default:
ret = ;
break;
} return ret;
} int scanner(const char* code)
{
LinkStack* stack = LinkStack_Create();
int ret = ;
int i = ; while( code[i] != '\0' )
{
if( isLeft(code[i]) )
{
LinkStack_Push(stack, (void*)(code + i)); //&code[i]
} if( isRight(code[i]) )
{
char* c = (char*)LinkStack_Pop(stack); if( (c == NULL) || !match(*c, code[i]) )
{
printf("%c does not match!\n", code[i]);
ret = ;
break;
}
} i++;
} if( (LinkStack_Size(stack) == ) && (code[i] == '\0') )
{
printf("Succeed!\n");
ret = ;
}
else
{
printf("Invalid code!\n");
ret = ;
} LinkStack_Destroy(stack); return ret;
} void main()
{
const char* code = "#include <stdio.h> int main() { int a[4][4]; int (*p)[4]; p = a[0]; return 0; "; scanner(code);
system("pause");
return ;
}
中缀表达式和后缀表达式
应用2:中缀 后缀
计算机的本质工作就是做数学运算,那计算机可以读入字符串
“ + ( - ) * + / ”并计算值吗?
后缀表达式 ==?符合计算机运算
波兰科学家在20世纪50年代提出了一种将运算符放在数字后面的后缀表达式对应的,
我们习惯的数学表达式叫做中缀表达式===》符合人类思考习惯 实例:
+ => +
+ * => * +
+ ( – ) * => – * +
中缀表达式符合人类的阅读和思维习惯
后缀表达式符合计算机的“运算习惯”
如何将中缀表达式转换成后缀表达式?
中缀转后缀算法:
遍历中缀表达式中的数字和符号
对于数字:直接输出
对于符号:
左括号:进栈
运算符号:与栈顶符号进行优先级比较
若栈顶符号优先级低:此符合进栈 (默认栈顶若是左括号,左括号优先级最低)
若栈顶符号优先级不低:将栈顶符号弹出并输出,之后进栈
右括号:将栈顶符号弹出并输出,直到匹配左括号
遍历结束:将栈中的所有符号弹出并输出
中缀转后缀
计算机是如何基于后缀表达式计算的?
– * +
遍历后缀表达式中的数字和符号
对于数字:进栈
对于符号:
从栈中弹出右操作数
从栈中弹出左操作数
根据符号进行运算
将运算结果压入栈中
遍历结束:栈中的唯一数字为计算结果
栈的神奇!
中缀表达式是人习惯的表达方式
后缀表达式是计算机喜欢的表达方式
通过栈可以方便的将中缀形式变换为后缀形式
中缀表达式的计算过程类似程序编译运行的过程 扩展:给你一个字符串,计算结果
“ + * ( / ( * ) + )” 字符串解析
词法语法分析
优先级分析
数据结构选型===》栈还是树?
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "linkstack.h" int isNumber(char c)
{
return ('' <= c) && (c <= '');
} int isOperator(char c)
{
return (c == '+') || (c == '-') || (c == '*') || (c == '/');
} int isLeft(char c)
{
return (c == '(');
} int isRight(char c)
{
return (c == ')');
} int priority(char c)
{
int ret = ; if( (c == '+') || (c == '-') )
{
ret = ;
} if( (c == '*') || (c == '/') )
{
ret = ;
} return ret;
} void output(char c)
{
if( c != '\0' )
{
printf("%c", c);
}
} //
void transform(const char* exp)
{
int i = ;
LinkStack* stack = LinkStack_Create(); while( exp[i] != '\0' )
{
if( isNumber(exp[i]) )
{
output(exp[i]);
}
else if( isOperator(exp[i]) )
{
while( priority(exp[i]) <= priority((char)(int)LinkStack_Top(stack)) )
{
output((char)(int)LinkStack_Pop(stack));
} LinkStack_Push(stack, (void*)(int)exp[i]);
}
else if( isLeft(exp[i]) )
{
LinkStack_Push(stack, (void*)(int)exp[i]);
}
else if( isRight(exp[i]) )
{
//char c = '\0';
while( !isLeft( (char)(int)LinkStack_Top(stack) ) )
{
output((char)(int)LinkStack_Pop(stack));
} LinkStack_Pop(stack);
}
else
{
printf("Invalid expression!");
break;
} i++;
} while( (LinkStack_Size(stack) > ) && (exp[i] == '\0') )
{
output((char)(int)LinkStack_Pop(stack));
} LinkStack_Destroy(stack);
} int main()
{
transform("8+(3-1)*5"); printf("\n");
system("pause");
return ;
} #include <stdio.h>
#include "LinkStack.h" int isNumber3(char c)
{
return ('' <= c) && (c <= '');
} int isOperator3(char c)
{
return (c == '+') || (c == '-') || (c == '*') || (c == '/');
} int value(char c)
{
return (c - '');
} int express(int left, int right, char op)
{
int ret = ; switch(op)
{
case '+':
ret = left + right;
break;
case '-':
ret = left - right;
break;
case '*':
ret = left * right;
break;
case '/':
ret = left / right;
break;
default:
break;
} return ret;
} int compute(const char* exp)
{
LinkStack* stack = LinkStack_Create();
int ret = ;
int i = ; while( exp[i] != '\0' )
{
if( isNumber3(exp[i]) )
{
LinkStack_Push(stack, (void*)value(exp[i]));
}
else if( isOperator3(exp[i]) )
{
int right = (int)LinkStack_Pop(stack);
int left = (int)LinkStack_Pop(stack);
int result = express(left, right, exp[i]); LinkStack_Push(stack, (void*)result);
}
else
{
printf("Invalid expression!");
break;
} i++;
} if( (LinkStack_Size(stack) == ) && (exp[i] == '\0') )
{
ret = (int)LinkStack_Pop(stack);
}
else
{
printf("Invalid expression!");
} LinkStack_Destroy(stack); return ret;
} int main()
{
printf("8 + (3 - 1) * 5 = %d\n", compute("831-5*+"));
system("pause");
return ;
}
C 栈实例的更多相关文章
- JAVA栈实例—括号匹配
import java.util.Stack; public class test { public static void main(String[] args){ System.out.print ...
- 框架学习之Struts2(三)---OGNL和值栈
一.OGNL概述 1.1OGNL是对象图导航语言(Object-Graph Navigation Languaged)的缩写,他是一种功能强大的表达式语言,通过简单一致的表达式语法,可以存取Java对 ...
- [ SSH框架 ] Struts2框架学习之三(OGNl和ValueStack值栈学习)
一.OGNL概述 1.1 什么是OGNL OGNL的全称是对象图导航语言( object-graph Navigation Language),它是一种功能强大的开源表达式语言,使用这种表达式语言,可 ...
- C语言函数调用栈(三)
6 调用栈实例分析 本节通过代码实例分析函数调用过程中栈帧的布局.形成和消亡. 6.1 栈帧的布局 示例代码如下: //StackReg.c #include <stdio.h> //获取 ...
- OGNL与值栈
一.OGNL入门 1.什么是OGNL OGNL的全称是对象图导航语言(Object-Graph Navigation Language),它是一种功能强大的开源表达式语言.使用这种表达式语言,可以通过 ...
- 面试题:struts 值栈 有用
一. 核心部分 1. [核心试题]完成当天课堂练习 2. [多选题] 阅读如下代码中,下列哪种方式可以在页面正确迭代获取集合中的数据 (ABC) public String add(){ ValueS ...
- (转)OGNL与值栈
http://blog.csdn.net/yerenyuan_pku/article/details/67709693 OGNL的概述 什么是OGNL 据度娘所说: OGNL是Object-Graph ...
- PWN菜鸡入门之函数调用栈与栈溢出的联系
一.函数调用栈过程总结 Fig 1. 函数调用发生和结束时调用栈的变化 Fig 2. 将被调用函数的参数压入栈内 Fig 3. 将被调用函数的返回地址压入栈内 Fig 4. 将调用函数的基地址(ebp ...
- 4、OGNL与值栈
一.OGNL 1.什么是OGNL 对象导航图语言(Object Graph Navigation Language),简称OGNL,是应用于Java中的一个开源的表达式语言(Expression La ...
随机推荐
- 什么是Zookeeper,Zookeeper的作用是什么,在Hadoop及hbase中具体作用是什么
什么是Zookeeper,Zookeeper的作用是什么,它与NameNode及HMaster如何协作?在没有接触Zookeeper的同学,或许会有这些疑问.这里给大家总结一下. 一.什么是Zooke ...
- pattern目录
pattern目录 1.创建型模式 JDK1.5枚举Singleton 单例模式 AbstractFactory 工厂方法模式 简单工厂模式 Builder Prototype 2.结构 ...
- javascript-实现日期大写
<script language="javascript"> $(document).ready(function() { //定义中文数组 var chinese = ...
- css定位方式
CSS表达式 匹配元素说明 xpath * 匹配任何元素 //* div 标签 //div div#eleID by ID //div[@id='eleID'] div.class by clas ...
- bzoj 2244 [SDOI2011]拦截导弹(DP+CDQ分治+BIT)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2244 [题意] 给定n个二元组,求出最长不上升子序列和各颗导弹被拦截的概率. [思路] ...
- POJ 2429
思路:a/n*b/n=lcm/gcd 所以这道题就是分解ans.dfs枚举每种素数情况.套Miller_Rabin和pollard_rho模板 //#pragma comment(linker, &q ...
- MATLAB绘图与图形处理
参考:http://www.cnblogs.com/djcsch2001/tag/MATLAB/ matlab部分写的不错! 7.2 三维图形 7.2.1 三维曲线.面填色命令 命令1 com ...
- 【创建本地仓库】【for Centos】CentOS下创建本地repository
[日期]2014年4月24日 [平台]Centos 6.5 [工具]httpd yum-utils createrepo [步骤] 1)安装httpd. yum install httpd 2)安装y ...
- asp.net(C#) 中 怎么使用 MongoDb
1. 先引用以下Dll(如果找不到 到gethub上下载源代码自己编译 特别是MongoDB.Driver.Legacy.dll 我自己找了半天没找到): MongoDB.Bson.dll Mongo ...
- POJ2778&HDU2243&POJ1625(AC自动机+矩阵/DP)
POJ2778 题意:只有四种字符的字符串(A, C, T and G),有M中字符串不能出现,为长度为n的字符串可以有多少种. 题解:在字符串上有L中状态,所以就有L*A(字符个数)中状态转移.这里 ...