UN+1图灵机

本文围绕图灵机UN+1型展开,编程模拟其运行过程。先明确问题,分析图灵机4种运行状态及加1操作实现方式,建立main函数输入二进制字符串。介绍了使用gets函数读取字符串的依据,给出算法实现代码,还分享了调试、测试结果及编程中遇到的问题和解决经验。

图灵机UN+1

  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开始到最后的字符的位置截止。

  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循环写在外面,经运行结果正确。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值