就近匹配:
应用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 栈实例的更多相关文章

  1. JAVA栈实例—括号匹配

    import java.util.Stack; public class test { public static void main(String[] args){ System.out.print ...

  2. 框架学习之Struts2(三)---OGNL和值栈

    一.OGNL概述 1.1OGNL是对象图导航语言(Object-Graph Navigation Languaged)的缩写,他是一种功能强大的表达式语言,通过简单一致的表达式语法,可以存取Java对 ...

  3. [ SSH框架 ] Struts2框架学习之三(OGNl和ValueStack值栈学习)

    一.OGNL概述 1.1 什么是OGNL OGNL的全称是对象图导航语言( object-graph Navigation Language),它是一种功能强大的开源表达式语言,使用这种表达式语言,可 ...

  4. C语言函数调用栈(三)

    6 调用栈实例分析 本节通过代码实例分析函数调用过程中栈帧的布局.形成和消亡. 6.1 栈帧的布局 示例代码如下: //StackReg.c #include <stdio.h> //获取 ...

  5. OGNL与值栈

    一.OGNL入门 1.什么是OGNL OGNL的全称是对象图导航语言(Object-Graph Navigation Language),它是一种功能强大的开源表达式语言.使用这种表达式语言,可以通过 ...

  6. 面试题:struts 值栈 有用

    一. 核心部分 1. [核心试题]完成当天课堂练习 2. [多选题] 阅读如下代码中,下列哪种方式可以在页面正确迭代获取集合中的数据 (ABC) public String add(){ ValueS ...

  7. (转)OGNL与值栈

    http://blog.csdn.net/yerenyuan_pku/article/details/67709693 OGNL的概述 什么是OGNL 据度娘所说: OGNL是Object-Graph ...

  8. PWN菜鸡入门之函数调用栈与栈溢出的联系

    一.函数调用栈过程总结 Fig 1. 函数调用发生和结束时调用栈的变化 Fig 2. 将被调用函数的参数压入栈内 Fig 3. 将被调用函数的返回地址压入栈内 Fig 4. 将调用函数的基地址(ebp ...

  9. 4、OGNL与值栈

    一.OGNL 1.什么是OGNL 对象导航图语言(Object Graph Navigation Language),简称OGNL,是应用于Java中的一个开源的表达式语言(Expression La ...

随机推荐

  1. POJ 2135 Farm Tour(最小费用最大流,变形)

    题意:给一个无向图,FJ要从1号点出发到达n号点,再返回到1号点,但是路一旦走过了就会销毁(即回去不能经过),每条路长度不同,那么完成这趟旅行要走多长的路?(注:会有重边,点号无序,无向图!) 思路: ...

  2. Java [leetcode 18]4Sum

    问题描述: Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d ...

  3. HDU 4003-Find Metal Mineral(树状背包)

    题意: n个节点的树给出每个边的权值,有k个机器人,求由机器人走完所有节点的最小花费(所有机器人开始在根节点) 分析: 仔细看了几遍例题后,发现这个题的状态很巧妙,先从整体考虑,一个机器人走完所有边回 ...

  4. Python脚本控制的WebDriver 常用操作 <二十四> 定位frame中的元素

    测试用例场景 处理frame需要用到2个方法,分别是switch_to_frame(name_or_id_or_frame_element)和switch_to_default_content() 如 ...

  5. 寒假训练第九场 Brocard Point of a Triangle

    题意:求布洛卡点坐标 思路:直接利用布洛卡点的性质.http://pan.baidu.com/s/1eQiP76E #include<cstdio> #include<cstring ...

  6. codeforce 605BE. Freelancer's Dreams

    题意:给你n个工程,做了每个工程相应增长x经验和y钱.问你最少需要多少天到达制定目标.时间可以是浮点数. 思路:杜教思路,用对偶原理很简易.个人建议还是标准解题法,凸包+线性组合. #include& ...

  7. ACM2123(一个简单的问题)

    一个简单的问题 问题说明 在这个问题中,你需要做N * N的乘法表,就像样品.第第i 行和j 个列中的元素i和j的乘积(乘积).   输入 输入的第一行是一个整数C中表示测试用例的数量,然后C的测试用 ...

  8. 中断——中断描述符表的定义和初始化(一) (基于3.16-rc4)

    1.中断描述符表的定义(arch/x86/kernel/traps.c) gate_desc debug_idt_table[NR_VECTORS] __page_aligned_bss; 定义的描述 ...

  9. 基于Hadoop 2.2.0的高可用性集群搭建步骤(64位)

    内容概要: CentSO_64bit集群搭建, hadoop2.2(64位)编译,安装,配置以及测试步骤 新版亮点: 基于yarn计算框架和高可用性DFS的第一个稳定版本. 注1:官网只提供32位re ...

  10. android 链接蓝牙不稳定的解决建议

    My workaround I scan BLE for a short period of time 3-4 seconds then I turn scan OFF for 3-4 seconds ...