数据结构实验报告

数据结构实验报告

学校:     武汉理工大学

学院:     计算机科学与技术学院

课程:     数据结构

姓名:     韩炜伟

班级:     计算机zy1302班

学号:     0121310870414

指导老师: 杨克俭

1、问题描述:.................................... 4

2、设计:........................................ 4

2.1存储结构设计:............................. 4

2.2、主要算法设计(用类C/C++语言或用框图描述): 6

2.3测试用例设计............................... 9

3、调试报告...................................... 9

4、 经验和体会(包括对算法改进的设想)........... 10

5、 附源程序清单和运行结果:..................... 10

5.1.源程序清单............................... 10

5.2.运行结果................................. 19

课内实践任务书

学生姓名:    韩炜伟              专业班级:  zy1302            

指导教师:杨克俭            工作单位:  计算机科学系   

题  目: 识别广义表的“头尾”                                     

初始条件:

      写一个程序,建立广义表的存储结构,演示在此存储结构上实现的广义表求头/求尾操作序列的结果。

(1)设一个广义表允许分多行输入,其中可以任意地输入空格符,原子是不限长的仅由字母或数字组成的串。

(2)广义表采用如教科书中图5.8所示结点的存储结构,试按表头和表尾的分解方法编写建立广义表存储结构的算法。

(3)对已建立存储结构的广义表施行操作,操作序列为一个仅由“t”(取表尾)或“h”(取表头)组成的串,它可以是空串(此时印出整个广义表),自左至右施行各种操作,再以符号形式显示结果。

测试用例见严蔚敏《数据结构习题集(C语言版)》p138。

要求完成的主要任务: (包括课内实践工作量及其技术要求,以及说明书撰写等具体要求)

课内实践报告按学校规定格式用A4纸打印(书写),并应包含如下内容:

1. 问题描述:简述题目要解决的问题是什么。

2. 设计:存储结构设计、主要算法设计(用类C/C++语言或用框图描述)、测试用例设计;

3. 调试报告:调试过程中遇到的问题是如何解决的;对设计和编码的讨论和分析。

4. 经验和体会(包括对算法改进的设想)

5. 附源程序清单和运行结果。源程序要加注释。如果题目规定了测试数据,则运行结果要包含这些测试数据和运行输出。

说明:

1. 设计报告、程序不得相互抄袭和拷贝;若有雷同,则所有雷同者成绩均为0分。

2. 凡拷贝往年任务书或课内实践充数者,成绩一律无效,以0分记。

时间安排:

1.第15周完成,验收时间为12月17日(星期三)上午

2.验收地点:实验中心

3.验收内容:可执行程序与源代码、课内实践报告书。

指导教师签名:                 20##年11月4日

系主任(或责任教师)签名:          年  月    日

  : 识别广义表的“头尾”

初始条件:

 写一个程序,建立广义表的存储结构,演示在此存储结构上实现的广义表求头/求尾操作序列的结果。

(1)设一个广义表允许分多行输入,其中可以任意地输入空格符,原子是不限长的仅由字母或数字组成的串。

(2)广义表采用如教科书中图5.8所示结点的存储结构,试按表头和表尾的分解方法编写建立广义表存储结构的算法。

(3)对已建立存储结构的广义表施行操作,操作序列为一个仅由“t”(取表尾)或“h”(取表头)组成的串,它可以是空串(此时印出整个广义表),自左至右施行各种操作,再以符号形式显示结果。

测试用例见严蔚敏《数据结构习题集(C语言版)》p138。

1、问题描述:

本课程设计主要完成对广义表的建立以及遍历(输出),并且对已建立的广义表实施操作,操作序列为一串由“t”、“h”以及“ ”组成的字符串。“t”表示对广义表求表尾,“h”表示对广义表求表头,“ ”表示遍历当前整个广义表。

2、设计:

2.1存储结构设计:

广义表的存储结构是采用的链式存储结构,每个数据元素、子表都可以用结点表示。由于列表中的数据元素可能为原子或列表,所以此程序需要三种结点:附加头结点、原子结点、子表。一个表结点可由三个域组成:标志域utype、info(ref、value、hlink)、tlink。

/*

广义表的结点定义

*/

template<class T>

struct GenListNode{

private:

       int utype; //标志域 结点种类标志

       union{  

              int ref; //附加头结点,引用次数  utype = 0

               T value; //元素值 utype = 1

               GenListNode<T> * hlink ; //子表表头的指针 utype = 2

       } info ; //信息域

       GenListNode<T> * tlink ; //尾指针域,指向同层下一节点的指针

public:

       GenListNode() :utype(0),tlink(NULL){ info.ref = 0; } //构造函数

       GenListNode(const GenListNode<T>& node){

              utype = node.utype;

              info = node.info;

              tlink = node.tlink;

       }

       template<class T> friend class GenList;

};

/*

广义表的类定义

*/

template<class T>

class GenList{

private:

       GenListNode<T> * first; //广义表头指针

       void  createGenList(istream&  in, GenListNode<T>* first, SeqList<char>& genListNames, SeqList<GenListNode<T> *>& genListNodePtrs); //创建广义表的存储结构

       void read(char& ch, istream& in); //用于读取一个字符到ch中,忽略空串

public:

       GenList();

       ~GenList(){};

       GenList<T>* getHead() ;  //拿到表头

       GenList<T>* getTailList() ;  //拿到表尾

       static void print(GenListNode<T>* node);  //单独打印结点

       static void printHead(GenList<T>* list);   //打印表头

       static void printTail(GenListNode<T>* node); //打印表尾

       static void printAll(GenListNode<T>* node); //从附加头节点之后的第一个节点开始打印整个表

       static void printList(GenList<T>* list);   //打印整个表

       static void printNode(GenListNode<T>* node);

       GenListNode<T>* copyNode( GenListNode<T>* node);

       friend istream& operator>>(istream& in, GenList<T>& GL){ //输入广义表

              cout << "请出入表达式,如:A(B(a,b),c);\n";

              char ch;

              GL.read(ch,in);

              if (!(ch <= 'Z'&&ch >= 'A'))

              {

                     cerr << "输入格式不合法,第一个是大写\n";

                     throw runtime_error("输入格式不合法,第一个是大写\n");

              }

              SeqList<char> genListNames;   //存放表名

              genListNames.add(ch);   //将总表的表名加入到genListNames中

              SeqList<GenListNode<T> *> genListNodePtrs;  //存放表的附加头结点指针

              genListNodePtrs.add(GL.first); //将总表的附加头结点指针加入genListNodePtrs

              GL.createGenList(in, GL.first, genListNames, genListNodePtrs);

              return in;

       }

};

2.2、主要算法设计(用类C/C++语言或用框图描述):

程序主体主要由3个函数组成:

1.创建广义表

void  createGenList(istream&  in, GenListNode<T>* first, SeqList<char>& genListNames, SeqList<GenListNode<T> *>& genListNodePtrs){

      

        //初始化表的附加头节点

       first->utype = 0;  //附加头结点

       first->info.ref = 0; //引用计数初始化为0

       char ch ;

       //1.表的开始一定是‘(’

       read(ch, in);

       if (ch != '(')

       {

              cerr << "ch != (";

              cerr << "输入格式不合法\n";

              throw runtime_error("输入格式不合法");

              return;

       }

       //2.判表空否

       read(ch, in);

       if (ch=='#')  //2.1表为空,直接将尾指针域赋为NULL

       {

              first->tlink = NULL;

              read(ch,in);

              if (ch != ')')  //‘#’后一定是‘)’才对

              {

                     cerr << "ch != )";

                     cerr << "输入格式不合法\n";

                     throw runtime_error("输入格式不合法");

                     return;

              }

       }

       else       //2.2表不为空

       {

              GenListNode<T> * ptr = first;  //动态指针,链接表元素的时候使用

              if ( !(ch <= 'z'&&ch >= 'a') && !(ch<='Z'&&ch>='A')) //若有元素,必//须为大写字母或小写字母

              {

                     cerr << "输入格式不合法\n";

                     throw runtime_error("输入格式不合法");

                     return;

              }

              while (ch!=')') //遇到 ‘)’时,表结束

              {

                     if (ch <= 'z'&&ch >= 'a') //小写字母说明是原子节点,存的是元素值

                     {

                            GenListNode<T> * temp = new GenListNode<T>; //新建节点

                            temp->utype = 1;   //原子节点 设置标志域

                            temp->info.value = ch;  //将值赋为ch

                            ptr->tlink = temp; //链接节点

                            ptr = ptr->tlink; //指针右移一位

                     }

                     if (ch <= 'Z'&&ch >= 'A')//大写字母说明是子表,存的是子表附加头//结点

                     {

                            GenListNode<T> * newNode;  //用来存放子表的附加头结点指针

                            int index;

                            if ((index = genListNames.indexOf(ch)) != -1){ //子表表名存//在,说明是共享表

                                   newNode = genListNodePtrs.getData(index); //newNode置为//共享表附加头结点指针

                                   newNode->info.ref++;

                            }

                            else{     //子表不是共享表,就需新创建子表                 

                                   newNode = new GenListNode<T>; 

                                   createGenList(in, newNode, genListNames, genListNodePtrs); //递归创建字表,返回子表的头指针

                                   genListNames.add(ch);  //将此表名加入表名List中

                                   genListNodePtrs.add(newNode); //子表的附加头结点指针加//入

                            }

                            GenListNode<T> * temp = new GenListNode<T>; //新建同级节点

                            temp->utype = 2;   //子表 设置标志域

                            temp->info.hlink = newNode;  //将值赋为子表头指针

                            ptr->tlink = temp; //链接节点

                            ptr = ptr->tlink; //指针右移一位

                     }

                     read(ch, in);

                     if (ch == ','){  //判断后面一个是否为 ‘,’

                            read(ch, in);

                            continue;   //是‘,’读取一个字符,继续往后走

                     }

                     else if (ch != ')'){ //不是‘,’的话,判断是否是‘)’

                            cerr << "输入格式不合法\n";  //不是的话说明不合法,因为表的//结尾必须是‘)’

                            throw runtime_error("输入格式不合法");

                            return;

                     }

              }

       }

}

广义表是采用递归方式定义的,所以创建广义表也是根据递归实现的。大写字母代表表名,小写字母代表元素。建表时还应分清是否为共享表。

 2.取表头

GenList<T>* GenList<T>::getHead(){

       GenListNode<T> *newNode = new GenListNode<T>(*(first->tlink));

       if (first->tlink != NULL){

              newNode->tlink = NULL;

       }

       GenList<T> *newList = new GenList<T>();

       if (newNode->utype == 1){

              newList->first->tlink = copyNode(newNode);

       }

       else if (newNode->utype == 2){

              newList->first = copyNode(newNode->info.hlink);

       }

      return newList;  //表头的节点

}

这里取表头过程中要复制结点,而复制结点也采用了递归的思想。

   3.取表尾

GenList<T>* GenList<T>::getTailList() {

       if (first->tlink!=NULL&&first->tlink->tlink!=NULL)

       {

              GenListNode<T> *newNode = first->tlink->tlink;

              GenList<T> *tailList = new GenList<T>();

              tailList->first->tlink = copyNode(newNode);

              return tailList; //表尾的节点

       }

       return NULL;

}

这里取表尾过程中要复制结点,而复制结点也采用了递归的思想。

2.3测试用例设计

输入:A(B(b,c,d),E(e));  hh

输入:A(B(#),E(D(a,b),c));  th

输入:A(a,b,B(C(a,b),c),d,e);  th

3、调试报告

调试过程中遇到的问题:

1.

错误: 在没有操作序列的情况下,提示字符不合法。

原因: 是因为创建广义表的时候,是以最后一个‘)’作为结束标志的,而‘)’后多余一个‘;’。

解决办法:使用fflush(stdin)清空输入流的缓存

2.

错误:

在创建广义表的过程中,由于考虑因素太多以及涉及递归调用,造成调用栈太深。当用户输入不合法时,给出友好提示后,本来是用return跳出广义表的创建,但只跳出了部分的调用栈,程序还继续运行造成出错。

解决办法:使用抛异常的方法往外抛异常,在main函数中将异常捕获并处理。

3.

错误:指针混乱,程序突然运行异常

原因:空指针或者内存空间未分配。

解决办法:①代码分块,打印日志

          ②使用visual studio的断点调试功能,逐步运行,找出问题代码。

4、 经验和体会(包括对算法改进的设想)

在此次的课程设计之前,我对广义表的内容了解的比较模糊。经过此次课程设计,对于广义表的存储结构以及求头尾操作,我有了较深的理解。广义表的用途十分广泛,因此要求了广义表的灵活性。广义表的存储结构是链式的,且类似于二叉树,广义表与二叉树的表头结点均有两个指针,但是二叉树的指针是自上而下的联系,而广义表中的尾指针是指向同层结点,因此有横向的联系,这点上与二叉树不同。对广义表的求头尾操作中要注意:广义表的表头是广义表中的第一个元素,而广义表的表尾是除第一个元素外其他元素组成的表。即广义表的表尾一定是广义表,而表头是否为广义表,取决于第一个元素的类型。在本次课程设计中,遇到最多的就是空指针和野指针问题,经过不断地调试,最终都能解决。但是,代码的结构还是有些许混乱,耦合度较高,程序之间依赖性大。

算法的改进的设想:广义表的创建过分依赖递归算法,造成调用栈十分深,如果子表嵌套太深会导致栈溢出的后果。在这里,我设想:我们可以去将递归算法改为自定义栈,来提高程序的稳定性。

5、 附源程序清单和运行结果:

5.1.源程序清单

//广义表的类声明

#ifndef GENLIST_H

#define GENLIST_H

#include<iostream>

#include"SeqList.h"

using namespace std;

//返回值的类结构定义

template<class T>

struct Item

{

       int utype;

       union info

       {

              int ref; //附加头结点,引用次数  utype = 0

              T value;//元素值 utype = 1

              //GenListNode<T>  * hlink; //子表表头的指针 utype = 2

       };

       Item() :utype(0), info.ref(0){}//初始化为空表附加头结点,引用计数0

       Item(Item<T> &RL){    //复制构造函数

      

              utype = RL.utype;

              info = RL.info;

       }

};

/*

广义表的结点定义

*/

template<class T>

struct GenListNode{

private:

       int utype; //标志域 结点种类标志

       union{  

              int ref; //附加头结点,引用次数  utype = 0

               T value; //元素值 utype = 1

               GenListNode<T> * hlink ; //子表表头的指针 utype = 2

       } info ; //信息域

       GenListNode<T> * tlink ; //尾指针域,指向同层下一节点的指针

public:

       GenListNode() :utype(0),tlink(NULL){ info.ref = 0; } //构造函数

       GenListNode(const GenListNode<T>& node){

              utype = node.utype;

              info = node.info;

              tlink = node.tlink;

       }

       template<class T> friend class GenList;

};

/*

广义表的类定义

*/

template<class T>

class GenList{

private:

       GenListNode<T> * first; //广义表头指针

       void  createGenList(istream&  in, GenListNode<T>* first, SeqList<char>& genListNames, SeqList<GenListNode<T> *>& genListNodePtrs); //创建广义表的存储结构

       void read(char& ch, istream& in); //用于读取一个字符到ch中,忽略空串

public:

       GenList();

       ~GenList(){};

       GenList<T>* getHead() ;  //拿到表头

       GenList<T>* getTailList() ;  //拿到表尾

       static void print(GenListNode<T>* node);  //单独打印结点

       static void printHead(GenList<T>* list);   //打印表头

       static void printTail(GenListNode<T>* node); //打印表尾

       static void printAll(GenListNode<T>* node); //从附加头节点之后的第一个节点开始打印整个表

       static void printList(GenList<T>* list);   //打印整个表

       static void printNode(GenListNode<T>* node);

       GenListNode<T>* copyNode( GenListNode<T>* node);

       friend istream& operator>>(istream& in, GenList<T>& GL){ //输入广义表

              cout << "请出入表达式,如:A(B(a,b),c);\n";

              char ch;

              GL.read(ch,in);

              if (!(ch <= 'Z'&&ch >= 'A'))

              {

                     cerr << "输入格式不合法,第一个是大写\n";

                     throw runtime_error("输入格式不合法,第一个是大写\n");

              }

              SeqList<char> genListNames;   //存放表名

              genListNames.add(ch);   //将总表的表名加入到genListNames中

              SeqList<GenListNode<T> *> genListNodePtrs;  //存放表的附加头结点指针

              genListNodePtrs.add(GL.first); //将总表的附加头结点指针加入genListNodePtrs

              GL.createGenList(in, GL.first, genListNames, genListNodePtrs);

              return in;

       }

};

template<class T>

GenList<T>::GenList(){

       first = new GenListNode<T>;

       assert(first!=NULL);

}

template<class T>

void GenList<T>::read(char& ch, istream& in){

       in.get(ch);

       while (1)

       {

              if (ch == ' '||ch=='\n')

                     in.get(ch);

              else

                     break;

       }

}

/*

创建字表,传递待创建字表的附加头结点给first

*/

template<class T>

void GenList<T>::createGenList(istream&  in, GenListNode<T>* first, SeqList<char>& genListNames, SeqList<GenListNode<T> *>& genListNodePtrs){

      

        //初始化表的附加头节点

       first->utype = 0;  //附加头结点

       first->info.ref = 0; //引用计数初始化为0

       char ch ;

       //1.表的开始一定是‘(’

       read(ch, in);

       if (ch != '(')

       {

              cerr << "ch != (";

              cerr << "输入格式不合法\n";

              throw runtime_error("输入格式不合法");

              return;

       }

       //2.判表空否

       read(ch, in);

       if (ch=='#')  //2.1表为空,直接将尾指针域赋为NULL

       {

              first->tlink = NULL;

              read(ch,in);

              if (ch != ')')  //‘#’后一定是‘)’才对

              {

                     cerr << "ch != )";

                     cerr << "输入格式不合法\n";

                     throw runtime_error("输入格式不合法");

                     return;

              }

       }

       else       //2.2表不为空

       {

              GenListNode<T> * ptr = first;  //动态指针,链接表元素的时候使用

              if ( !(ch <= 'z'&&ch >= 'a') && !(ch<='Z'&&ch>='A')) //若有元素,必须为大写字母或小写字母

              {

                     cerr << "输入格式不合法\n";

                     throw runtime_error("输入格式不合法");

                     return;

              }

              while (ch!=')') //遇到 ‘)’时,表结束

              {

                     if (ch <= 'z'&&ch >= 'a') //小写字母说明是原子节点,存的是元素值

                     {

                            GenListNode<T> * temp = new GenListNode<T>; //新建节点

                            temp->utype = 1;   //原子节点 设置标志域

                            temp->info.value = ch;  //将值赋为ch

                            ptr->tlink = temp; //链接节点

                            ptr = ptr->tlink; //指针右移一位

                     }

                     if (ch <= 'Z'&&ch >= 'A')//大写字母说明是子表,存的是子表附加头结点

                     {

                            GenListNode<T> * newNode;  //用来存放子表的附加头结点指针

                            int index;

                            if ((index = genListNames.indexOf(ch)) != -1){ //子表表名存在,说明是共享表

                                   newNode = genListNodePtrs.getData(index); //newNode置为共享表附加头结点指针

                                   newNode->info.ref++;

                            }

                            else{     //子表不是共享表,就需新创建子表                 

                                   newNode = new GenListNode<T>; 

                                   createGenList(in, newNode, genListNames, genListNodePtrs); //递归创建字表,返回子表的头指针

                                   genListNames.add(ch);  //将此表名加入表名List中

                                   genListNodePtrs.add(newNode); //子表的附加头结点指针加入

                            }

                            GenListNode<T> * temp = new GenListNode<T>; //新建同级节点

                            temp->utype = 2;   //子表 设置标志域

                            temp->info.hlink = newNode;  //将值赋为子表头指针

                            ptr->tlink = temp; //链接节点

                            ptr = ptr->tlink; //指针右移一位

                     }

                     read(ch, in);

                     if (ch == ','){  //判断后面一个是否为 ‘,’

                            read(ch, in);

                            continue;   //是‘,’读取一个字符,继续往后走

                     }

                     else if (ch != ')'){ //不是‘,’的话,判断是否是‘)’

                            cerr << "输入格式不合法\n";  //不是的话说明不合法,因为表的结尾必须是‘)’

                            throw runtime_error("输入格式不合法");

                            return;

                     }

              }

       }

}

template<class T>

GenListNode<T>* GenList<T>::copyNode( GenListNode<T>* node){

       if (node == NULL)

              return NULL;

       else{

              GenListNode<T> *head = NULL;

              GenListNode<T> *newNode =NULL;

              GenListNode<T> *ptr = node;

              GenListNode<T> *ptr1 = NULL;

              while (ptr!=NULL)

              {

                     switch (node->utype)

                     {

                            case 0:

                                   newNode = new GenListNode<T>(*ptr);

                                   break;

                           

                            case 1:

                                   newNode = new GenListNode<T>(*ptr);

                                   break;

                            case 2:

                                   newNode = new GenListNode<T>(*ptr);

                                   newNode->info.hlink = copyNode(newNode->info.hlink);

                                   break;

                     }

                     if (head == NULL){

                            ptr1 = head = newNode;

                     }

                     else{

                            ptr1->tlink = newNode;

                            ptr1 = ptr1->tlink;

                     }

                     ptr = ptr->tlink;

              }

              return head;

       }

}

template <class T>

GenList<T>* GenList<T>::getHead(){

       GenListNode<T> *newNode = new GenListNode<T>(*(first->tlink));

       if (first->tlink != NULL){

              newNode->tlink = NULL;

       }

       GenList<T> *newList = new GenList<T>();

       if (newNode->utype == 1){

              newList->first->tlink = copyNode(newNode);

       }

       else if (newNode->utype == 2){

              newList->first = copyNode(newNode->info.hlink);

       }

      return newList;  //表头的节点

}

template <class T>

GenList<T>* GenList<T>::getTailList() {

       if (first->tlink!=NULL&&first->tlink->tlink!=NULL)

       {

              GenListNode<T> *newNode = first->tlink->tlink;

              GenList<T> *tailList = new GenList<T>();

              tailList->first->tlink = copyNode(newNode);

              return tailList; //表尾的节点

       }

       return NULL;

}

template<class T>

void GenList<T>::printHead(GenList<T>* list){

       if (list->first->tlink->tlink!=NULL)

       {

              printList(list);

       }

       else{

              print(list->first->tlink);

       }

}

template<class T>

void GenList<T>::printList(GenList<T>* list){

       if (list == NULL)

       {

              cout << "空表\n";

              return;

       }

       printNode(list->first->tlink); //打印表,即打印表的头节点的下个节点,然后递归打印

}

template<class T>

void GenList<T>::printNode(GenListNode<T>* node){

       if (node == NULL){

              cout << "()";  //表为空

       }

       else{

              cout << "(";  //这里方便打印,表不是空

              print(node);

              cout << ")";

       }

       cout << "\n\n";

}

template<class T>

void GenList<T>::print(GenListNode<T>* node){

       if (node->utype == 1){

              cout << node->info.value;

       }

       else if (node->utype == 2)

       {

              GenListNode<T> * temp = node->info.hlink->tlink; //子表的附加头结点的下一个节点,即子表的第一个元素节点

              cout << "(";

              if (temp != NULL)

                     print(temp);

              cout << ")";

       }

       GenListNode<T> * temp = node->tlink;

       if (temp != NULL){

              cout << ",";

              print(temp);

       }

}

#endif

#include"GenList.h"

//便于跳过换行和空格读取字符

void read(istream& in,char &ch){

       in.get(ch);

       while (1)

       {

              if (ch == '\n')

                     in.get(ch);

              else

                     break;

       }

}

int main(){

       char ch;

       while (true)

       {

              GenList<char> *genList = new GenList<char>();

              try{

                     cin >> *genList;

                     fflush(stdin);   //清空输入流的缓存

                     cout << "请选择:\n";

                     cout << "h 输出表头  t 输出表尾 空格 输出整个表 c 重新建表  e 退出\n";

                     while (true)

                     {

                            //cout << "请选择:\n";

                            //cout << "h 输出表头  t 输出表尾 空格 输出整个表 c 重新建表  e 退出\n";

                            read(cin, ch);

                            if (ch == 'h')

                            {

                                   cout << "Head:\n";

                                   if (genList == NULL){

                                          cout << "已经是空表了\n";

                                          break;

                                   }

                                   genList = genList->getHead();  //取表头

                                   GenList<char>::printHead(genList);

                                   cout << endl;//打印表头

                            }

                            else if (ch == 't')

                            {

                                   cout << "Tail:\n";

                                   if (genList == NULL){

                                          cout << "已经是空表了\n";

                                          break;

                                   }

                                   genList = genList->getTailList();//取表尾

                                   GenList<char>::printList(genList);//打印表尾

                                   cout << endl;

                            }

                            else if (ch == ' ')

                            {

                                   cout << "All:\n";

                                   GenList<char>::printList(genList);

                                   cout << endl;//空字符,打印全表

                            }

                            else if (ch == 'c')   //重新建表

                            {

                                   break;

                            }

                            else if (ch == 'e')  //退出

                            {

                                   exit(0);

                            }

                            else if (ch != '\n') //输入不合法

                            {

                                   cout << "输入不合法\n";

                                   continue;

                            }

                     }

              }

              catch (runtime_error err){

                     continue;

              }

       }

       system("pause");

       return 0;

}

5.2.运行结果

输入:A(B(b,c,d),E(e));  hh

输入:A(B(#),E(D(a,b),c));  th()  ()代表空字符

输入:A(a,b,B(C(a,b),c),d,e);  th()        ()代表空字符

相关推荐