本节主要讲利用栈来实现一个程序中的成对出现的符号的检测,完成一个类似编译器的符号检测的功能,采用的是链式栈。

一、问题的提出以及解决方法

1.假定有下面一段程序:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. int main ()
  5. {
  6. int a[5][5];
  7. int(*p)[5];
  8.  
  9. p = a[0];
  10.  
  11. printf ("%d", &a[3][3] - &p[3][3]);
  12. }

这段程序中<>[]{}""这些符号都是成对出现的,假如不是成对出现,那么我的程序在编译的时候将会报错。

2.我们即将要编写的程序的主要目的就是来检测程序中所出现的成对的符号是否都匹配。

3.解决方法:

假定我们要检测的程序是上面的一段程序,那么我们要把每一个字符都进行扫描,当程序遇见字母数字或者非成对的符号的时候直接忽略,当程序遇见了成对出现的符号的左符号时我们将左符号压入栈。当扫描的过程中遇见右括号的时候,我们将栈顶元素弹出,进行匹配,如果匹配程序则继续扫描,如果匹配失败,则报错。如果所有的都匹配成功,那么栈为空且所有字符都扫描失败。如果没有匹配成功,那么就是匹配失败或者栈不为空。

4.算法框架

程序的算法框架如下:

二、具体程序的实现

1.程序的具体实现主要采用链式栈的数据结构,同时链式栈是通过复用单向链表来实现的,这些在点击打开链接这篇博文中都有讲解。所以算法实现的主要部分都是在主函数中实现的,也就是我所谓的上层函数。

2.首先采用在主函数中调用其他函数的方式来实现整个程序的运行。

  1. int main()
  2. {
  3. 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]); } ";
  4. scan(a);
  5. return 0;
  6. }

定义的是一个字符串数组,将字符串数组的首地址传递给scan,这里直接说字符串数组可能不太确切,关于字符和字符串的问题我始终没有搞清楚,拖到了现在。

3.scan函数接部分

(1)scan函数接收的是字符串数组的指针

  1. int scan (char *a)

(2)调用链式栈的函数进行建栈的操作,返回的是栈指针(因为以后只要涉及到栈的操作都要使用到栈指针)

  1. LinkStack * stack = LinkStack_Create();

(3)因为程序的算法中已经说明,我们要不断的扫描所有的字符,直到整个字符串结束,字符串结束的标志是'\0',这里采用while循环来实现

  1. while (a[i] != '\0')

这里通过传递进来的字符串数组的首地址,我们可以通过这个首地址来定义一个字符数组,然后进行操作。

(4)首先判定数组中的元素是否为成对匹配的符号的左符号,如果是左符号,那么将左符号压进栈。

  1. if (left(a[i]) == 1)
  2. {
  3. LinkStack_Push(stack, (void*)(a + i));
  4. }

在将左符号压进栈的操作中,我们压进栈的是数组元素的地址,这里也是链式栈的可复用性的一个体现。

(5)接下来判定数组中的元素是否为成对匹配的符号的右符号,如果是右符号,那么将栈顶元素弹出,并和相应的右符号进行比较。如果栈顶元素为空或者比较失败,那么将进行报错。

  1. if (right(a[i]) == 1)
  2. {
  3. char* bijiao = (char*)LinkStack_Pop(stack);
  4. if ((bijiao == NULL) || !match(*bijiao, a[i]))
  5. {
  6. printf ("%c\n", a[i]);
  7. ret = 0;
  8. break;
  9. }
  10. }

(6)最后,成功的完成了检测的条件是:栈顶为空且已经检测到了最后一个结束符。

  1. if (LinkStack_Top(stack) == NULL && a[i] == '\0')
  2. {
  3. printf ("编译成功\n");
  4. }

(7)程序执行的过程中还有其他几个子函数

1)检测是否为左符号的函数2)检测是否为右符号的函数3)进行比较的函数

三、具体代码

1.程序实现所复用的链式栈的详细代码请看点击打开链接点击打开链接部分,这里粘的是主函数的实现部分。由于是菜鸟,所以可能有的代码部分写的比较粗糙,望大家见谅。

2.主函数的实现部分代码:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include "1.h"
  4.  
  5. /*******************************************************************************
  6. *函数名:left
  7. *参数:char a 传进来的数组元素
  8. *返回值:int类型 如果是左侧符号,那么返回1,不是返回0
  9. *功能:判断传进来的字符是否是左侧字符
  10. *******************************************************************************/
  11. int left (char a)
  12. {
  13. int ret = 0;
  14. switch(a)
  15. {
  16. case '<':
  17. ret = 1;
  18. break;
  19. case '(':
  20. ret = 1;
  21. break;
  22. case '[':
  23. ret = 1;
  24. break;
  25. case '{':
  26. ret = 1;
  27. break;
  28. case '\'':
  29. ret = 1;
  30. break;
  31. case '\"':
  32. ret = 1;
  33. break;
  34. default:
  35. ret = 0;
  36. break;
  37. }
  38. return ret;
  39. }
  40.  
  41. /*******************************************************************************
  42. *函数名:right
  43. *参数:char a 传进来的数组元素
  44. *返回值:int类型 如果是右侧符号,那么返回1,不是返回0
  45. *功能:判断传进来的字符是否是右侧字符
  46. *******************************************************************************/
  47. int right (char a)
  48. {
  49. int ret = 0;
  50. switch(a)
  51. {
  52. case '>':
  53. case ')':
  54. case ']':
  55. case '}':
  56. case '\'':
  57. case '\"':
  58. ret = 1;
  59. break;
  60. default:
  61. ret = 0;
  62. break;
  63. }
  64. return ret;
  65. }
  66.  
  67. /*******************************************************************************
  68. *函数名:right
  69. *参数:char a 传进来的数组元素
  70. *返回值:int类型 如果是右侧符号,那么返回1,不是返回0
  71. *功能:判断传进来的字符是否是右侧字符
  72. *******************************************************************************/
  73. int match(char bijiao, char a)
  74. {
  75. int ret = 0;
  76. int i = 0;
  77. switch(bijiao)
  78. {
  79. case '<':
  80. ret = (a == '>');
  81. break;
  82. case '(':
  83. ret = (a == ')');
  84. break;
  85. case '[':
  86. ret = (a == ']');
  87. break;
  88. case '{':
  89. ret = (a == '}');
  90. break;
  91. case '\'':
  92. ret = (a == '\'');
  93. break;
  94. case '\"':
  95. ret = (a == '\"');
  96. break;
  97. default:
  98. ret = 0;
  99. break;
  100. }
  101. return ret;
  102. }
  103.  
  104. /*******************************************************************************
  105. *函数名:scan
  106. *参数:char *a 传进来的字符数组元素的地址
  107. *返回值:int类型 如果是右侧符号,那么返回1,不是返回0
  108. *功能:符号匹配算法的主要实现部分
  109. *******************************************************************************/
  110. int scan (char *a)
  111. {
  112. LinkStack * stack = LinkStack_Create();
  113. int i = 0;
  114. int ret = 0;
  115.  
  116. while (a[i] != '\0')
  117. {
  118. if (left(a[i]) == 1)
  119. {
  120. LinkStack_Push(stack, (void*)(a + i));
  121. }
  122.  
  123. if (right(a[i]) == 1)
  124. {
  125. char* bijiao = (char*)LinkStack_Pop(stack);
  126. if ((bijiao == NULL) || !match(*bijiao, a[i]))
  127. {
  128. printf ("%c\n", a[i]);
  129. ret = 0;
  130. break;
  131. }
  132. }
  133. i++;
  134. }
  135.  
  136. if (LinkStack_Top(stack) == NULL && a[i] == '\0')
  137. {
  138. printf ("编译成功\n");
  139. }
  140. else
  141. {
  142. printf ("出现错误\n");
  143. }
  144. LinkStack_Destroy(stack);
  145.  
  146. return ret;
  147. }
  148.  
  149. int main()
  150. {
  151. 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]); } ";
  152. scan(a);
  153. return 0;
  154. }

C语言数据结构----栈的应用(程序的符号匹配检测)的更多相关文章

  1. C语言数据结构----栈与递归

    本节主要说程序中的栈函数栈的关系以及栈和递归算法的关系. 一.函数调用时的栈 1.程序调用时的栈是也就是平时所说的函数栈是数据结构的一种应用,函数调用栈一般是从搞地质向低地址增长的,栈顶为内存的低地址 ...

  2. C语言数据结构-栈的实现-初始化、销毁、长度、取栈顶元素、查找、入栈、出栈、显示操作

    1.数据结构-栈的实现-C语言 #define MAXSIZE 100 //栈的存储结构 typedef struct { int* base; //栈底指针 int* top; //栈顶指针 int ...

  3. 数据结构——栈的应用 NOI2.2 括号匹配问题

    栈是一种数据结构,相当于一个容器,将一个又一个变量从顶端压进去,需要使用时,又从顶端拿出来,其具体使用方法,下面是详细讲解: #include<stack>必须使用此头文件 stack&l ...

  4. C语言数据结构-栈

    一.栈的定义 栈(statck)这种数据结构在计算机中是相当出名的.栈中的数据是先进后出的(First In Last Out, FILO).栈只有一个出口,允许新增元素(只能在栈顶上增加). 移出元 ...

  5. C语言数据结构栈

    #include<stdio.h>#include<stdlib.h>typedef struct Node{ int data; struct Node* pnext;}no ...

  6. C语言数据结构----栈的定义及实现

    本节主要说的是数据结构中的栈的基本定义和实现的方式,其中实现的方式采用的是复用顺序表和单向链表的方式. 一.栈的基本定义 1.栈是一种特殊的线性表,只能从固定的方向进出,而且栈进出的基本原则是:先进栈 ...

  7. 栈的应用:表达式括号匹配检测(C)

    问题说明: 假设数学表达式中允许包含两种括号:圆括号"()"和方括号"[]",嵌套顺序任意. 正确的嵌套模式:( [ ] ( ) ).[ ( [ ] [ ] ) ...

  8. C语言数据结构之栈:中缀表达式的计算

    *注:本人技术不咋的,就是拿代码出来和大家看看,代码漏洞百出,完全没有优化,主要看气质,是吧 学了数据结构——栈,当然少不了习题.习题中最难的也是最有意思的就是这个中缀表达式的计算了(可以算+-*/和 ...

  9. 数据结构——栈(C语言实现)

    #include <stdio.h> #include <stdlib.h> #include<string.h> #include<malloc.h> ...

随机推荐

  1. codevs 1913 数字梯形问题 费用流

    题目链接 给你一个数字梯形, 最上面一层m个数字, 然后m+1,......m+n-1个. n是层数. 在每个位置, 可以向左下或右下走.然后让你从最顶端的m个数字开始, 走出m条路径, 使得路过的数 ...

  2. C99新特性

    c99标准允许使用变长数组,变的意思是可以根据变量的值来指定数组的维数,如根据用户的输入值指定数组的大小,印象中以前是不可以的.现在在gcc中是可以的(PS:ansi c标准是C90标准): ==== ...

  3. mysql排行榜sql的实现

    SELECT num_rows AS num_rows, openid , openid, money FROM lt_cash_user ) t ORDER BY money DESC ) t1 W ...

  4. hdu 2769 uva 12169 Disgruntled Judge 拓展欧几里德

    //数据是有多水 连 10^10的枚举都能过 关于拓展欧几里德:大概就是x1=y2,y1=x2-[a/b]y2,按这个规律递归到gcd(a,0)的形式,此时公因数为a,方程也变为a*x+0*y=gcd ...

  5. opennebula auth module ldap

    1,安装net-ldap  addon ruby library for openldap

  6. matlab 矩阵

    假设矩阵A=[1 3;4 2] 1.对角置零: A-diag(diag(A)) 2.求A的特征值以及特征向量: 用到eig(A)函数,此函数有五种用法,如下: 2.1 E=eig(A):求矩阵A的全部 ...

  7. poj1007 qsort快排

    这道题比较简单,但通过这个题我学会了使用c++内置的qsort函数用法,收获还是很大的! 首先简要介绍一下qsort函数. 1.它是快速排序,所以就是不稳定的.(不稳定意思就是张三.李四成绩都是90, ...

  8. Log4Net不生成日志文件

    可能没有初始化配置,在Global文件Application_Start添加 log4net.Config.XmlConfigurator.Configure(); 或者输出日志进行初始化,如(Log ...

  9. poj 2686 Traveling by Stagecoach ---状态压缩DP

    题意:给出一个简单带权无向图和起止点,以及若干张马车车票,每张车票可以雇到相应数量的马. 点 u, v 间有边时,从 u 到 v 或从 v 到 u 必须用且仅用一张车票,花费的时间为 w(u, v) ...

  10. jquery动态连接节点

    <1> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://w ...