魔王语言解释
问题描述
有一个魔王总是使用自己的一种非常精练而抽象的语言讲话,没有人能听懂,但他的语言是可以逐步解释成人能听懂的语言,因为他的语言是由以下两种形式的规则由人的语言逐步抽象上去的:
(
1)α->β1β2……βm
(
2)(θδ1δ2……δn)—>θδnθδn-1……θδ1θ
在这两种形式中,从左到右均表示解释。试写一个魔王语言的解释系统,把他的话解释成人能听得懂的话;
基本要求
用下述两条具体规则和上述规则形式(
2)实现。设大写字母表示魔王语言的词汇;小写字母表示人的语言词汇;希腊字母表示可以用大写字母或小写字母代换的变量。魔王语言可含人的词汇。
(
1)B->tAdA
(
2)A->sae
测试数据
B(
ehnxgz)B解释成tsaedsaeezegexenehetsaedsae
若将小写字母与汉字建立下表所示的对应关系,则魔王说的话是:“天上一只鹅地上一只鹅追鹅赶鹅下鹅蛋鹅恨鹅天上一只鹅地上一只鹅”。
t
|
d
|
s
|
a
|
e
|
z
|
g
|
x
|
n
|
h
|
天
|
地
|
上
|
一只
|
鹅
|
追
|
赶
|
下
|
蛋
|
恨
|
实现提示
将魔王的语言自右至左进栈,总是处理栈顶字符。若是开括号,则逐一出栈,将字母顺序入队列,直至闭括号出栈,并按规则要求逐一出队列再处理后入栈。其他情形较简单,请读者思考应如何处理。应首先实现栈和队列的基本操作。
选作内容
(
1)由于问题的特殊性,可以实现栈和队列的顺序存储空间共享。
(
2)代换变量的数目不限,则在程序开始运行时首先读入一组第一种形式的规则,而不是把规则固定在程序中(第二种形式的规则只能固定在程序中)。
这道题目主要考察栈和队列的使用。实现同题目中的实现提示相仿。重要数据结构包括一个栈和一个辅助队列,一张记录大写字母处理规则的表以及记录闭合左括号对应的括号表达式的表。处理方法是从左至右依次读入待翻译的字符串,根据读入字符做出不同操作。如果读到小写字母,如果当前栈中压入的左括号数目为0,则直接输出,否则入栈;如果读到大写字母,如果当前栈中压入的左括号数目为0,则输出大写字母对应的规则,否则入栈;如果读到左括号,记下在串中的位置,然后入栈;如果读到右括号,则依次弹出栈中的元素并将这些元素加入辅助队列,直到弹出左括号为止。如果当前栈中压入的左括号数目为0,则根据括号内表达式处理规则将队列中存放的从栈中弹出的元素输出,否则将这些元素加入对应左括号位置的表项中进行记录,并生成记录左括号位置的元素然后压栈。最后处理完毕后,翻译后的串输出并且队列和栈中为空。
栈中元素的数据结构定义为:
//OPEN_BRACKET表示左括号还没有与对应的右括号进行合并
//CLOSE_BRACKET表示左括号已与对应的右括号进行合并
enum CharType{LOWERLETTER,CAPITAL,OPEN_BRACKET,CLOSE_BRACKET};
struct HElement
{
{
CharType type;
//type = LOWERLETTER以及CAPITAL,pos的值为字符与'a'或'A'的差
//type = OPEN_BRACKET以及CLOSE_BRACKET,pos的值为左括号在待翻译字符串中的位置
int pos;
};
};
//闭合左括号括号表达式表项的数据结构定义为:
struct PElement
{
{
//括号表达式的符号序列
vector<struct HElement> seq;
};
vector<struct HElement> seq;
};
以下是实现的源程序,栈和队列采用的是STL中的stack和deque,MAXSTRLENGTH 定义输入翻译字符串的最长长度。
#include <vector>
#include <stack>
#include <deque>
#include <fstream>
using namespace std;
#include <string.h>
#define MAXSTRLENGTH 10000
enum CharType{LOWERLETTER,CAPITAL,OPEN_BRACKET,CLOSE_BRACKET};
struct HElement
{
CharType type;
int pos;
};
struct PElement
{
//括号表达式符号序列
//(AB[1]B[2]..B[n])
vector seq;
};
class Translator
{
public:
Translator()
{}
~Translator()
{}
bool init(const char *filename)
{
char regBuf[MAXSTRLENGTH];
ifstream ifs(filename);
if(ifs.fail())
return false;
char c;
while(!ifs.eof())
{
ifs>>c>>regBuf;
strncpy(&T[c-'A'][0],regBuf,MAXSTRLENGTH-1);
T[c-'A'][MAXSTRLENGTH-1] = '/0';
}
return true;
}
//输出翻译后的字符串
//@param oriStr: 待翻译的字符串
void translate(const char* oriStr)
{
int i;
int length = oriStr ? strlen(oriStr):0;
int cnt = 0;
for(i=0;i='a'&&c<='z')
{
if(cnt == 0)
{
//栈中左括号的数目为0
printf("%c",c);
}
else
{
struct HElement elem;
elem.pos = c-'a';
elem.type = LOWERLETTER;
S.push(elem);
}
}
else if(c>='A'&&c<='Z')
{
if(cnt == 0)
{
//栈中左括号的数目为0
printRegulation(c);
}
else
{
struct HElement elem;
elem.pos = c - 'A';
elem.type = CAPITAL;
S.push(elem);
}
}else if(c == '(')
{
struct HElement elem;
elem.pos = i;
elem.type = OPEN_BRACKET;
S.push(elem);
cnt++;
}else if(c == ')')
{
//弹出栈顶元素并加入辅助队列,直到弹出'('
struct HElement* firstElem = NULL;
int bracketPos = -1;
while(!S.empty())
{
struct HElement& hElem = S.top();
if(hElem.type == OPEN_BRACKET)
{
//弹出'('
bracketPos = hElem.pos;
cnt--;
S.pop();
break;
}
firstElem = &hElem;
Q.push_back(hElem);
S.pop();
}
if(firstElem != NULL && bracketPos != -1)
{
if(cnt == 0)
{
//栈中左括号的数目为0
//输出括号中的符号序列
//(AB[1]B[2]B[3]..B[n])->(AB[n]B[n-1]...B[2]B[1])
struct HElement& elemRef = Q.back();
while(Q.size() > 0)
{
printHElement(elemRef);
if(Q.size() > 1)
{
printHElement(Q.front());
}
Q.pop_front();
}
}
else
{
while(!Q.empty())
{
//在P表中记录括号表达式的符号序列
//bracketPos为闭合左括号在原串中的位置
P[bracketPos].seq.push_back(Q.front());
Q.pop_front();
}
//在栈中记录闭合左括号的位置
struct HElement elem;
elem.pos = bracketPos;
elem.type = CLOSE_BRACKET;
S.push(elem);
}
}
}
}
}
protected:
stack S;
deque Q;
char T['Z'-'A'+1][MAXSTRLENGTH];
PElement P[MAXSTRLENGTH];
void printHElement(const HElement& elem)
{
if(elem.type == LOWERLETTER)
{
printRegulation(elem.pos + 'a');
}
else if(elem.type == CAPITAL)
{
printRegulation(elem.pos + 'A');
}
else if(elem.type == CLOSE_BRACKET)
{
printBracketExpression(elem.pos);
}
}
void printRegulation(char R)
{
if(R>='a'&&R<='z')
{
printf("%c",R);
}
else if(R>='A'&&R<='Z')
{
int pos = R - 'A';
char *regulationStr = &T[pos][0];
int length = strlen(regulationStr);
for(int i=0;i 0)
{
lastElem = &elem.seq.back();
}
for(int i = 0; i < elem.seq.size();i++)
{
struct HElement& hElem = elem.seq[i];
printHElement(*lastElem);
if(i < elem.seq.size() - 1)
{
printHElement(hElem);
}
}
}
};
int main(int argc,char **argv)
{
char *regFile;
if(argc > 1)
{
regFile = argv[1];
}
else
{
regFile = "regFile.txt";
}
char *langFile;
if(argc > 2)
{
langFile = argv[2];
}
else
{
langFile = "langFile.txt";
}
Translator t;
if(t.init(regFile))
{
char langBuf[MAXSTRLENGTH];
ifstream ifs(langFile);
if(!ifs.fail())
{
while(!ifs.eof())
{
ifs.getline(langBuf,sizeof(langBuf));
t.translate(langBuf);
printf("/n");
}
}
}
return 0;
}
#include <stack>
#include <deque>
#include <fstream>
using namespace std;
#include <string.h>
#define MAXSTRLENGTH 10000
enum CharType{LOWERLETTER,CAPITAL,OPEN_BRACKET,CLOSE_BRACKET};
struct HElement
{
CharType type;
int pos;
};
struct PElement
{
//括号表达式符号序列
//(AB[1]B[2]..B[n])
vector seq;
};
class Translator
{
public:
Translator()
{}
~Translator()
{}
bool init(const char *filename)
{
char regBuf[MAXSTRLENGTH];
ifstream ifs(filename);
if(ifs.fail())
return false;
char c;
while(!ifs.eof())
{
ifs>>c>>regBuf;
strncpy(&T[c-'A'][0],regBuf,MAXSTRLENGTH-1);
T[c-'A'][MAXSTRLENGTH-1] = '/0';
}
return true;
}
//输出翻译后的字符串
//@param oriStr: 待翻译的字符串
void translate(const char* oriStr)
{
int i;
int length = oriStr ? strlen(oriStr):0;
int cnt = 0;
for(i=0;i='a'&&c<='z')
{
if(cnt == 0)
{
//栈中左括号的数目为0
printf("%c",c);
}
else
{
struct HElement elem;
elem.pos = c-'a';
elem.type = LOWERLETTER;
S.push(elem);
}
}
else if(c>='A'&&c<='Z')
{
if(cnt == 0)
{
//栈中左括号的数目为0
printRegulation(c);
}
else
{
struct HElement elem;
elem.pos = c - 'A';
elem.type = CAPITAL;
S.push(elem);
}
}else if(c == '(')
{
struct HElement elem;
elem.pos = i;
elem.type = OPEN_BRACKET;
S.push(elem);
cnt++;
}else if(c == ')')
{
//弹出栈顶元素并加入辅助队列,直到弹出'('
struct HElement* firstElem = NULL;
int bracketPos = -1;
while(!S.empty())
{
struct HElement& hElem = S.top();
if(hElem.type == OPEN_BRACKET)
{
//弹出'('
bracketPos = hElem.pos;
cnt--;
S.pop();
break;
}
firstElem = &hElem;
Q.push_back(hElem);
S.pop();
}
if(firstElem != NULL && bracketPos != -1)
{
if(cnt == 0)
{
//栈中左括号的数目为0
//输出括号中的符号序列
//(AB[1]B[2]B[3]..B[n])->(AB[n]B[n-1]...B[2]B[1])
struct HElement& elemRef = Q.back();
while(Q.size() > 0)
{
printHElement(elemRef);
if(Q.size() > 1)
{
printHElement(Q.front());
}
Q.pop_front();
}
}
else
{
while(!Q.empty())
{
//在P表中记录括号表达式的符号序列
//bracketPos为闭合左括号在原串中的位置
P[bracketPos].seq.push_back(Q.front());
Q.pop_front();
}
//在栈中记录闭合左括号的位置
struct HElement elem;
elem.pos = bracketPos;
elem.type = CLOSE_BRACKET;
S.push(elem);
}
}
}
}
}
protected:
stack S;
deque Q;
char T['Z'-'A'+1][MAXSTRLENGTH];
PElement P[MAXSTRLENGTH];
void printHElement(const HElement& elem)
{
if(elem.type == LOWERLETTER)
{
printRegulation(elem.pos + 'a');
}
else if(elem.type == CAPITAL)
{
printRegulation(elem.pos + 'A');
}
else if(elem.type == CLOSE_BRACKET)
{
printBracketExpression(elem.pos);
}
}
void printRegulation(char R)
{
if(R>='a'&&R<='z')
{
printf("%c",R);
}
else if(R>='A'&&R<='Z')
{
int pos = R - 'A';
char *regulationStr = &T[pos][0];
int length = strlen(regulationStr);
for(int i=0;i 0)
{
lastElem = &elem.seq.back();
}
for(int i = 0; i < elem.seq.size();i++)
{
struct HElement& hElem = elem.seq[i];
printHElement(*lastElem);
if(i < elem.seq.size() - 1)
{
printHElement(hElem);
}
}
}
};
int main(int argc,char **argv)
{
char *regFile;
if(argc > 1)
{
regFile = argv[1];
}
else
{
regFile = "regFile.txt";
}
char *langFile;
if(argc > 2)
{
langFile = argv[2];
}
else
{
langFile = "langFile.txt";
}
Translator t;
if(t.init(regFile))
{
char langBuf[MAXSTRLENGTH];
ifstream ifs(langFile);
if(!ifs.fail())
{
while(!ifs.eof())
{
ifs.getline(langBuf,sizeof(langBuf));
t.translate(langBuf);
printf("/n");
}
}
}
return 0;
}
用过的测试数据:
规则文件:
B tAdA
A sae
A sae
未翻译字符串文件:
((B(ehn(xgz)))((B)))
BexzxgxeneheBBBexzxgxeneheB
BexzxgxeneheBBBexzxgxeneheB
B(
ehnxgz)B
BezegexeneheB