题目:对于任意给定的一台Turing机和任意给定的字符串w ( w不含空格),编程模拟此Turing机的运行过程,要求输出从开始运行起的每一步骤的结果。
- 题目分析
用C++模拟一个XN*2的图灵机,输入一个正整数,将其转化为它的二进制数,并将它转化为图灵机的二进制编码(其中0->0,1->10,逗号(,)->110)然后将运算指令编译上去会输出这个数乘以2之后的拓展二进制码,定义一个state变量用来存放内态,用if-else if-else判断内态和输入,然后进行输出和内态的改变,得到拓展二进制编码后进行收缩并转化为十进制,输出最终结果。
二、算法构造
- 输入一个正整数,通过调用transform()函数将其转化为二进制。
- 将二进制转化为图灵机二进制编码。其中用到int,string及字符串数组之间的互相转化,string_replace()字符串的替换等函数。
- 二进制数据扩展,在扩展的二进位上实现该图灵机的运算指令,指令如下:
00→00R,01→10R选,10→01R,11→100R,100→111R,110→01STOP。将图灵机二进制编码收缩,并将其转化为十进制输出。
三、算法实现(源代码)
#include<iostream>
#include<stdlib.h>
#include <cstring>
#include<math.h>
#include <sstream>
using namespace std;
int transfrom(int x) //将十进制转化为二进制
{
int p=1,y=0,m;
while(1)
{
m=x%2;
x/=2;
y+=m*p;
p*=10;
if(x<2)
{
y+=x*p;
break;
}
}
return y;
}
void string_replace(std::string &strBig, const std::string &strsrc, const std::string &strdst) //字符串替换函数,通过查资料得到
{
std::string::size_type pos=0;
std::string::size_type srclen=strsrc.size();
std::string::size_type dstlen=strdst.size();
while( (pos=strBig.find(strsrc, pos)) != std::string::npos)
{
strBig.replace(pos, srclen, strdst);
pos += dstlen;
}
}
void main()
{
int m,t1;
cout<<"请输入一个正整数:"<<endl;
cin>>m;
t1=transfrom(m); //调用transform()函数
ostringstream myos; //将int型转化为字符串型
myos<<t1;
string s=myos.str();
cout<<s<<endl;
string b=","; //定义字符串变量b
s.append(b); //在字符串末尾处添加","
cout<<"该数字对应的二进制数为:"<<s<<endl;
string_replace(s,"1","01"); //调用string_replace函数,用“01”代替“1”
string_replace(s,",","0110");//调用string_replace函数,用“0110”代替“,”
string_replace(s,"0","0"); //调用string_replace函数,用“0”代替“0”,此步骤可以省略
cout<<"对应的二进制编码为:"<<s<<endl;
string n="00";//为便于后面的运算,在得到的二进制编码末尾处添加00
s.append(n);
char a[20]; //定义字符串数组
strcpy(a,s.c_str());//将字符串型转化为成字符数组
int state=0;//表示最初的内态
int i;
string str;
for(i=0;i<20;i++) //对字符串数组进行循环遍历,实现运算指令
{
if(state==0&&a[i]=='0') //实现0 0->0 0 R指令
{
state=0;
a[i]='0';
}
else if(state==0&&a[i]=='1') //实现0 1->1 0 R指令
{
state=1;
a[i]='0';
}
else if(state==1&&a[i]=='0') //实现1 0->0 1 R指令
{
state=0;
a[i]='1';
}
else if(state==1&&a[i]=='1') //实现1 1->10 0 R指令
{
state=10;
a[i]='0';
}
else if(state==10&&a[i]=='0') //实现1 0->11 1 R指令
{
state=11;
a[i]='1';
}
else if(state==11&&a[i]=='0') //实现11 0->0 1 STOP指令
{
state=0;
a[i]='1';
break;
}
}
str = a; //将字符数组转化为string类型
cout<<"扩展后得到的字符串为为"<<":"<<str<<endl;
string_replace(str,"0110",","); //调用string_replace函数,用“,”代替“0110”
string_replace(str,"01","1"); //调用string_replace函数,用“1”代替“01”
string_replace(str,"0","0"); //调用string_replace函数,用“0”代替“0”
cout<<"收缩后得到的字符串为为"<<str<<endl;
int x;
x= atoi(str.c_str()); //将字符型转化为int型
cout<<"图灵机(XN*2)收缩扩展完成后得到的二进制数为:"<<x<<endl;
char d[20];
strcpy(d,str.c_str());//将字符串型转化为成字符数组
}
四、调试、测试及运行结果
- 调试结果:
1.调试过程发现if-else语句中出现错误,经过调试发现其中的0和1是单个字符,需要加上单引号,否则会提示错误
2.调用transform()函数时,输入12,发现t1结果如下图所示。经过检查发现是函数括号里面没有写参数,所以出现了错误。
2)测试结果:
1.测试十进制数转化为二进制数
#include<iostream>
using namespace std;
int transfrom(int x) //将十进制转化为二进制
{
int p=1,y=0,m;
while(1)
{
m=x%2;
x/=2;
y+=m*p;
p*=10;
if(x<2)
{
y+=x*p;
break;
}
}
return y;
}
void main()
{
int m,t1;
cout<<"请输入一个正整数:"<<endl;
cin>>m;
t1=transfrom(m); //调用transform()函数
cout<<"二进制数为:"<<t1<<endl;
}
截图如下所示:
测试得到的二进制编码
#include<iostream>
#include<stdlib.h>
#include <cstring>
#include <sstream>
using namespace std;
int transfrom(int x) //将十进制转化为二进制
{
int p=1,y=0,m;
while(1)
{
m=x%2;
x/=2;
y+=m*p;
p*=10;
if(x<2)
{
y+=x*p;
break;
}
}
return y;
}
void main()
{
int m,t1;
cout<<"请输入一个正整数:"<<endl;
cin>>m;
t1=transfrom(m); //调用transform()函数
ostringstream myos; //将int型转化为字符串型
myos<<t1;
string s=myos.str();
cout<<s<<endl;
string b=","; //定义字符串变量b
s.append(b); //在字符串末尾处添加","
cout<<"该数字对应的二进制数为:"<<s<<endl;
}
截图如下所示:
- 测试图灵机的二进制编码
#include<iostream> #include<stdlib.h> #include <cstring> #include<math.h> #include <sstream> using namespace std; int transfrom(int x) //将十进制转化为二进制 { int p=1,y=0,m; while(1) { m=x%2; x/=2; y+=m*p; p*=10; if(x<2) { y+=x*p; break; } } return y; } void string_replace(std::string &strBig, const std::string &strsrc, const std::string &strdst) //字符串替换函数,通过查资料得到 { std::string::size_type pos=0; std::string::size_type srclen=strsrc.size(); std::string::size_type dstlen=strdst.size(); while( (pos=strBig.find(strsrc, pos)) != std::string::npos) { strBig.replace(pos, srclen, strdst); pos += dstlen; } } void main() { int m,t1; cout<<"请输入一个正整数:"<<endl; cin>>m; t1=transfrom(m); //调用transform()函数 ostringstream myos; //将int型转化为字符串型 myos<<t1; string s=myos.str(); cout<<s<<endl; string b=","; //定义字符串变量b s.append(b); //在字符串末尾处添加"," cout<<"该数字对应的二进制数为:"<<s<<endl; string_replace(s,"1","01"); //调用string_replace函数,用“01”代替“1” string_replace(s,",","0110");//调用string_replace函数,用“0110”代替“,” string_replace(s,"0","0"); //调用string_replace函数,用“0”代替“0”,此步骤可以省略 cout<<"对应的二进制编码为:"<<s<<endl; string n="00";//为便于后面的运算,在得到的二进制编码末尾处添加00 s.append(n); cout<<"图灵机对应的二进制编码为:"<<s<<endl; }截图如下所示:
(其他部分测试不再说明)
(3)运行结果:
五、经验归纳
- 不足:此次图灵机的实验对我来说还是相当有难度的,虽然开始理解了图灵机的思想,但是真正上机实践的时候还是有很多问题。例如十进制和二进制之间的转化,整型,字符型和字符数组之间的转化,字符连接、替换等过程都有或多或少的问题。
- 收获:此次实验我也学到了许多。如:C++中ostringstream myos将int型转化为字符串,s.append(b)连接两个字符串,strcpy(a,s.c_str())将字符串型转化为成字符数组,string_replace(str,"0110",",")实现字符串的替换,atoi(str.c_str())将字符型转化为int型,strcpy(d,str.c_str())将字符串型转化为成字符数组。同样细心还是非常重要的,“==”刚开始写成了“=”出现了错误,经过检查才发现,还有0,1要加单引号等等,只要学习就会有收获,以后还是要多动手,多练习!