图灵机UN+1
- 问题描述
对人任意给定的一台图灵机和任意给定的字符串w(w不含空格),编程模拟此图灵机的运行过程,要求输出从开始运行起的每一步骤的结果。
2.题目分析
首先确定要编程的是UN+1图灵机的运行过程,理解此种图灵机运行的4种状态。内态为0,输入为0,右移一位,输出及内态均不变。内态为0,输入为1,右移,内态变为1,输出不变。内态输入均为1,右移,其余条件不变。内态为1,输入为0,内态变为0,输入变为1,程序停止。该程序执行结果是在原基础字符串上实现加1操作。
其次建立main函数,输入二进制字符串。由于要求w不含空格,即遇到enter键换行停止,且可以输入任意长度数字,所有可以使用gets函数无限读取,将读取到的字符串输入数组nums,方便在下面执行加1操作时,右移数组下标到下一个字符,判断输入数字。
最后是加1操作的实现,四种状态可以通过if语句判断内态和输入,即数组下标对应数字实现,但由于题目要求输出每一步骤的结果,因此每一个if语句运行后需要一个for循环输出此时的所有字符串。从第一个字符开始每后移一位就是下标+1,所以可再用一个大的for循环,控制下标从1开始到最后的字符的位置截止。
- 算法构造
使用gets函数的依据:
输入字符串时,用到的gets函数可以无限读取,以回车结束。gets函数本身是字符指针,因此要将读取到的字符串存入nums数组,就需要将该数组定义为字符数组。用for循环输入字符串,其中数组下标i的结束范围是数组的长度,gets函数的长度可由strlen求得,即strlen(nums).
4.算法实现
#include < iostream >
using namespace std;
int main()
{
int i,t;
int pos=0;
char nums[20];
cout<<endl;
cout<<“请输入一串二进制数字(不含空格):”;
gets(nums);//读取字符串
cout<<"\n"<<“nums[20]数组是:[ “;
for(i=0;i<strlen(nums);i++)
cout<<nums[i]<<” “;
cout<<”]”;
cout<<endl;
cout<<endl;
//循环输出每一步的所有数据
for(t=0;t<strlen(nums);t++) //注意此处的下标是t<10
{
if(pos==0&&nums[t]==48) //00->00
{
pos=0;
nums[t]='0';
}
if(pos==0&&nums[t]==49) //01->11
{
pos=1;
nums[t]='1';
}
if(pos==1&&nums[t]==49) //11->11
{
pos=1;
nums[t]='1';
}
if(pos==1&&nums[t]==48) //10->01STOP
{
pos=0;
nums[t]='1';
for(i=0;i<strlen(nums);i++)
{
cout<<nums[i]<<" ";
}
cout<<endl;
cout<<endl;
break;
}
for(i=0;i<strlen(nums);i++)
{
cout<<nums[i]<<" ";
}
cout<<endl;
cout<<endl;
}
return 0;
}
5.调试
输入字符串0110到数组:
下标为0,即内态和输入均为0时,输出的内态及数字:
下标为0,进入了第一个if语句后,跳过第二个第三个第四个if语句:
下标为0时,运行的for循环第一次数组输出(后续的110忽略):
下标为1时执行第2个if语句:
下标为3时执行的if语句,实现加1操作:
结束调试环节:
6.测试及运行结果
输入二进制字符串0110,程序运行得出4组数据,最后一组实现加1.
7.经验归纳
本次程序重在掌握图灵机的编码方式,我选择了UN+1的图灵机来编程运行它的结果.
(1).gets函数:字符指针,无限读取字符,以空格结束
strlen:仅是计数器的工作,计算给定字符串的长度
刚开始编写main函数时指定了输入的字符串长度为10,定义了一个整型数组nums来存储字符串。这样可以很简单的将10个数据传入数组中,但无法输入任意位数字符串,并且输入的字符串必须用空格以保证换行继续完成后续操作。后来,由于要求不含空格,只能上网搜索得到gets函数可以满足要求,gets函数无限读取字符,但还是需要一个数组存放字符串,因为后面的for循环需要数组下标完成后移。gets是字符指针,先定义的整型数组nums被换成char型。还是用for循环和strlen(nums)(数组的长度函数)将字符串写入数组。 数组类型的改变要求在后续写好的for循环里所有的数组下标对应的值用字符表示,即数字0或1对应的ASCII值。(数字0对应48,数字1对应49)
(2).输出结果不在指定位置加1,且直接输出最终结果,没有中间具体步骤
for(i=0;i<strlen(nums);i++)
{
cout<<nums[i]<<" ";
}
这是每个if语句中的循环,用来输出每一次运行完判断内态和输出数字过程的所有字符串。特别注意变量是i而不是下标t,否则没办输出该有的数组。这也是导致程序一直无法运行正确结果的原因。问
题很小,但影响很大。也是思路不准确的后果,以后需要注意。
(3).运行结果总是多出1行,内态1输入1的if语句循环出现问题
运行程序时+1操作位置都很正确,就是总会多循环一个语句导致结果多了一行。例如输入字符串01110,正常运行结果应输出5行,第5行输出01111。但程序总是多写一行01110,经检查发现是11->11的if语句循环出现问题,多循环了一次。后来将除了10->01外的其余3种if语句中的for循环写在外面,经运行结果正确。